Android 8.0:使用RSA/ECB/OAEPWithSHA-512AndMGF1Padding时出现IllegalBlocksizeException

Dim*_*tri 10 encryption android rsa padding

我通常会在这里找到大部分问题的答案,但这次我需要问:-).

我们在Android 8.0(API级别26)上运行的某个应用程序中遇到了RSA加密/解密问题.

我们一直在使用带有"RSA/ECB/OAEPWithSHA-256AndMGF1Padding"的RSA,它适用于Android 7.1以上的所有版本.在调用Cipher.doFinal()时,在Android 8.0上运行的相同代码会抛出IllegalBlocksizeException.

以下是重现问题的代码:

private KeyStore mKeyStore;

private static final String KEY_ALIAS = "MyKey";
void testEncryption() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, KeyStoreException, IOException, CertificateException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, UnrecoverableEntryException, NoSuchPaddingException {

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

    // Generate Key Pair -------------------------------------
    KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
    kpg.initialize(new KeyGenParameterSpec.Builder(
            KEY_ALIAS,
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
            .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
            .setKeySize(2048)
            .build());
    KeyPair kp = kpg.generateKeyPair();

    // Encrypt -----------------------------------------------
    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)mKeyStore.getEntry(KEY_ALIAS, null);
    PublicKey publicKey = (PublicKey) privateKeyEntry.getCertificate().getPublicKey();
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    String x = "It doesn't have to be perfect, it's just for demonstration.";

    byte [] vals = cipher.doFinal(x.getBytes("UTF-8"));

    byte[] encryptedBytes = Base64.encode(vals, Base64.DEFAULT);
    String encryptedText = new String(encryptedBytes, "UTF-8");


    // Decrypt -----------------------------------------------
    PrivateKey privateKey = privateKeyEntry.getPrivateKey();

    Cipher output = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    output.init(Cipher.DECRYPT_MODE, privateKey/*, spec */);

    byte[] bxx = Base64.decode(encryptedText, Base64.DEFAULT);
    byte[] bytes = output.doFinal(bxx);  // <= throws IllegalBlocksizeException

    String finalText = new String(bytes, 0, bytes.length, "UTF-8");
}
Run Code Online (Sandbox Code Playgroud)

我也尝试过其他填充算法."RSA/ECB/OAEPWithSHA-1AndMGF1Padding"工作,"RSA/ECB/PKCS1Padding"工作正常.作为一种解决方法,我可以更改填充,但这可能会导致从使用"RSA/ECB/OAEPWithSHA-256AndMGF1Padding"的应用程序的先前版本更新时出现问题,因为无法再读取存储的数据.

有没有人在这里同样的问题,也许一个想法如何修复它而不改变填充?

在此期间感谢汉堡,迪米特里的问候

cra*_*ash 13

2017年9月8日07:08 PM评论#15中描述了一个可能的解决方案:

https://issuetracker.google.com/issues/36708951#comment15

我改变了密码初始化

Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, this.getPrivateKey(context));
Run Code Online (Sandbox Code Playgroud)

OAEPParameterSpec sp = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSource.PSpecified.DEFAULT);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, this.getPrivateKey(context), sp);
Run Code Online (Sandbox Code Playgroud)

我在Android 6上测试了这个到Android 8(模拟器),问题似乎已经消失.您还应该更改Cipher.ENCRYPT_MODE-Implementation.

  • 保存了我的一天,很好的答案,我想应该接受 (2认同)