繁体   English   中英

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

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

我正在使用RSA和Java(Android)中的PKCS1填充来加密文本,之后必须将其作为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程序,发现每个程序都可以解密对方的输出并获得正确的结果。

两种代码都是正确的。 您可以使用Java版本和C#版本以相同的方式加密数据。 如果其中一个正在工作而另一个在失败,则可能是您使用了不正确的公钥(复制/粘贴错误,一些不同的字节等)。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM