java - 使用带有 PKCS1 填充的 RSA 进行加密时,C# 和 Java (Android) 有什么区别?
问题描述
我在Java(Android)中使用带有PKCS1填充的RSA加密文本,之后我必须将其作为Web服务中正文的一部分发送。我的 Java 代码的输出不起作用,但如果我在 C# 中执行,技术上相同的算法,那么它可以正常工作。
这是运行良好的C#代码:
static void Main(string[] args)
{
var plainData = "plain_text";
RSA publicKeyEncryptor = getRSAPublic(@"<public_key>");
var plainBytes = Encoding.ASCII.GetBytes(plainData);
string encryptedPayload = System.Convert.ToBase64String(publicKeyEncryptor.Encrypt(plainBytes, RSAEncryptionPadding.Pkcs1));
Console.WriteLine(encryptedPayload);
}
public static RSA getRSAPublic(string publicKey)
{
string publicKeyPem = $"-----BEGIN PUBLIC KEY-----\r\n{ publicKey }\r\n-----END PUBLIC KEY-----\r\n";
var pemReader = new PemReader(new StringReader(publicKeyPem));
AsymmetricKeyParameter keyPairRaw = (AsymmetricKeyParameter)pemReader.ReadObject();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)keyPairRaw);
RSA rsaObj = System.Security.Cryptography.RSA.Create();
rsaObj.ImportParameters(rsaParams);
return rsaObj;
}
当我尝试将其转换为Java (Android) 时,这是我想出的代码,但它不会生成有效的输出:
public static void main(String args[]) {
String stringToEncrypt = "plain_text";
String publicKey = "<public_key>";
System.out.println(encrypt(stringToEncrypt, publicKey))
}
public String encrypt(String plain, String publicKey) {
try {
byte[] keyBytes = Base64.decode(publicKey, Base64.DEFAULT);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
PublicKey rsaPublicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
byte[] plainTextBytes = plain.getBytes(Charset.forName("US-ASCII"));
byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
return Base64.encodeToString(encryptedBytes, Base64.NO_WRAP));
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
有什么不同?
谢谢!
解决方案
Java 和 C# 程序都产生兼容的输出。兼容,但不完全相同,因为输出应该每次都不同。出于安全原因,PKCS1 填充包含一个随机组件。因此,如果您期望相同的输出,那么您的期望是错误的。相同的输出将是出现问题的线索,输出应该每次都不同。
RFC 8017,第 7.2.1 节详细解释了正在发生的事情。特别是,步骤 2a 说:
生成长度为 k - mLen - 3 的八位字节字符串 PS,由伪随机生成的非零八位字节组成。PS 的长度至少为八个八位字节。
只是为了验证它们的兼容性,我根据您的代码编写了小型 C# 和 Java 程序,发现它们都可以解密对方的输出并得到正确的结果。
推荐阅读
- python - 最小化python目录/模块
- spring - Spring注册后通过电子邮件发送激活码
- spring - 带有 Azure AD 的 Spring MVC 框架
- dynamics-crm - 无法提取没有使用 CRM SDK FetchXML 绑定的帐户的联系人
- python - 如何处理tensorflow中的数据大小错误
- flutter - Flutter - 在 PageView 中传递数据
- android - Gradle 同步在 Windows 10 上的 Android Studio 4、0、1 中失败
- javascript - 在反应中使用功能显示通知/模式
- javascript - 我们如何使用 for 循环初始化多个变量?
- excel - 从动态表中提取信息到静态稳定