当前位置: 首页 > 知识库问答 >
问题:

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

黎腾
2023-03-14

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

主要问题可能是将加密消息从c#获取到java。在c#中,我们有无符号字节,字节序是不同的

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

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

javax.crypto.BadPaddingException:Message is large than modulus

从C#到C35的加密和解密与从java到java一样有效。只有C#到java不能工作。(要加密的字符串的长度为7个字符,因此它并不太长)

我正在将c#中的公钥转换为<code>BigInteger</code>。公钥由<code>参数</code>传递:

 html" target="_blank">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中的模和指数的BigIntger值相同。填充也是相等的。所以我假设我的加密数据的格式有问题。它应该有哪个版本?

我也看过这个问题:RSA。NET加密Java解密,但即使这样,我也不确定我要加密/解密的数据应该是什么格式

EDIT:试图将c#中的加密字节转换为< code>Base64字符串并在java中将其转换回字节。也不起作用

EDIT2:如果我使用var key = rsaProvider.ToXmlString(true);要获取公钥的xml重现,并将模数和指数的xml字符串放在我的java代码中,将它们从Base64字符串转换为字节数组,从字节数组转换为BigInteger,那么我将获得模量的BigInteger的另一个值,就像BigInteger在c#中一样, 但是我得到这个值的异常:javax.crypto.BadPaddingException:解密错误

编辑3:发现我的错误:为了简单的测试,我只是使用我在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内置方法)

共有2个答案

洪高阳
2023-03-14

因此,为了测试,我将c#中加密数据的字节数组转换为sbyte数组,并获得它的字符串表示。然后,我将字节数组的字符串表示复制到我的java代码中,并将其转换回“字节”数组。之后,我反转数组来匹配java的字节序。

我不太明白为什么“字节序”在这里是一个问题。字节序是运行 CPU 的函数,而不是编程语言。

夹谷成龙
2023-03-14

我有点不清楚你到底哪里错了。下面是一个对我有用的示例,我基于您的代码。我没有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 从命令行读取 base64 字符串(“label = ” 剥离)并执行一些操作。这使用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);
    }

}
 类似资料:
  • 我正在尝试在我的C#程序中实现RSA加密。 这是我的代码: 我收到这个错误代码: <代码>系统。安全密码学。CryptographicException:“错误数据。” 这一行给出了错误:

  • 本文向大家介绍java使用RSA加密方式实现数据加密解密的代码,包括了java使用RSA加密方式实现数据加密解密的代码的使用技巧和注意事项,需要的朋友参考一下 RSA的应用 RSA是一种非对称加密算法。现在,很多登陆表单的密码的都采用RSA加密,例如京东中的登陆使用公钥对密码进行加密 java使用RSA加密方式实现数据加密解密,需要首先产生私钥和公钥 测试代码 RSA工具类的实现 总结 以上所述是

  • 前面小节介绍了如何存储密码,但是有的时候,我们想把一些敏感数据加密后存储起来,在将来的某个时候,随需将它们解密出来,此时我们应该在选用对称加密算法来满足我们的需求。 base64加解密 如果Web应用足够简单,数据的安全性没有那么严格的要求,那么可以采用一种比较简单的加解密方法是base64,这种方式实现起来比较简单,Go语言的base64包已经很好的支持了这个,请看下面的例子: package

  • 在C#中解密RSA加密字符串时,我得到的错误是,要解密的数据超过了256字节模的最大值。 我正在努力实现的目标: 在C#(RSA)中生成公钥/私钥对 将私钥保存在会话/临时存储中,以便在解密期间使用 向客户端/JS发送/返回公钥以用于加密 用公钥加密JS中的字符串(最多20个字符)并发送到服务器 使用步骤2中保存的私钥解密服务器中加密的字符串 工作原理: 公钥/私钥对的生成 在JS中使用库jscr

  • 问题内容: 我正在尝试使用RSA算法在.NET中加密字符串,并在Java中解密结果。目前,我已经可以做相反的事情(用Java加密,用.NET解密)。这里有我的代码可以实际工作(JAVA加密): 和(.NET解密) 现在我想做相反的事情……但是我遇到了一些错误,例如(密钥的大小应该是128个字节……等等)我应该怎么做? 在这里,我添加当前的 无效 代码: 。净 爪哇 问题答案: Java解密代码的最

  • 问题内容: 我正在使用RSA在JAVA上进行加密,并尝试使用.NET进行解密。我包括我的JAVA代码和.NET代码,希望有人对此有所了解。 JAVA代码: 从此JAVA代码中,我得到了加密字符串的结果,该结果恰好是: FOP4 AAIH6hcabXnrvNG5YUk + / + nBv9n9HU0CAgZjkIWQIDjbOpSwoPVBFERrZ6641x2QaoJw5yv18XAay 0WrC