AES шифрование / дешифрование на Android не запускается - PullRequest
3 голосов
/ 23 марта 2012

Мне нужна помощь по шифрованию / дешифрованию в приложении Android.

Я объясняю ситуацию. Я на самом деле написал приложение, которое использует контент, сгенерированный и зашифрованный приложением iPhone.

А для обеспечения безопасности пользователь предоставляет свою собственную фразу-пароль для правильного шифрования / дешифрования данных между различными платформами ...

Но я придумаю проблему с шифрованием / дешифрованием этой ключевой фразы на Android.

У меня есть две функции:

public byte[] crypt(String pStringToCrypt) throws Exception{

    byte[] key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    System.arraycopy(this.passphrase.getBytes(), 0, key, 0, this.passphrase.getBytes().length);
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(pStringToCrypt.getBytes());
    return encrypted;

}

для шифрования строки, и эта функция:

public String decrypt(byte[] pCryptedStringtoDecrypt) throws Exception{
    byte[] key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    System.arraycopy(this.passphrase.getBytes(), 0, key, 0, this.passphrase.getBytes().length);
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    byte[] encrypted = pCryptedStringtoDecrypt;
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] original = cipher.doFinal(encrypted);
    String originalString = new String(original);
    return originalString;
}

для расшифровки строки.

Когда я использую метод crypt для шифрования данных, у меня нет ошибок, и строка была зашифрована:

encrypted = [26, 119, -108, -24, 81, -128, 18, 35, -96, 10, -38, 69, 111, 40, 109, 107]

Если я попытаюсь преобразовать этот байт в строку, я получу эту строку:

encryptedString = "w��Q�#�\n�Eo(mk"

Я думаю, что фаза шифрования прошла хорошо. Теперь, когда я пытаюсь расшифровать эту зашифрованную строку, происходит сбой приложения:

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
    at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:711)
    at javax.crypto.Cipher.doFinal(Cipher.java:1090)
    at org.vincentsaluzzo.lightrpc.common.security.AES256.decrypt(AES256.java:61)
    at com.vincentsaluzzo.LoginBox.model.SettingsManager.getUserPassphrase(SettingsManager.java:67)
    at com.vincentsaluzzo.LoginBox.mainActivity.onCreate(mainActivity.java:26)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1586)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1638)
    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:3647)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    at dalvik.system.NativeStart.main(Native Method)

И я не понимаю, почему появляется эта ошибка ...

У вас есть какие-нибудь решения? или какое-то объяснение для меня?

Ответы [ 2 ]

2 голосов
/ 25 марта 2012

Хорошо, с помощью всех ваших комментариев я решил свою проблему.

Объясняю.Я преобразовал два моих метода, чтобы сделать их максимально простыми:

public byte[] crypt(byte[] toCrypt) throws Exception {
    byte[] key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    System.arraycopy(this.passphrase.getBytes(), 0, key, 0, ((this.passphrase.getBytes().length < 16) ? this.passphrase.getBytes().length : 16));
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(toCrypt);
    return encrypted;
}

и

public byte[] decryptt(byte[] toDecrypt) throws Exception {
    byte[] key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    System.arraycopy(this.passphrase.getBytes(), 0, key, 0, ((this.passphrase.getBytes().length < 16) ? this.passphrase.getBytes().length : 16));
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] original = cipher.doFinal(toDecrypt);
    return original;
}

Вскоре я удаляю все преобразования в строку в этих методах.И я проверил мои методы в моем другом проекте в Objective-C.Я обнаружил проблему: Encoding String!

Иногда, если я шифрую / дешифрую, я получаю тот же байтовый массив, но иногда массив другой, потому что я храню этот зашифрованный байтовый массив в String в SharedPreference,Конечно, это возможно, но я просто поместил байт в новую строку (байты), и базовая кодировка - UTF-8, так что это проблема.

Я решил это с помощью кодировки base 64.Я использую класс Base64, найденный здесь: http://sourceforge.net/projects/iharder/files/base64/2.3/

и перед сохранением зашифрованного массива байтов в SharedPreferences я кодирую их в кодировку Base64, и то же самое для процесса дешифрования.

0 голосов
/ 25 марта 2012

Как правило, использование getBytes() для преобразования строки в байты в криптографии не очень хорошая вещь. Вы находитесь в зависимости от кодировки символов по умолчанию на вашем компьютере. Намного лучше указать кодировку для шифрования и дешифрования, getBytes("UTF-8")

Вы не показываете вызывающий код, вы уверены, что передаете байтовый массив (encrypted) функции дешифрования, а не строку байтового массива, ваш "w Q # \ n Ео (тк "?

Режим ECB небезопасен и пропускает данные. Для безопасности вам необходимо использовать режим CBC или CTR.

...