java - 在 Java 中从 C# 解密 RSA 加密数据。加密数据的格式?

标签 java c# rsa

我正在使用 RSA 加密来加密 C# 中的一些数据。现在我想用Java解密加密的数据。 但我遇到了一些问题。

主要问题可能是从 C# 到 Java 获取加密消息。 在 C# 中,我们有无符号字节,并且字节序不同

因此,为了进行测试,我将 C# 中加密数据的 byte 数组转换为 sbyte 数组,并获取它的字符串表示形式。 然后,我将字节数组的字符串表示形式复制到我的 java 代码中,并将其转换回“字节”数组。之后,我反转数组以匹配 java 的字节顺序。

但是如果我尝试解码上面传输的数据,则会出现以下异常:

javax.crypto.BadPaddingException: Message is larger than modulus

从 C# 到 C# 的加密和解密以及从 java 到 java 的加密和解密同样有效。只有C#转java是不行的。 (要加密的字符串长度为7个字符,所以并不是太长)

我正在将 C# 中的公钥转换为 BigInteger。公钥是从RSAParameters传递的:

 public byte[] RSAEncrypt(byte[] data, RSAParameters param, bool padding) {
        using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(1024)) {
            rsaProvider.ImportParameters(param);

            byte[] modulusArray = param.Modulus;
            byte[] exponentArray = param.Exponent;

            BigInteger modulusBigInt = new BigInteger(modulusArray);

            BigInteger exponentBigInt = new BigInteger(exponentArray);

            encryptedData = rsaProvider.Encrypt(data, false);

            return encryptedData;
        }
    }

之后,我将模数和指数的字符串表示形式复制到我的 java 代码中,并从中创建新的 BigInteger 并创建公钥:

    BigInteger modulusBigInt = new BigInteger(modulusBytesStr);
    BigInteger exponentBigInt = getBigIntFromByteString(exponentBytesStr);

    Key pK = getPublicKey(modulusBigInt, exponentBigInt);

然后我尝试解密数据(其中数据是我从 C# 传输到 Java 的字节数组,如上所述):

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

        cipher.init(Cipher.DECRYPT_MODE, pK);

        decryptedData = cipher.doFinal(data);

但是如果我尝试这样做,我就会收到上面提到的异常。我认为公钥应该是正确的。至少我在 C# 和 Java 中具有相同的 BigInteger 模数和指数值。填充也相等。 所以我假设我的加密数据的格式有问题。它应该有哪个 fromat?

我也读过这个问题:RSA .NET encryption Java decryption 但即使在那之后,我也不确定要加密/解密的数据应该采用什么格式

编辑:尝试将 c# 中的加密字节转换为 Base64 String 并在 java 中将其转换回字节。也不起作用

EDIT2:如果我使用 var key = rsaProvider.ToXmlString(true); 来获取公钥的 xml 表示并将模数和指数的 xml 字符串放入我的 java 代码中,将它们从 Base64 字符串转换为字节数组,从字节数组转换为 BigInteger,然后我得到另一个模数 BigInteger 值,就像 C# 中的 BigInteger 一样,但我得到以下值的异常:javax.crypto。 BadPaddingException:解密错误

EDIT3:发现我的错误:为了简单测试,我只是使用我在 C# 代码中生成的私钥在 java 中解密。但在我的java代码中,我尝试从私钥生成公钥。

     RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);

        KeyFactory kf = KeyFactory.getInstance("RSA");
        PublicKey pK = kf.generatePublic(keySpec);

这显然是错误的。所以我将其更改为:

 RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(modulusBigInt, exponentBigInt);

        KeyFactory kf = KeyFactory.getInstance("RSA");
        Key key = kf.generatePrivate(keySpec);

而且它成功了。这也是 GregS 方法起作用的原因(没有生成“PublicKey”/“PrivateKey”,并且解密不是使用 java 内置方法)

最佳答案

