Android 与纯 Java 的不同加密 - RSA/ECB/OAEPWithMD5AndMGF1Padding

use*_*721 3 java encryption android

我用公钥加密 Android 中的字符串。但是,当我尝试使用纯 Java 代码中的私钥解密加密字符串时,出现异常“解密错误”。谁能帮忙找出问题所在吗?

Android 代码加密

import android.util.Base64;
public static String encryptMessage(final String plainText, final PublicKey publicKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithAndMGF1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    return Base64.encodeToString(cipher.doFinal(plainText.getBytes()), Base64.NO_WRAP);
}
Run Code Online (Sandbox Code Playgroud)

纯Java代码解密

import java.util.Base64;
public static String decryptMessage(final String encryptedText, final PrivateKey privateKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithAndMGF1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);

    Base64.Decoder decoder = Base64.getDecoder();
    byte[] byteArray = decoder.decode(encryptedText);
    byte[] decryptedArray = cipher.doFinal(byteArray);  // throw exception here
    String plainText = new String(decryptedArray);
    return plainText;
}
Run Code Online (Sandbox Code Playgroud)

您可能会注意到我必须在 Android 和纯 Java 中使用不同的 Base64 API。我尝试了“RSA/ECB/PKCS1Padding”,它可以正确解密,没有异常。也尝试过“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”,但得到了相同的异常。

Top*_*aco 5

OAEP 使用两种摘要,一种用于 OAEP 标签,另一种作为 MGF1 的基础,请参阅 RFC 8017, 7.1。RSAES-OAEPB.1。散列函数B.2。掩模生成函数

导致此问题的原因是 OP 代码两侧使用的提供程序(Android/API 级别 28 和 Java 8)对OAEPWithMD5AndMGF1Padding.

双方的相关参数(提供者、OAEP 摘要、MGF、MGF1 摘要)可以在密码初始化后确定,例如:

OAEPParameterSpec parameterSpec = cipher.getParameters().getParameterSpec(OAEPParameterSpec.class);
System.out.println("Provider: " + cipher.getProvider().getName());          
System.out.println("OAEP digest: " + parameterSpec.getDigestAlgorithm());  
System.out.println("OAEP MGF : " + parameterSpec.getMGFAlgorithm());        
System.out.println("OAEP MGF1 digest: " + ((MGF1ParameterSpec)parameterSpec.getMGFParameters()).getDigestAlgorithm()); 
Run Code Online (Sandbox Code Playgroud)

这样,MD5 在 Android 端被确定为 MGF1 摘要,在 Java 端被确定为 SHA-1。双方都使用 MD5 作为 OAEP 摘要。如果显式设置摘要OAEPParameterSpec以便双方使用相同的摘要,则可以解决此问题。

例如,Java端的以下代码确保MD5用作OAEP和MGF1摘要,类似于Android端。

OAEPParameterSpec oaepParameterSpecDec = new OAEPParameterSpec("MD5", "MGF1", new MGF1ParameterSpec("MD5"), PSource.PSpecified.DEFAULT);
cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParameterSpecDec);
Run Code Online (Sandbox Code Playgroud)

这同样适用于OAEPWithSHA-256AndMGF1Padding.

另请注意 B.1 中的 RFC 8017 。哈希函数建议 RSAES-OAEP 使用 SHA-1 和 SHA-2,但不建议使用MD5。