问题描述
我通常会在这里找到大多数问题的答案,但是这次我需要问:-).
I usually find answers for most of our issues here but this time I need to ask :-).
我们在一个运行于Android 8.0(API级别26)的应用中遇到了RSA加密/解密问题.
We have encountered a problem with RSA encryption / decryption in one of our Apps running on Android 8.0 (API level 26).
我们一直在将RSA与"RSA/ECB/OAEPWithSHA-256AndMGF1Padding"一起使用,在所有Android 7.1之前的版本中都可以正常使用.调用Cipher.doFinal()时,在Android 8.0上运行的同一代码会引发IllegalBlocksizeException.
We've been using RSA with "RSA/ECB/OAEPWithSHA-256AndMGF1Padding", which works fine on all versions up to Android 7.1. The same code running on Android 8.0 throws an IllegalBlocksizeException when calling Cipher.doFinal().
以下是重现此问题的代码:
Here is the code to reproduce the issue:
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"的以前版本的应用程序更新时,这可能会导致问题,因为无法再读取存储的数据.
I tried other padding algorithms too. "RSA/ECB/OAEPWithSHA-1AndMGF1Padding" works and also "RSA/ECB/PKCS1Padding" works fine. As a workaround I could change the padding but this might cause problems when updating from a previous version of the App which used "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" because stored data could not be read anymore.
这里有人遇到同样的问题吗,也许有个想法,如何在不更改填充的情况下解决该问题?
Has anybody here the same problem and maybe an idea how to fix it without changing the padding?
在此先感谢汉堡的问候,迪米特里
Thanks in advance and greetings from Hamburg,Dimitri
推荐答案
在2017年9月8日晚上7:08 PM的注释#15中描述了一种可能的解决方案:
A possible solution is described here in the comment #15 from Sep 8, 2017 07:08PM:
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.
I tested this on Android 6 up to Android 8 (emulator) and the issue seems to be gone. You should also change the Cipher.ENCRYPT_MODE-Implementation.
这篇关于使用RSA/ECB/OAEPWithSHA-512AndMGF1Padding时,Android 8.0:IllegalBlocksizeException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!