Как правильно передать соль с клиента на сервер и обратно при шифровании? В качестве сервера использую ASP.NET WebApi 2. В качестве клиента универсальное приложение на Windows 10 Везде используется NET.Framework 4.6 Данные пересылаются по http. Для шифрования использую PCLCryptohttps://github.com/aarnott/pclcrypto Ниже класс для шифрования:public static class Crypto { public static byte[] CreateSalt(uint lengthInBytes) { return WinRTCrypto.CryptographicBuffer.GenerateRandom(lengthInBytes); } public static byte[] CreateDerivedKey(string password, byte[] salt, int keyLengthInBytes = 32, int iterations = 10000) { byte[] key = NetFxCrypto.DeriveBytes.GetBytes(password, salt, iterations, keyLengthInBytes); return key; }
public static byte[] EncryptAes(string data, string password, byte[] salt) { byte[] key = CreateDerivedKey(password, salt); ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcbPkcs7); ICryptographicKey symetricKey = aes.CreateSymmetricKey(key); var bytes = WinRTCrypto.CryptographicEngine.Encrypt(symetricKey, Encoding.UTF8.GetBytes(data)); return bytes; } public static string DecryptAes(byte[] data, string password, byte[] salt) { byte[] key = CreateDerivedKey(password, salt); ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcbPkcs7); ICryptographicKey symetricKey = aes.CreateSymmetricKey(key); var bytes = WinRTCrypto.CryptographicEngine.Decrypt(symetricKey, data); return Encoding.UTF8.GetString(bytes, 0, bytes.Length); } } Шифрую на клиенте логин и пароль пользователя перед отправкой:var salt = Crypto.CreateSalt(16); var bytes = Crypto.EncryptAes(data, pass, salt); Расшифровываю на сервере:var str = Crypto.DecryptAes(bytes, pass, salt); Когда тестил в одном приложении то все работало. Как только разнес части на сервер и клиент, то возникли трудности при конвертировании byte[] в string и обратно. использовал Convert.ToString() и Encoding.UTF8.GetBytes/GetString. При использовании этих функций получается разные значения в массиве байт. Нашел такой пример:stackoverflow.com/questions/472906/converting-a-st... Использовал первый ответ:static byte[] GetBytes(string str) { var bytes = new byte[str.Length * sizeof(char)]; Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); return bytes; } static string GetString(byte[] bytes) { var chars = new char[bytes.Length / sizeof(char)]; Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length); return new string(chars); } На одной машине работает. Но в комментариях к данном ответу что-то сказано что данный способ будет работать только на одной машине. Возможности проверить на разных машинах нет. Про SSL знаю, но использовать его пока не буду. Соль передаю вместе с зашифрованным текстом так она генерируется каждый раз при шифровании. Вроде это (новая генерация соли) увеличивает шансы от взломала методом перебора по радужным таблицам или как то так. Скажите пожалуйста, в рамках одной версии net.framework но на разных устройствах этот код будет работать? Правильно ли будут происходить преобразования со строками? И может есть более универсальные решения?
Да, преобразование byte[] в string и обратно может вызвать проблемы при передаче данных между разными устройствами из-за различий в кодировках и представлении символов.
Для универсального и безопасного способа передачи данных между клиентом и сервером рекомендуется использовать сериализацию данных в формат JSON. Например, вы можете использовать библиотеку Newtonsoft.Json для сериализации объектов в JSON и обратно.
Пример использования Newtonsoft.Json для сериализации и десериализации данных:
using Newtonsoft.Json; public static class Crypto { public static byte[] EncryptAes(string data, string password, byte[] salt) { byte[] key = CreateDerivedKey(password, salt); ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcbPkcs7); ICryptographicKey symetricKey = aes.CreateSymmetricKey(key); var bytes = WinRTCrypto.CryptographicEngine.Encrypt(symetricKey, Encoding.UTF8.GetBytes(data)); return bytes; } public static string DecryptAes(byte[] data, string password, byte[] salt) { byte[] key = CreateDerivedKey(password, salt); ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcbPkcs7); ICryptographicKey symetricKey = aes.CreateSymmetricKey(key); var bytes = WinRTCrypto.CryptographicEngine.Decrypt(symetricKey, data); return Encoding.UTF8.GetString(bytes, 0, bytes.Length); } } // Serialize data to JSON before sending to server var saltJson = JsonConvert.SerializeObject(salt); var dataJson = JsonConvert.SerializeObject(bytes); // Deserialize data from JSON on server side var salt = JsonConvert.DeserializeObject<byte[]>(saltJson); var bytes = JsonConvert.DeserializeObject<byte[]>(dataJson);
Таким образом, используя сериализацию в JSON, вы можете безопасно передавать данные между клиентом и сервером, обходя проблемы с различными форматами кодировки и представления данных.
Да, преобразование byte[] в string и обратно может вызвать проблемы при передаче данных между разными устройствами из-за различий в кодировках и представлении символов.
Для универсального и безопасного способа передачи данных между клиентом и сервером рекомендуется использовать сериализацию данных в формат JSON. Например, вы можете использовать библиотеку Newtonsoft.Json для сериализации объектов в JSON и обратно.
Пример использования Newtonsoft.Json для сериализации и десериализации данных:
using Newtonsoft.Json;public static class Crypto
{
public static byte[] EncryptAes(string data, string password, byte[] salt)
{
byte[] key = CreateDerivedKey(password, salt);
ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcbPkcs7);
ICryptographicKey symetricKey = aes.CreateSymmetricKey(key);
var bytes = WinRTCrypto.CryptographicEngine.Encrypt(symetricKey, Encoding.UTF8.GetBytes(data));
return bytes;
}
public static string DecryptAes(byte[] data, string password, byte[] salt)
{
byte[] key = CreateDerivedKey(password, salt);
ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcbPkcs7);
ICryptographicKey symetricKey = aes.CreateSymmetricKey(key);
var bytes = WinRTCrypto.CryptographicEngine.Decrypt(symetricKey, data);
return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}
}
// Serialize data to JSON before sending to server
var saltJson = JsonConvert.SerializeObject(salt);
var dataJson = JsonConvert.SerializeObject(bytes);
// Deserialize data from JSON on server side
var salt = JsonConvert.DeserializeObject<byte[]>(saltJson);
var bytes = JsonConvert.DeserializeObject<byte[]>(dataJson);
Таким образом, используя сериализацию в JSON, вы можете безопасно передавать данные между клиентом и сервером, обходя проблемы с различными форматами кодировки и представления данных.