Android String Encryption / Decryption - PullRequest
       23

Android String Encryption / Decryption

0 голосов
/ 03 июня 2019

Я хочу зашифровать и расшифровать String из EditText, используя AndroidKeyStore. Моя проблема в том, что в процессе расшифровки получить BadPaddingException.

Код генератора ключей:

        KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

        KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).
                setBlockModes(KeyProperties.BLOCK_MODE_GCM).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE).build();

        keyGenerator.init(keyGenParameterSpec);
        keyGenerator.generateKey();

Код шифрования:

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);

            KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null);
            SecretKey secretKey = secretKeyEntry.getSecretKey();

            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            cipherIV = cipher.getIV();

            plainText.setText(new String(cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));

Код расшифровки:

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);

            final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null);
            final SecretKey secretKey = secretKeyEntry.getSecretKey();

            final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            final GCMParameterSpec spec = new GCMParameterSpec(128, cipherIV);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);

            byte[] decrypted = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
            plainText.setText(new String(decrypted, StandardCharsets.UTF_8));

Ответы [ 2 ]

0 голосов
/ 03 июня 2019

Ошибка в этой строке:

plainText.setText(new String(cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));

Если мы разобьем его на части, у нас будет что-то вроде

byte [] cipherBytes = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
plainText.setText(new String(cipherBytes, StandardCharsets.UTF_8);

Проблема в том, что cipherBytes - это последовательность произвольных байтов, а не символов строки. Конструктор String будет молча заменять недопустимые символы чем-то другим, процесс, который портит данные.

Если вы хотите отобразить байты шифра или иным образом отправить его в символьно-ориентированный канал, вы должны кодировать его. Обычно кодировки являются base64 или hex. Чтобы расшифровать строку, вы должны сначала декодировать ее в байты, а затем расшифровать.

Пример:

byte [] cipherBytes = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
plainText.setText(Base64.encodeToString(cipherBytes, Base64.DEFAULT));

А при расшифровке:

byte[] cipherBytes = Base64.decode(plainText.getText().toString(), Base64.DEFAULT);
byte[] decrypted = cipher.doFinal(cipherBytes);
0 голосов
/ 03 июня 2019
byte[] decrypted = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));

Эта строка может не работать должным образом из-за вызова getBytes(StandardCharsets.UTF_8).Если ваш EditText является шестнадцатеричным представлением, попробуйте преобразовать его в строку и затем вызовите getBytes().Например,

public static byte[] convertHexStringToByteArray(String hexString) {

    int l = hexString.length();
    byte[] data = new byte[l/2];
    for (int i = 0; i < l; i += 2) {
        data[i/2] = (byte)((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16));
    }

    return data;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...