RSA-可以加密,但是加密的消息太大,无法解密

时间:2018-11-08 09:42:28

标签: c# encryption aes rsa

编辑:感谢LasseVågsætherKarlsen的建议。我能够解决我的问题。我使用Bitconverter将字节转换为字符串,然后使用UTF8.GetBytes将其转换回字节。这行不通。我决定使用

Convert.FromBase64String Convert.ToBase64String

我正在尝试将RSA实施到客户端服务器C#程序中。

我的计划是在服务器上生成公用密钥,并在握手期间将其发送给客户端。然后,客户端将生成一个用RSA公钥加密的AES密钥,并将其发送回服务器。然后,我将在会话期间使用AES加密通信。

问题是,当服务器收到加密的消息时,出现错误消息,指出文件超出限制。即使将客户端上的加密消息和服务接收到的消息相同,如果将它们转换为XML字符串以比较2,它们的长度和内容也相同。

  

错误:System.Security.Cryptography.CryptographicException:要解密的数据超出了该模块的最大值256个字节。

将序列化的公钥发送给客户端:

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}!");

RSAManager类:

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);
}

用于序列化和反序列化的代码:

序列化:

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;
}

反序列化:

static RSAParameters DeSerializeKey(string publicKeyString)
{
    var sr = new System.IO.StringReader(publicKeyString);
    //we need a deserializer
    var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
    //get the object back from the stream
    return (RSAParameters)xs.Deserialize(sr);
}

接收,加密并发回给客户

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密钥

// 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}");

3 个答案:

答案 0 :(得分:1)

为什么从加密字节取回字符串时使用BitConverter的任何原因? 您是否尝试使用Encoding.UTF8.GetString?

答案 1 :(得分:0)

可以使用RSA加密的数据的最大大小为245,您应该做的是使用随机生成的对称密钥对主块进行加密,然后使用私钥对该密钥进行加密。

This link on StackExchange提供了更多信息。

答案 2 :(得分:-1)

我强烈建议您考虑使用libsodium来解决此类问题。他们的明确目标是为密码操作提供更好的API,以减少滥用滥用库的可能性。

此外,您是否还考虑过如何认证服务器?您可能不需要新生成的RSA密钥。

相关问题