java - 使用 SHA-256 进行主要和 MGF1 摘要的 OAEP 的 Android RSA 加密
问题描述
根据规范,我需要对两个摘要使用带有 SHA-256 的“RSA/ECB/OAEPPadding”密码 - 主摘要和 MGF1 摘要。
Android Cryptography建议Cipher
像这样初始化:cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
实际上这不起作用,因为init(DECRYPT_MODE, ...)
throws exception: InvalidAlgorithmParameterException, Unsupported MGF1 digest: SHA-256. Only SHA-1 supported
。
有谁知道,如何解决这个问题?在没有选项中使用其他算法参数。
这是代码示例,运行encryptDecrypt()
以重现错误。最低 API 级别为 23。
static void encryptDecrypt()
{
KeyPair keyPair = generateWrappingKeypair("MY_KEY");
try
{
Cipher cipher = getCipher(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] data = new byte[1]; // Just create the smallest data to encrypt
// Encryption goes well
byte[] encrypted = cipher.doFinal(new byte[1]);
// This line throws exception: "InvalidAlgorithmParameterException, Unsupported MGF1 digest: SHA-256. Only SHA-1 supported"
cipher = getCipher(Cipher.DECRYPT_MODE, keyPair.getPrivate());
byte[] decrypted = cipher.doFinal(encrypted);
if (!Arrays.equals(data, decrypted))
{
throw new RuntimeException("Decrypted data is not equals to raw data");
}
}
catch (Exception ex)
{
Log.e(TAG, "Encryption error, exception: " + ex.getClass().getSimpleName() + " " + ex.getMessage());
}
}
static KeyPair generateWrappingKeypair(String aliasOfKey)
{
Calendar dateValidFrom = Calendar.getInstance();
Calendar dateValidTo = Calendar.getInstance();
dateValidTo.add(Calendar.YEAR, 1);
KeyGenParameterSpec specOfKey = new KeyGenParameterSpec.Builder(aliasOfKey, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(4096, RSAKeyGenParameterSpec.F0))
.setKeySize(4096)
.setKeyValidityStart(dateValidFrom.getTime())
.setKeyValidityEnd(dateValidTo.getTime())
.setCertificateSerialNumber(BigInteger.ONE)
.setCertificateSubject(new X500Principal(String.format("CN=%s", aliasOfKey)))
.setDigests(KeyProperties.DIGEST_SHA256) // Setting two SHA256 digests here don't make any difference
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.build();
try
{
KeyPairGenerator generatorOfKeyPairs = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
generatorOfKeyPairs.initialize(specOfKey);
return generatorOfKeyPairs.generateKeyPair();
}
catch (GeneralSecurityException ex)
{
Log.e(TAG, "Cannot generate keypair, exception: " + ex.getClass().getSimpleName() + " " + ex.getMessage());
return null;
}
}
static Cipher getCipher(int operationMode, Key key) throws GeneralSecurityException
{
// AndroidKeyStoreBCWorkaround should be used here from API 23 for Cipher to be compatible with AndroidKeyStore keys
// Any other security provider is not compatible
final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding", "AndroidKeyStoreBCWorkaround");
cipher.init(operationMode, key, new OAEPParameterSpec(KeyProperties.DIGEST_SHA256, "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
return cipher;
}
解决方案
推荐阅读
- r - tidyR 嵌套和完整:避免 group_by (或数据表等价物)
- node.js - 如何将我的节点项目与 Angular 合并?
- python - 如果变量只包含数字,如何知道变量是分类变量还是数值变量?
- android - 底部工作表不出现,留在 Android 中的 ArFragment 后面
- angular - 具有纯打字稿类实例化的同步角度代码
- ios - 使用 swift 更改 uitableView 特定单元格的标签文本
- airflow - 当本地气流.cfg 打包在 zip 文件中时,CodeDeploy 失败
- reactjs - 现在我已经在 IDE 中创建了我的 react 应用程序,我如何让它在 IDE 之外的命令行中工作
- algorithm - 如何构造一个最优的排序函数?
- arrays - 我有一个示例文本文件,我希望我的数据是一个数组并有一个索引