InvalidKeyException: сбой операции хранилища ключей при расшифровке RSA на устройстве Android

Я пытаюсь выполнить шифрование и дешифрование RSA для ключа, находящегося в AndroidKeyStore. Шифрование завершается успешно, но когда я пытаюсь расшифровать, возникает исключение InvalidKeyException: операция хранилища ключей завершилась неудачно для Cipher.init ().

Вот мой код генерации ключей:

KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
AlgorithmParameterSpec spec = null;
spec = new KeyGenParameterSpec.Builder(mAlias,
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
        .build();
kpGenerator.initialize(spec);
KeyPair kp = kpGenerator.generateKeyPair();

Вот мой код шифрования:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(mAlias, null);
Cipher cip = null;
RSAPublicKey pubKey = (RSAPublicKey) entry.getCertificate().getPublicKey();
cip = Cipher.getInstance("RSA/ECB/NoPadding");
cip.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] encryptBytes = cip.doFinal(challenge.getBytes());
String encryptedStr64 = Base64.encodeToString(encryptBytes, Base64.DEFAULT);

Вот мой код расшифровки:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(mAlias, null);
Cipher cip = null;
cip = Cipher.getInstance("RSA/ECB/NoPadding");
cip.init(Cipher.DECRYPT_MODE, entry.getPrivateKey());
byte[] decryptedBytes = cip.doFinal(Base64.decode(encrypted64, Base64.DEFAULT));
String plainText = new String(decryptedBytes);

Я знаю, что заполнение кода генерации ключа отличается от моего кода шифрования / дешифрования. Однако, когда я меняю заполнение кода генерации ключа на KeyProperties.ENCRYPTION_PADDING_NONE, вместо этого я получаю InvalidAlgorithmParameterException в kpGenerator.initialize (spec). При расшифровке «RSA / ECB / PKCS1Padding» все работает. Независимо от заполнения в encrypt, он всегда работает.

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

Вот трассировка стека с InvalidKeyException:

03-06 09:10:32.710  5058  5058 W System.err: java.security.InvalidKeyException: Keystore operation failed
03-06 09:10:32.713  5058  5058 W System.err:    at android.security.KeyStore.getInvalidKeyException(KeyStore.java:692)
03-06 09:10:32.713  5058  5058 W System.err:    at android.security.KeyStore.getInvalidKeyException(KeyStore.java:712)
03-06 09:10:32.713  5058  5058 W System.err:    at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
03-06 09:10:32.713  5058  5058 W System.err:    at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
03-06 09:10:32.713  5058  5058 W System.err:    at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:263)
03-06 09:10:32.713  5058  5058 W System.err:    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:108)
03-06 09:10:32.713  5058  5058 W System.err:    at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:612)
03-06 09:10:32.713  5058  5058 W System.err:    at javax.crypto.Cipher.tryCombinations(Cipher.java:532)
03-06 09:10:32.714  5058  5058 W System.err:    at javax.crypto.Cipher.getSpi(Cipher.java:437)
03-06 09:10:32.714  5058  5058 W System.err:    at javax.crypto.Cipher.init(Cipher.java:815)
03-06 09:10:32.714  5058  5058 W System.err:    at javax.crypto.Cipher.init(Cipher.java:774)
03-06 09:10:32.714  5058  5058 W System.err:    at dfpidentifiers.my.test.app.MainActivity.decrypt(MainActivity.java:950)
03-06 09:10:32.714  5058  5058 W System.err:    at dfpidentifiers.my.test.app.MainActivity.onCreate(MainActivity.java:117)
03-06 09:10:32.714  5058  5058 W System.err:    at android.app.Activity.performCreate(Activity.java:6251)
03-06 09:10:32.714  5058  5058 W System.err:    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
03-06 09:10:32.714  5058  5058 W System.err:    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
03-06 09:10:32.714  5058  5058 W System.err:    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
03-06 09:10:32.714  5058  5058 W System.err:    at android.app.ActivityThread.-wrap11(ActivityThread.java)
03-06 09:10:32.714  5058  5058 W System.err:    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
03-06 09:10:32.714  5058  5058 W System.err:    at android.os.Handler.dispatchMessage(Handler.java:102)
03-06 09:10:32.714  5058  5058 W System.err:    at android.os.Looper.loop(Looper.java:148)
03-06 09:10:32.714  5058  5058 W System.err:    at android.app.ActivityThread.main(ActivityThread.java:5417)
03-06 09:10:32.714  5058  5058 W System.err:    at java.lang.reflect.Method.invoke(Native Method)
03-06 09:10:32.714  5058  5058 W System.err:    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
03-06 09:10:32.714  5058  5058 W System.err:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
03-06 09:10:32.714  5058  5058 W System.err: Caused by: android.security.KeyStoreException: Incompatible padding mode
03-06 09:10:32.714  5058  5058 W System.err:    at android.security.KeyStore.getKeyStoreException(KeyStore.java:632)
03-06 09:10:32.714  5058  5058 W System.err:    ... 24 more

Судя по трассировке стека, это несовместимый режим заполнения, но как мне сгенерировать пару ключей, которая не поддерживает заполнение?


person user1118764    schedule 03.03.2017    source источник
comment
Не могли бы вы выложить полную трассировку стека?   -  person Maarten Bodewes    schedule 03.03.2017
comment
Обратите внимание, что детерминированная асимметричная криптография обычно считается запретной областью; злоумышленник может просто попытаться зашифровать несколько сообщений, чтобы найти одно, соответствующее вашему зашифрованному тексту. Если у вас уже есть достаточно случайных байтов в сообщении, я бы подумал о расширении его до полного размера модуля (-1 старший бит), например, HKDF или XOF и RSA шифруют это значение. Затем вы можете снова использовать HKDF для получения симметричного ключа из значения (до шифрования / после дешифрования) и, наконец, использовать его для шифрования зашифрованного текста, например, AES-GCM.   -  person Maarten Bodewes    schedule 03.03.2017
comment
Возможно, вам нужно передать обработчик обратного вызова для пароля. Если это ваша проблема, позвольте мне ответить на вопрос; без трассировки стека или хранилища ключей мы не можем проверить какие-либо решения.   -  person Maarten Bodewes    schedule 03.03.2017
comment
Я добавил трассировку стека.   -  person user1118764    schedule 06.03.2017


Ответы (1)


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

Я также изначально не мог использовать NoPadding во время генерации ключей, так как требуется IND-CPA. Мне нужно установить setRandomizedEncryptionRequired (true), чтобы переопределить это.

person user1118764    schedule 06.03.2017
comment
Спасибо за ответ! - person Maarten Bodewes; 10.03.2017
comment
Вы имеете в виду - вам нужно было установить setRandomizedEncryptionRequired(false) для использования NoPadding, верно? - person Ωmega; 21.03.2018