Android: шифрование и дешифрование AES с использованием режима GCM в Android?

Я пытаюсь зашифровать и расшифровать строку, используя алгоритм AES и режим GCM.

Мой код может зашифровать строку, но я не могу расшифровать закодированные данные.

Последующие шаги:

  • Создать ключ ()
  • Зашифровать (строка)
  • Расшифровать (encded_data);

Мой код:

Создать ключ

public void createKey() {
    try {
        if (!ks.containsAlias(keyName)) {

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                Log.e("MAinAcvtivity", "Current version is 23(MashMello)");
                //Api level 23
                KeyGenerator generator  = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
                generator.init(
                        new KeyGenParameterSpec.Builder(keyName,
                                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                .build());
                SecretKey key = generator.generateKey();

            } else {
                Log.e("MAinAcvtivity", "Current version is < 23(MashMello)");

            }

        }else{
            Log.e("MAinAcvtivity", "Key exist");
        }
    } catch (Exception e) {

        Log.e("MAinAcvtivity", "Key didn't generated");
        Log.e("MAinAcvtivity", Log.getStackTraceString(e));
    }
}

Шифрование:

public String doEncryption(String data) {
    try {

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            ce = Cipher.getInstance("AES/GCM/NoPadding");
            sKey = (SecretKey) ks.getKey(keyName, null);
            ce.init(Cipher.ENCRYPT_MODE, sKey);
        } else {

        }

        encodedData = ce.doFinal(data.getBytes());
        mEncodedData = Base64.encodeToString(encodedData, Base64.DEFAULT);
    } catch (Exception e) {
        Log.e("Main", "RSA Encription Error.!");
        Log.e("MainActivity", "RSA Decryption Error.!", e);
    }
    Log.e("Main", "encripted DATA =" + mEncodedData);
    return mEncodedData;
}

Расшифровка:

public String doDecryption(String eData) {
    String decryptedText = null;
encodedData = Base64.decode(eData, Base64.DEFAULT);

    try {
        Cipher c;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            Log.i("MainActivity","in Decryption version m");

            c = Cipher.getInstance("AES/GCM/NoPadding");
            sKey = (SecretKey) ks.getKey(keyName, null);
            Log.e("MainActivity", "After getting key : " );
            c.init(Cipher.DECRYPT_MODE, sKey);
        } else {

        }

        decodedData = c.doFinal(encodedData);
        decryptedText = new String(decodedData, "UTF-8");
        Log.e("MainActivity", "After decryption : "+ decryptedText);
    } catch (Exception e) {
        Log.e("MainActivity", "RSA Decryption Error.!", e);
    }
    return decryptedText;
}

Журнал ошибок:

MAinAcvtivity: Key exist
Main: encripted DATA =KrHmMXhcytb0owDzLaMY2wsQmwY=
MainActivity: in decryption : encoded data =KrHmMXhcytb0owDzLaMY2wsQmwY=
MainActivity: After getting key : 
MainActivity: RSA Decryption Error.!
MainActivity: java.security.InvalidKeyException: IV required when     decrypting. Use IvParameterSpec or AlgorithmParameters to provide it.
MainActivity:     at android.security.keystore.AndroidKeyStoreAuthenticatedAESCipherSpi$GCM.initAlgorithmSpecificParameters(AndroidKeyStoreAuthenticatedAESCipherSpi.java:79)
MainActivity:     at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:106)

person Uday    schedule 30.11.2015    source источник
comment
ce.getIV()   -  person Artjom B.    schedule 30.11.2015


Ответы (2)


Бингоу!

Я нашел решение.

При расшифровке я внес следующие изменения:

 GCMParameterSpec spec = new GCMParameterSpec(128,ce.getIV());
 c.init(Cipher.DECRYPT_MODE, sKey,spec);
person Uday    schedule 30.11.2015
comment
Почему 128 - единственная длина? - person IgorGanapolsky; 27.05.2018
comment
128, потому что в спецификации GCM указано, что tLen может иметь значения {128, 120, 112, 104, 96} или {64, 32} только для определенных приложений. developer.android.com/reference/javax/crypto/spec/ - person Tushar Bapte; 12.06.2020

Это код расчета размера тегов, который я использовал для режима AES / GCM. Я не предпочитаю статическое использование.

byte[] pinBytes = pin.getBytes();
byte[] bytes = cipher.doFinal(pinBytes);
tagLenght= bytes.length - pin.length;
person atasoyh    schedule 23.06.2016
comment
Где ваш cipher.init? - person IgorGanapolsky; 27.05.2018