RSA在c#中加密和在java中解密数据
我试图用Java服务器上的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
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带有--分隔符--这比它实际编码的二进制密钥数据长。是的,但它没有定义公钥长度。检查。它还生成长公钥。