简体   繁体   English

使用带有PKCS1填充的RSA加密时,C#和Java(Android)有什么区别?

[英]What are the differences between C# and Java (Android) when encrypting using RSA with PKCS1 padding?

I'm encrypting a text using RSA with PKCS1 padding in Java (Android), that I have to send afterwards as part of the body in a webservice. 我正在使用RSA和Java(Android)中的PKCS1填充来加密文本,之后必须将其作为Web服务主体的一部分发送。 The output of my Java code doesn't work, but if I do it in C#, technically the same algorithm, then it works fine. 我的Java代码的输出不起作用,但是如果我在C#中使用技术上相同的算法,那么它可以正常工作。

This is the C# code that works fine: 这是可以正常工作的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;
    }

When I try to convert it to Java (Android), this is the code I came up with, but it doesn't generate a valid output: 当我尝试将其转换为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 "";
}

What can be different? 有什么不同?

Thanks! 谢谢!

Both the Java and the C# program produce compatible output. Java和C#程序均产生兼容的输出。 Compatible, but not identical, because the output is supposed to be different every time. 兼容,但不完全相同,因为每次输出都应该不同。 PKCS1 padding includes a random component for security reasons. 出于安全原因,PKCS1填充包含随机成分。 Thus, if you were expecting identical output your expectations were wrong. 因此,如果您期望相同的输出,则您的期望是错误的。 Identical output would be a clue that something was wrong, the output is supposed to be different every time. 相同的输出可能表明出了点问题,每次输出都应该不同。

RFC 8017, section 7.2.1 explains in detail what is happening. RFC 8017的7.2.1节详细说明了正在发生的事情。 In particular, step 2a says: 特别是,步骤2a表示:

Generate an octet string PS of length k - mLen - 3 consisting of pseudo-randomly generated nonzero octets. 生成长度为k-mLen-3的八位字节串PS,该字符串由伪随机生成的非零八位字节组成。 The length of PS will be at least eight octets. PS的长度至少为八个八位位组。

Just to verify their compatibility, I made up small C# and Java programs based on your code and found that each could decrypt the other's output and get the correct result. 为了验证它们的兼容性,我根据您的代码组成了小型C#和Java程序,发现每个程序都可以解密对方的输出并获得正确的结果。

Both codes are right. 两种代码都是正确的。 You can encrypt data in same way with Java version and C# version. 您可以使用Java版本和C#版本以相同的方式加密数据。 If one of them is working and another one is failing, probably you are using an incorrect public key (copy/paste error, some different bytes, etc...) 如果其中一个正在工作而另一个在失败,则可能是您使用了不正确的公钥(复制/粘贴错误,一些不同的字节等)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Java中使用给定的公钥以rsa / ecb / pkcs1填充模式编码文本? - How to encode a text with rsa/ecb/pkcs1 padding mode with a given public key in java? 在C#中使用RSA加密和在Java中使用解密时出现填充错误 - Padding error when using RSA Encryption in C# and Decryption in Java Pycrypto RSA PKCS1 OAEP SHA256 与 Java 的互操作性 - Pycrypto RSA PKCS1 OAEP SHA256 Interoperability with Java 将 RSA PKCS1 私钥字符串转换为 Java PrivateKey 对象 - Convert an RSA PKCS1 private key string to a Java PrivateKey object 在JAVA中读取格式为PKCS1的RSA私钥 - Read RSA private key of format PKCS1 in JAVA 使用RSA / ECB / PKCS1padding的Android加密问题。 它在Java和Android中给出不同的结果 - Issue in Android Encryption using RSA/ECB/PKCS1padding. It gives different results in Java and Android PKCS1-padding / RSA加密ios objc和java之间的区别 - Difference between PKCS1-padding/RSA encryption ios objc and java 使用模量和指数的C#中的RSA / ECB / PKCS1填充解密 - RSA/ECB/PKCS1Padding Decryption in C# using Modulus and Exponent 在 RSA 加密中使用 Java 但不能使用 c# 加密? - In RSA Encrypting working in Java but not working with encrypting from c#? C#和Java有什么主要区别? - What are major differences between C# and Java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM