首页 > 解决方案 > 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 大小,所以我将无法解密加密的对称密钥。

我的代码有什么问题?

标签: javac#encryption

解决方案


推荐阅读