RSA - Can Encrypt, But encrypted Message is too large for decrypting
编辑:多亏了拉斯五世的建议?GS?卡尔森。我能解决我的问题。我使用bitconverter将字节转换为字符串,然后使用utf8.getbytes将它们转换回字节。这不管用。我决定用
Convert.ToBase64String
我正在尝试将RSA实现到客户机-服务器C程序中。
我的计划是在服务器上生成一个公钥,并在握手期间将其发送到客户机。然后,客户机将生成一个用RSA公钥加密的AES密钥,并将其发送回服务器。然后,我将在会话期间使用AES加密通信。
问题是,当服务器接收到加密消息时,我会收到一个错误,说明文件超出了限制。即使客户机上的加密消息和服务接收到的消息长度相同,并且内容相同,但如果我将它们转换为XML字符串来比较2的话。
error: System.Security.Cryptography.CryptographicException: The data to be decrypted exceeds the maximum for the module by 256 bytes.
正在将序列化公钥发送到客户端:
1 2 3 4 5 6 | RSAManager rSAManager = new RSAManager(); string publicKeyString = SerializeKey(rSAManager.publicKey); // Serialize the public key so we can send it to the clients // Send test data to the remote device. Send(client, $"{publicKeyString}!"); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | public class RSAManager { #region Keys, Containername, Keysizes public RSAParameters publicKey; public RSAParameters privateKey; static string CONTAINER_NAME ="MyContainerName"; public enum KeySizes { SIZE_512 = 512, SIZE_1024 = 1024, SIZE_2048 = 2048, SIZE_952 = 952, SIZE_1369 = 1369 }; #endregion #region Methods public RSAManager() { GenerateKeys(); } public void GenerateKeys() { using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.PersistKeyInCsp = false; //Don't store the keys in a key container publicKey = rsa.ExportParameters(false); privateKey = rsa.ExportParameters(true); } } /// <summary> /// Encrypts the given byte array with the RSA standard /// </summary> /// <param name="input"></param> /// <returns></returns> public byte[] Encrypt(string message) { byte[] input = Encoding.UTF8.GetBytes(message); byte[] encrypted; using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.PersistKeyInCsp = false; rsa.ImportParameters(publicKey); encrypted = rsa.Encrypt(input, true); } return encrypted; } /// <summary> /// Decrypts the given byte array with the RSA standard /// </summary> /// <param name="input"></param> /// <returns></returns> public string Decrypt(byte[] encrypted) { byte[] decrypted; using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.PersistKeyInCsp = false; rsa.ImportParameters(privateKey); decrypted = rsa.Decrypt(encrypted, true); } return Encoding.UTF8.GetString(decrypted); } |
用于序列化和反序列化的代码:Serialize:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static string SerializeKey(RSAParameters publicKey) { string publicKeyString; { //we need some buffer var sw = new System.IO.StringWriter(); //we need a serializer var xs1 = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters)); //serialize the key into the stream xs1.Serialize(sw, publicKey); //get the string from the stream publicKeyString = sw.ToString(); } return publicKeyString; } |
Deserialize:
1 2 3 4 5 6 7 8 |
接收、加密和发送回客户
1 2 3 4 5 6 7 8 9 10 11 12 13 | string publicKeyString = TrimString(new string[] {"!"},content); RSAManager rSAManager = new RSAManager(); rSAManager.publicKey = DeSerializeKey(publicKeyString); string randomAESKey = GetRandomString(40); Console.WriteLine($"Randomstring: {randomAESKey"); byte[] encrypted = rSAManager.Encrypt(randomAESKey); string encryptedAESKey = BitConverter.ToString(encrypted); Console.WriteLine($"Encrypted. {encryptedAESKey}"); Console.WriteLine("Length of encrypted string:" + encryptedAESKey.Length); // Echo the data back to the server. Send(handler, encryptedAESKey); |
服务器接收和解密AES密钥
1 2 3 4 5 6 7 | // Write the response to the console. Console.WriteLine("Length of encrypted response:" + response.Length); Console.WriteLine("Length of public Key:" + SerializeKey(rSAManager.publicKey).Length); // Decrypt functions needs byte array so we need to encode it. This line always causes the error. string encryptedResponse = rSAManager.Decrypt(Encoding.UTF8.GetBytes(response)); // Received encrypted response Console.WriteLine($"Decrypted response: {encryptedResponse}"); |
为什么在从加密字节中获取字符串时使用bitconverter?是否尝试使用encoding.utf8.getString?
可以用RSA加密的最大数据大小是245,您应该用随机生成的对称密钥加密主块,并用您的私钥加密该密钥。
StackExchange上的此链接有更多信息。
我强烈建议你考虑用溴化钠来解决这类问题。他们明确的目标是为加密操作提供一个更好的API,以减少误用库而破坏安全的可能性。
另外,您是否也考虑过如何对服务器进行身份验证?您可能不需要新生成的RSA密钥。