java - c#中的RSA加密和java中的解密数据
问题描述
我正在尝试使用来自 Java 服务器的公共 RSA 密钥加密我的 C# 客户端中的数据。为此,我KeyPair
在 Java 中生成
密钥对生成器.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();
它给了我两个文件(rsa_key.key 和 rsa_key.pub),然后我用 Base64 对公钥进行编码,以便 C# 可以读取它:
PublicKeyBase64.java
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# 类来加密数据
加密器.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);
}
}
最后是我的 Decrypter 课程
public class Decrypter {
private static final String PATH = "I:\\rsa_key.key";
private File privateKeyFile = new File(PATH);
private RSAPrivateKey privateKey;
public Decrypter() throws Exception {
DataInputStream dis = new DataInputStream(new FileInputStream(privateKeyFile));
byte[] privateKeyBytes = new byte[(int)privateKeyFile.length()];
dis.read(privateKeyBytes);
dis.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privateKeyBytes);
privateKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
}
public String decrypt(String data) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return new String(cipher.doFinal(data.getBytes()));
}
}
我通过 WebSocket 在 C# 中发送加密数据并毫无问题地接收它,因为发送和接收时的数据是相同的。问题是数据长度是 344 个字符(字节),所以当我解密数据时,它会显示我和错误:javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes
我使用 2048 位密钥,所以它是 256B - 11B 用于填充,这就是为什么它是 245B。但问题是它总是生成 344B 并且它不依赖于消息来编码长度。例如,编码“A”给出 344B,“Hello world”也给出 344B。
在这个话题中,人们说要使用对称密钥,用对称密钥加密数据,然后用 rsa 加密对称密钥。但这无济于事,因为我的代码中的任何加密字符串都有 344B 大小,所以我将无法解密加密的对称密钥。
我的代码有什么问题?
解决方案
推荐阅读
- python - 如何在给定条件下用其他行的值填充 DataFrame 的数据?
- hive - Hive 表加入:我有一个分区表并想加入另一个表
- python - 为什么我不能在 Python Ktinker 上移动我的下拉列表
- python - intellij pycharm/python:创建 JVM 失败。JVM - 路径:C:\Program Files\ JetBrains\ PyCharm 2020.1.2\jbr\
- python - 如何在我的音乐游戏中解决这个问题?
- javascript - 传单搜索的自动完成和建议不起作用?
- .net - 如何从 Microsoft.Extensions.Caching.Memory.MemoryCache 获取 ICacheEntry
- c - 将数字分配给结构指针时输出错误
- javascript - 使用 Private react-router Route 时“超出最大更新深度”
- postgresql - Flyway 7.5.1 及以上版本无法初始化 Zonky-test DB