使用SHAEP-256对主要摘要和MGF1摘要进行OAEP的Android RSA加密

时间:2019-10-09 20:26:07

标签: java android encryption cryptography rsa

根据规范,我需要对两种摘要(主摘要和MGF1摘要)均使用带有SHA-256的“ RSA / ECB / OAEPPadding”密码。

Android Cryptography建议像这样初始化Ciphercipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT)); 实际上,这是行不通的,因为init(DECRYPT_MODE, ...)抛出异常: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;
}

0 个答案:

没有答案