0

I'm using this library to save an username and password encrypted to SharedPreferences (pretty sure no app can access my SharedPreferences, but anyway this is a requirement).

I did this code, because I also need to use my own IV and key:

public class EncryptionHandler {
    private final static String PREFS_FILE_NAME = "SAVED_CREDENTIALS";
    private final static String MSG_FORMAT = "%s;%s";

    public static void saveCredentials(Context context, String username, String password) {
        try {
            String formattedMsg = String.format(MSG_FORMAT, username, password);

            String encryptedMsg = new String(AESCrypt.encrypt(getKeySpec(), getIV(), stringToBytes(formattedMsg)));

            //save encryptedMsg to SharedPreferences
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static byte[] stringToBytes(String msg) {
        return msg.getBytes(Charset.forName("UTF-8"));
    }

    public static LoginCredentials getSavedCredentials(Context context) {
        try {
            String encryptedMsg = getSharedPreferences(context).getString(PREFS_FILE_NAME, "");
            String messageAfterDecrypt = new String(AESCrypt.decrypt(getKeySpec(), getIV(), stringToBytes(encryptedMsg)));

            String[] split = messageAfterDecrypt.split(";");

            //irrelevant code

            return credentials;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static byte[] ivBytes = {0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x52, 0x00, 0x00, 0x00, 0x00};

    private static SecretKeySpec secretKeySpec = new SecretKeySpec(ivBytes, "AES");

    private static SecretKeySpec getKeySpec() throws Exception {
        return secretKeySpec;
    }

    private static byte[] getIV() {
        return ivBytes;
    }
}

Related questions suggest to use Base64, but I really need to use AESCrypt (it's already working on the iOS app so I have to make the same).

The exception I get is:

javax.crypto.IllegalBlockSizeException: error:1e06b07b:Cipher functions:EVP_DecryptFinal_ex:WRONG_FINAL_BLOCK_LENGTH
    at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
    at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:568)
    at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:350)
    at javax.crypto.Cipher.doFinal(Cipher.java:1502)
    at com.scottyab.aescrypt.AESCrypt.decrypt(AESCrypt.java:158)
    at com.mypackage.encryption.EncryptionHandler.getSavedCredentials(EncryptionHandler.java:48)

The exception happens in this line, when I'm trying to read and decrypt:

String messageAfterDecrypt = new String(AESCrypt.decrypt(getKeySpec(), getIV(), stringToBytes(encryptedMsg)));

Edit:

I understood that doing new String(someBytes) doesn't make sense, so I also tried converting the bytes to Base64:

public static void saveCredentials(Context context, String username, String password) {
    try {
        String formattedMsg = String.format(MSG_FORMAT, username, password);
        byte[] bytes = stringToBytes(formattedMsg);
        byte[] encryptedBytes = AESCrypt.encrypt(getKeySpec(), getIV(), bytes);
        String encryptedMsg = Base64.encodeToString(encryptedBytes, Base64.NO_WRAP);

        //save to sharedpreferences
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static byte[] stringToBytes(String msg) {
    byte[] bytes = msg.getBytes(Charset.forName("UTF-8"));

    return bytes;
}

public static LoginCredentials getSavedCredentials(Context context) {
    try {
        String base64Msg = getSharedPreferences(context).getString(PREFS_FILE_NAME, "");
        byte[] bytes = Base64.decode(base64Msg, Base64.NO_WRAP);
        byte[] decryptedBytes = AESCrypt.decrypt(getKeySpec(), getIV(), bytes);

        String messageAfterDecrypt = ????;

        //...
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

I don't get errors but I don't know how to get the final, decrypted message (line String messageAfterDecrypt = ????;)

Community
  • 1
  • 1
RominaV
  • 3,335
  • 1
  • 29
  • 59
  • Could you let us know which line `EncryptionHandler.java:48` is? – Matt Clark Nov 24 '16 at 04:24
  • 1
    @MattClark edited the question. Thanks! – RominaV Nov 24 '16 at 04:27
  • This line is your real problem: `String encryptedMsg = new String(AESCrypt.encrypt(getKeySpec(), getIV(), stringToBytes(formattedMsg)));` String is not a container for arbitrary byte sequences. If you must have a String result then you need to base64 encode the `byte[]` returned from AESCrypt.encrypt() – President James K. Polk Nov 24 '16 at 04:43
  • @JamesKPolk I'm trying that approach now. I edited the question, in case you can help me in that final step that would be great, thanks! – RominaV Nov 24 '16 at 05:20
  • @JamesKPolk I used `new String(decryptedBytes, "UTF-8");` , and it works. But is it the right way to do it? – RominaV Nov 24 '16 at 06:25
  • 1
    You can perform *character-encoding/decoding on the plaintext (i.e. the decrypted bytes) without any problems. The problem occurred when you presumed a certain character-encoding on the *ciphertext*, the encrypted byte array. You need to use (binary to text) encoding such as base 64 for that if you need a string. – Maarten Bodewes Nov 28 '16 at 20:01
  • post a solution if found @RominaV – Amit Vaghela Aug 02 '18 at 10:46
  • @AmitVaghela my last comment is what I ended up using (from what I can remember) `new String(decryptedBytes, "UTF-8");` – RominaV Aug 09 '18 at 23:42
  • but @RominaV it sometimes gives same error. i have used that. – Amit Vaghela Aug 10 '18 at 04:59

0 Answers0