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

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

主要问题可能是将加密后的消息从c#发送到java。
在C#中,我们具有无符号字节,并且字节序不同

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

但是,如果我尝试对上述传输的数据进行解码,则会收到以下异常:

  javax.crypto.BadPaddingException:消息大于模数

从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模数和指数值。填充也相等。
 因此,我假设加密数据的格式有问题。它应该有哪一点?

我也阅读了以下问题: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: Decryption error

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内置方法)

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

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java-如何将此字符串转换为日期? - java

我从服务器收到此消息,我不明白T和Z的含义,2012-08-24T09:59:59Z将此字符串转换为Date对象的正确SimpleDateFormat模式是什么? java大神给出的解决方案 这是ISO 8601标准。您可以使用SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM…

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

从方法返回数组-Java - java

private static Coordinate[] getCircleCoordintaes() { Coordinate coordinates[] = {new Coordinate(0, 0)}; return coordinates; } 以上程序工作正常。在上面的程序中,返回的坐标数组首先初始化了数组使用这条线Coordinate coordi…

Java Swing SearchBox模型 - java

我需要使用Java Swing的搜索框,如果单击任何建议,当输入字母时它将显示来自数据库的建议,它将执行一些操作。如果有可能在Java swing中,请提供源代码提前致谢 java大神给出的解决方案 您可以使用DefaultComboBoxModel,输出将是这样。Try this在此代码中,您将找到countries数组,因此您需要从数据库中获取此数组。