Редактировать: Благодаря совету от Лассе Вогстер Карлсен. Я смог решить мою проблему. Я использовал Bitconverter для преобразования байтов в строку, а затем использовал UTF8.GetBytes для преобразования их обратно в байты. Это не работает Я решил использовать
Convert.FromBase64String
Convert.ToBase64String
Я пытаюсь внедрить RSA в программу клиент-сервер C #.
Мой план - создать открытый ключ на сервере и отправить его клиенту во время рукопожатия. Затем клиент сгенерирует ключ AES, зашифрованный открытым ключом RSA, и отправит его обратно на сервер. Затем я буду использовать 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;
}
Deserialize:
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}");