【问题标题】:Intermittent IllegalBlockSizeException when doing RSA decryption using KeyStore使用 KeyStore 进行 RSA 解密时出现间歇性 IllegalBlockSizeException
【发布时间】:2019-02-24 17:13:31
【问题描述】:

RSA 密钥是使用以下代码生成的:

RSAKeyGenParameterSpec rsaSpec = new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4);
AlgorithmParameterSpec keyPairGeneratorSpec;

KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_DECRYPT)
  .setAlgorithmParameterSpec(rsaSpec)
  .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP, KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
  .setDigests(KeyProperties.DIGEST_SHA256);
keyPairGeneratorSpec = specBuilder.build();

try {
  KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA, ANDROID_KEYSTORE);
  keyPairGenerator.initialize(keyPairGeneratorSpec);
  keyPairGenerator.generateKeyPair();
} catch(Exception e) {
  //handle exception
}

然后使用它在 Java 服务器上远程加密:

Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
cipher.doFinal(data);

然后在设备上,解密是这样完成的:

Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.DECRYPT_MODE, key);
return rsaCipher.doFinal(data);

一小部分时间,解密成功发生,但大多数时候我得到这个异常:

javax.crypto.IllegalBlockSizeException
  at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:519)
  ...
Caused by: android.security.KeyStoreException: Unknown error
  at android.security.KeyStore.getKeyStoreException(KeyStore.java:695)
  at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
  at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
  at javax.crypto.Cipher.doFinal(Cipher.java:1736)
  ...

我在其他几个 SO 答案中发现了这个例外,包括这个:https://stackoverflow.com/a/36020975/6552833,但它似乎并不相关,因为我一开始没有使用 OAEP 加密。

【问题讨论】:

  • 您应该使用 OAEP(最优非对称加密方案)。请参阅 Maarten 的 answer 或 Thomas 的 answer
  • 显示的代码不太可能是错误的来源。该错误很可能是由于用于将加密编码为要发送到对等方的有效负载的代码和/或在尝试解密之前对接收到的数据进行解码。我敢打赌,您在某处将加密的输出错误地视为字符串。

标签: android encryption keystore


【解决方案1】:

我有同样的问题。就我而言,我发现了 2 个原因:

  • 服务器端加密不知何故添加了一个额外的字节,因此加密的 base64 字符串有 257 个字节,而不是密码所期望的 256 个字节。剥离第一个字节使其适用于大多数设备。
  • 清单文件设置 - android: allowsbackup ="true" 导致解密在某些设备上失败(发布版本。调试版本很好)。将此设置为 False 可修复此问题。
<application
android:name=".application.MyApplication"
tools:replace="android:allowBackup"
android:allowBackup="false">

【讨论】:

    猜你喜欢
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 2015-08-03
    相关资源
    最近更新 更多