Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RSA在c#中加密和在java中解密数据_Java_C#_Encryption - Fatal编程技术网

RSA在c#中加密和在java中解密数据

RSA在c#中加密和在java中解密数据,java,c#,encryption,Java,C#,Encryption,我试图用Java服务器上的RSA公钥加密C#客户端中的数据。为此,我用Java生成了KeyPair KeyPairGenerator.java KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); KeyPair kp = kpg.generateKeyPair(); Key pub = kp.getPublic(); Key pvt = kp.getPrivate(); String

我试图用Java服务器上的RSA公钥加密C#客户端中的数据。为此,我用Java生成了
KeyPair

KeyPairGenerator.java

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
Key pub = kp.getPublic();
Key pvt = kp.getPrivate();

String outFile = "rsa_key";
FileOutputStream outPvt = new FileOutputStream(outFile + ".key");
outPvt.write(pvt.getEncoded());
outPvt.close();

FileOutputStream outPub = new FileOutputStream(outFile + ".pub");
outPub.write(pub.getEncoded());
outPub.close();
String keyFile2 = "rsa_key.pub";
Path path2 = Paths.get(keyFile2);
byte[] bytes2 = Files.readAllBytes(path2);
X509EncodedKeySpec ks2 = new X509EncodedKeySpec(bytes2);
KeyFactory kf2 = KeyFactory.getInstance("RSA");
PublicKey pub = kf2.generatePublic(ks2);

Base64.Encoder encoder = Base64.getEncoder();
String outFile = "en_rsa_key";
Writer out = new FileWriter(outFile + ".pub");
out.write(encoder.encodeToString(pub.getEncoded()));
out.close();
它给了我两个文件(rsa_key.key和rsa_key.pub),然后我用Base64对公钥进行编码,这样C#就可以读取它:

PublicKeyBase64.java

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
Key pub = kp.getPublic();
Key pvt = kp.getPrivate();

String outFile = "rsa_key";
FileOutputStream outPvt = new FileOutputStream(outFile + ".key");
outPvt.write(pvt.getEncoded());
outPvt.close();

FileOutputStream outPub = new FileOutputStream(outFile + ".pub");
outPub.write(pub.getEncoded());
outPub.close();
String keyFile2 = "rsa_key.pub";
Path path2 = Paths.get(keyFile2);
byte[] bytes2 = Files.readAllBytes(path2);
X509EncodedKeySpec ks2 = new X509EncodedKeySpec(bytes2);
KeyFactory kf2 = KeyFactory.getInstance("RSA");
PublicKey pub = kf2.generatePublic(ks2);

Base64.Encoder encoder = Base64.getEncoder();
String outFile = "en_rsa_key";
Writer out = new FileWriter(outFile + ".pub");
out.write(encoder.encodeToString(pub.getEncoded()));
out.close();
然后我创建了我的C#类来加密数据

Encrypter.cs

class Encrypter
{
    private const string PATH = "..\\..\\key\\en_rsa_key.pub";
    private string PublicKey;

    public Encrypter()
    {
        PublicKey = File.ReadAllText(PATH);
        Console.WriteLine(PublicKey.Length);
    }

    public string encryptData(string dataToEncrypt)
    {
        Asn1Object obj = Asn1Object.FromByteArray(Convert.FromBase64String(PublicKey));
        DerSequence publicKeySequence = (DerSequence)obj;

        DerBitString encodedPublicKey = (DerBitString)publicKeySequence[1];
        DerSequence publicKey = (DerSequence)Asn1Object.FromByteArray(encodedPublicKey.GetBytes());

        DerInteger modulus = (DerInteger)publicKey[0];
        DerInteger exponent = (DerInteger)publicKey[1];
        RsaKeyParameters keyParameters = new RsaKeyParameters(false, modulus.PositiveValue, exponent.PositiveValue);
        RSAParameters parameters = DotNetUtilities.ToRSAParameters(keyParameters);
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.ImportParameters(parameters);
        //Console.WriteLine(dataToEncrypt);
        byte[] encryptedData = rsa.Encrypt(Encoding.UTF8.GetBytes(dataToEncrypt), true);
        //Console.WriteLine(Convert.ToBase64String(encryptedData));
        return Convert.ToBase64String(encryptedData);
    }
}
最后是我的解密程序类


我通过WebSocket以C#格式发送加密数据,并毫无问题地接收,因为发送和接收时的数据是相同的。问题是数据长度为344个字符(字节),因此当我解密数据时,它会显示错误:
javax.crypto.IllegalBlockSizeException:数据长度不得超过245个字节
我使用2048位的键,所以它是256B-11B作为填充,这就是为什么它是245B。但问题是它总是生成344B,并且不依赖于消息的编码长度。例如,编码“A”会得到344B,“Hello world”也会得到344B

在这个主题中,人们说使用对称密钥,用对称密钥加密数据,然后用rsa加密对称密钥。但这不会有帮助,因为我代码中的任何加密字符串都有344B大小,所以我无法解密加密的对称密钥


我的代码有什么问题?

我猜您看到的334个字节是因为您看到的是Base64编码的输出文本长度,而不是实际的
encryptedData
缓冲区长度-2048位RSA密钥不会超过256个字节。正如您所说的,解决这个问题的方法是使用RSA加密一个AES-256密钥,它的32字节对RSA来说是没有问题的。我的公钥的长度是393-我在类构造函数中检查了它,就在读取key fileLength属性返回字符数之后,每个字符都是一个字节-393字节,那么原始.pub文件的长度不是密钥的长度,文件内容很可能是PKCS#8编码的,因此Base64带有--分隔符--这比它实际编码的二进制密钥数据长。是的,但它没有定义公钥长度。检查。它还生成长公钥。