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

Posted

技术标签:

【中文标题】Android 8.0:使用 RSA/ECB/OAEPWithSHA-512AndMGF1Padding 时出现 IllegalBlocksizeException【英文标题】:Android 8.0: IllegalBlocksizeException when using RSA/ECB/OAEPWithSHA-512AndMGF1Padding 【发布时间】:2018-02-12 23:47:36 【问题描述】:

我通常在这里找到我们大多数问题的答案,但这次我需要问:-)。

我们在 android 8.0(API 级别 26)上运行的一款应用中遇到了 RSA 加密/解密问题。

我们一直在使用带有“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”的 RSA,它在 Android 7.1 之前的所有版本上都可以正常工作。在 Android 8.0 上运行的相同代码在调用 Cipher.doFinal() 时会引发 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");

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

有没有人有同样的问题,也许知道如何在不改变填充的情况下解决它?

提前致谢。

【问题讨论】:

为什么你的标题和问题的正文不同? 嗯?对不起,但这并不完全不同。使用 SHA-256 得到与使用 SHA-512 相同的结果。 是的,我也是。我认为这与AndroidKeyStore有关。如果您不能尽快解决,我会将其作为错误报告发送给 Android。 我们遇到了同样的问题。我们还使用“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”并获得 IllegalBlocksizeException 上述问题您得到解决方案了吗? 【参考方案1】:

2017 年 9 月 8 日晚上 7:08 的评论 #15 中描述了一种可能的解决方案:

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

我将密码初始化从

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

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);

我在 Android 6 到 Android 8(模拟器)上对此进行了测试,问题似乎消失了。您还应该更改 Cipher.ENCRYPT_MODE-Implementation。

【讨论】:

拯救了我的一天,很好的答案,我想它应该被接受 刚在 Android 9 设备上遇到这个问题,而 Android 5 运行良好。非常感谢,拯救了我的一天。 嗨。也许我误解了一些东西,但为什么你为 MGF1ParameterSpec 设置“SHA-1”而不是 SHA-256? @LeandroOcampo KeyStore 使用 SHA-1

以上是关于Android 8.0:使用 RSA/ECB/OAEPWithSHA-512AndMGF1Padding 时出现 IllegalBlocksizeException的主要内容,如果未能解决你的问题,请参考以下文章

Android Check Internet Connection Android 8.0

Android 8.0 应用快捷方式(ShortcutManager)的使用

推送通知未在Android 8.0中使用解析sdk显示

位置侦听器适用于 Android 6.0 但不适用于 android 8.0+ [关闭]

Android学习笔记- ButterKnife 8.0注解使用介绍

Android依赖注入之BufferKnife 8.0注解使用