2017-09-04 106 views
4

我通常在这里找到我们大多数问题的答案,但这次我需要问:-)。Android 8.0:IllegalBlocksizeException当使用RSA/ECB/OAEPWithSHA-512AndMGF1Padding

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

我们一直在使用RSA与“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”,它适用于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”的应用的先前版本进行更新时,这可能会导致问题,因为存储的数据无法再读取。

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

提前感谢和问候来自汉堡, 迪米特里

+0

为什么你的标题说了一些与问题主体不同的东西? –

+0

嗯?对不起,但它并没有完全不同。 SHA-256的结果与SHA-512的结果相同。 – Dimitri

+0

是的,我也是。我认为它与AndroidKeyStore有关。如果你不能很快弄清楚,我会把它作为一个错误报告发送给Android。 –

回答

5

一个可能的解决方案,从9月8日在这里描述的意见#15,2017年下午7时08分:

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(模拟器)上测试了这个,并且问题似乎消失了。您还应该更改Cipher.ENCRYPT_MODE-Implementation。