Как правильно передать соль с клиента на сервер и обратно при шифровании?

В качестве сервера использую ASP.NET WebApi 2.
В качестве клиента универсальное приложение на Windows 10
Везде используется NET.Framework 4.6
Данные пересылаются по http.

Для шифрования использую PCLCrypto
https://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 но на разных устройствах этот код будет работать? Правильно ли будут происходить преобразования со строками? И может есть более универсальные решения?
  • Вопрос задан
  • 788 просмотров
Решения вопроса 1
schart
@schart
.NET Developer
В комментарии правильно написано, что результат может зависит от типа архитектуры клиента/сервера, а конкретно от порядка байт
Проверить порядок байт можно с помощью BitConverter.IsLittleEndian

Что касается самой идеи то есть стандартны для платформо-независимой сериализации/десериализации бинарных данных: Base64, ProtoBuf, BSON и т.д.

В Вашем случае лучше использовать Base64, т.к. он довольно распространен, прост и не требует дополнительных зависимостей. Посмотрите методы Convert.ToBase64String и Convert.FromBase64String
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы