2017-03-03 484 views
1

我试图对AndroidKeyStore中的密钥执行RSA加密和解密。加密成功完成,但是当我尝试解密时,它会抛出一个InvalidKeyException:密钥库操作在Cipher.init()上失败。InvalidKeyException:在Android设备上进行RSA解密时密钥库操作失败

这里是我的keygeneration代码:

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时,我在kpGenerator.initialize(spec)上得到了一个InvalidAlgorithmParameterException。 使用“RSA/ECB/PKCS1Padding”进行解密,它可以工作。无论在加密填充,它始终工作。

是的,我也意识到使用无填充的安全含义,但对于我的应用程序,我需要一个确定性的密文。

下面是与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 

从堆栈跟踪,这似乎是一个不兼容的填充模式,但如何生成支持不填充一个密钥?

+0

请问您可以发布完整的stacktrace吗? –

+1

请注意,确定性非对称密码通常被认为是不可行区域;攻击者可以简单地尝试加密几条消息以找到与你的密文相匹配的消息。如果在消息中已经有足够的随机字节,那么我会考虑使用例如扩展它到全模数大小(-1最高有效位)。 HKDF或XOF和RSA加密此值。然后,你可以再次使用HKDF从该值(在加密之前/解密之后)导出一个对称密钥,并最终用它来用例如密文对密文进行加密。 AES-GCM。 –

+0

也许你需要传递密码的回调处理程序。如果这是你的问题,请允许我回答这个问题;没有堆栈跟踪或密钥存储,我们无法验证任何解决方案。 –

回答

2

InvalidKeyException实际上是由密钥生成和解密期间的填充差异引起的。不知道为什么加密不会抛出相同的异常。

由于IND-CPA是必需的,因此我最初无法在密钥生成期间使用NoPadding。我必须设置setRandomizedEncryptionRequired(true)来覆盖这个。

+0

感谢您报告回来! –