我有点不清楚你到底哪里出了问题。这是一个对我有用的示例,我基于您的代码。我没有 Windows 机器,所以我在 Mono 中测试了这个。

C#:

using System;
using System.Security.Cryptography;
using System.Text;

namespace RsaDotNetToJava
{
    class MainClass
    {
        public byte[] RSAEncrypt(byte[] data, RSAParameters param, bool padding) {
            using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(1024)) {
                rsaProvider.ImportParameters(param);

                var encryptedData = rsaProvider.Encrypt(data, false);

                return encryptedData;
            }
        }

        public static void W(string label, byte [] x) {
            var b64 = Convert.ToBase64String (x);
            Console.WriteLine ("{0} = {1}", label, b64);
        }

        public static void Main (string[] args)
        {
            var x = new MainClass ();
            var rsa = new RSACryptoServiceProvider (1024);
            var data = Encoding.ASCII.GetBytes("Hello world");
            var parms = rsa.ExportParameters(true);
            W ("Modulus", parms.Modulus);
            W ("P", parms.P);
            W ("DecryptExponent", parms.D);
            W ("EncryptExponent", parms.Exponent);
            var cipher = x.RSAEncrypt(data, parms, false);
            W ("Cipher", cipher);
        }
    }
}

接下来,一些 Java 从命令行读取带有(“label =”剥离)的 base64 字符串并执行一些操作。它使用 java 7 类 javax.xml.bind.DatatypeConverter 作为其 base64 解析器。

import java.math.BigInteger;
import javax.xml.bind.DatatypeConverter;

public class RsaJavaToDotNet {


    private static BigInteger b64ToBigInteger(String b64) {
        byte [] bigEndianBytes = DatatypeConverter.parseBase64Binary(b64);
        return new BigInteger(1, bigEndianBytes); 
    }

    /**
     * @param args base64 encoded .NET big-endian integer arrays
     *    args[0] = modulus
     *    args[1] = prime
     *    args[2] = decrypt exponent
     *    args[3] = encrypt exponent
     *    args[4] = cipher
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {

        BigInteger modulus = b64ToBigInteger(args[0]);
        final int modulusByteLength = (modulus.bitLength() + 7) / 8;
        BigInteger prime = b64ToBigInteger(args[1]);
        BigInteger d = b64ToBigInteger(args[2]);
        BigInteger e = b64ToBigInteger(args[3]);
        BigInteger cipherInt = b64ToBigInteger(args[4]);

        // Decrypt the cipher

        BigInteger plainInt = cipherInt.modPow(d, modulus);
        byte [] plain = plainInt.toByteArray();

        // Verify the format and extract the message.

        if (plain.length != (modulusByteLength - 1) || plain[0] != 2) {
            throw new Exception("Something is wrong");
        }

        // Find the zero byte delimited the payload from the padding

        int zeroPos = 1;
        while (zeroPos < plain.length && plain[zeroPos] != 0) {
            ++zeroPos;
        }

        String plainStr = new String(plain, zeroPos + 1, plain.length - zeroPos - 1, "UTF-8");
        System.out.println(plainStr);
    }

}

关于java - 在 Java 中从 C# 解密 RSA 加密数据。加密数据的格式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24962424/

相关文章:

java - Spring MVC : Get Unnamed Request Parameter

java - 是什么导致 "bad operand types for binary operator ' = =' "与第二种类型 <nulltype>?

c# - C# 和 VB6 mdi 应用程序之间的消息互操作

c# - 使用 Linq 和 C# 计算一行中有多少个单元格为空

php - 兼容Javascript和PHP的RSA加密/解密

licensing - PHP 中的 RSA_sign 或 DSA_sign!

java - 如何在 Java 中使用 .p12 文件对数据进行签名?

java - 如何使用 Avro 序列化/反序列化动态 json 类型

java - dbpedia 聚焦 Java 中的 Web 服务

c# - 为什么设置字段比获取字段慢很多倍?