我通常会在这里找到我们大部分问题的答案,但这次我需要问:-)。
我们在Android 8.0(API级别26)上运行的一个应用程序中遇到了RSA加密/解密问题。
我们一直在将RSA与“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”一起使用,这在Android 7.1之前的所有版本上都能正常工作。在Android 8.0上运行的同一代码在调用Cipher时引发了非法BlockSizeException。doFinal()。
以下是重现问题的代码:
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/OAEPWITHHA-1和MGF1填充”工作正常,“RSA/ECB/PKCS1Padding”工作正常。作为一种解决方法,我可以更改填充,但这可能会导致从使用“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”的应用程序的早期版本更新时出现问题,因为存储的数据无法再读取。
有人有同样的问题,也许知道如何在不改变衬垫的情况下修复它?
提前谢谢。
9月8, 2017 07: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(emulator)上进行了测试,问题似乎已经解决了。你还应该更改密码。ENCRYPT\u模式实现。
问题内容: 我在Oracle的Java标准加密提供程序中发现了困难的方法 使用以SHA-1实例化的MFG1;SHA-256仅用于对标签进行哈希处理(实际上是空的)。我发现在MFG1中实际使用SHA-256的唯一解决方案(得到该答案和注释的帮助)是使用以下替代形式Cipher.init: 问:有没有转变是会认识到,与类似的效果,除了与MGF1使用SHA-256? 问题答案: 不,没有。 Java是开
问题内容: 我的应用程序正在访问e-Token来解密来自服务器的响应 来自服务器的会话密钥使用以下方法加密: RSA / ECB / OAEPWITHSHA-256ANDMGF1PADDING 我正在使用SunPKCS11 Provider来实现对加密令牌的访问。每当我尝试使用上述机制解密此文件时,即使用 RSA / ECB / OAEPWITHSHA-256ANDMGF1PADDING, 我都会
问题内容: Java有一种称为的模式。那有什么意思? RFC3447, 公开密钥密码标准(PKCS)#1:RSA密码规范2.1版 ,第 7.1.2 节 解密操作 说,哈希和MGF都是RSAES-OAEP- DECRYPT的选项。MGF是它自己的功能,在 B.2.1节MGF1中 定义,并且还具有自己的哈希“选项”。 也许RSAES-OAEP- DECRYPT和MGF1中的哈希“选项”应该是相同的,或
首先,我对加密/签名还是新手,所以请容忍任何滥用术语的行为。 我需要在C#中创建一个签名,该签名将被Python库验证。在Python中,解码/验证签名只需一段简单的代码: 我当前的C#代码如下所示: 但是,签名在Python代码中未通过验证检查。它看起来像PSS填充。Net库默认使用MGF1。然而,我相信我有问题,因为掩码生成函数(MGF1)在Python代码中使用256位哈希,但在C#中默认为
问题内容: 数据解密将使用算法在JAVA中运行。因此,我必须使用等效于中的算法使用公开密钥加密数据。 我尝试使用与上面的算法不相似的crypto.constants.RSA_PKCS1_OAEP_PADDING。所以我需要等效于“ RSA / ECB / OAEPWithSHA-256AndMGF1Padding”的算法,或者如何在node.js中实现相同的算法 问题答案: 我终于找到了答案。可以