Минимальное шифрование с открытым ключом размера сообщения в.NET

Я хотел бы зашифровать очень небольшие данные (15 байтов, чтобы быть точным) в максимально короткий (оптимально, не более, чем 16 байтов) сообщение с помощью системы шифрования с открытым ключом.

Стандартная система с открытым ключом, RSA, к сожалению, создает сообщения, столь же большие как его ключи, который составляет приблизительно 100 байтов, в зависимости от размера ключа. Для создания вещей более трудными я могу только пользоваться библиотеками платформы.NET, т.е. никаким третьим лицом.

Я читал немного о шифровании в эллиптических кривых в Википедии, и текст там, кажется, предполагает что размеры ключа, там обычно намного короче, чем ключи RSA.

Это переводит в короткие сообщения также? Может.NET ECDiffieHellmanCng класс привыкнуть к сообщениям de/encrypt? Это, кажется, показывает другую структуру класса затем, скажем, RSA или симметричные шифры.

11
задан Jens 2 April 2014 в 06:12
поделиться

2 ответа

Вы можете использовать ECDiffieHellman для шифрования сообщений. У вас есть два варианта: статический-статический ECDH и статический-эфемерный ECDH:

Для статического ECDH получателю необходимо знать открытый ключ отправителя (это может быть или не быть опцией в вашем приложении). У вас также должны быть некоторые данные, уникальные для этого сообщения (это может быть серийный номер, который вы получаете откуда-то из другого места в протоколе или из строки базы данных, или что-то еще, или это может быть nonce). Затем вы используете ECDH для генерации секретного ключа и используете его для шифрования ваших данных. Это даст вам желаемую длину зашифрованных данных в 16 байт, но это не полностью асимметрично: шифровальщик также может расшифровывать сообщения (опять же: это может быть или не быть проблемой в вашем приложении).

Статический-эфемерный немного отличается: здесь шифровальщик генерирует временную (эфемерную) пару ключей EC. Затем он использует эту пару ключей вместе с открытым ключом получателя для создания секретного ключа, который может быть использован для шифрования данных. Наконец, он отправляет открытый ключ эфемерной пары ключей получателю вместе с зашифрованными данными. Это может лучше подойти для вашего приложения, но полные зашифрованные данные теперь будут 2*32+16=80 байт при использовании ECDH-256 и AES (как отмечает GregS, вы можете сэкономить 32 байта, отправив только x-координату открытого ключа, но я не верю, что .NET предоставляет функциональность для пересчета y-координаты).

Вот небольшой класс, который будет выполнять статический-статический ECDH:

public static class StaticStaticDiffieHellman
{
  private static Aes DeriveKeyAndIv(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce)
  {
    privateKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    privateKey.HashAlgorithm = CngAlgorithm.Sha256;
    privateKey.SecretAppend = nonce;
    byte[] keyAndIv = privateKey.DeriveKeyMaterial(publicKey);
    byte[] key = new byte[16];
    Array.Copy(keyAndIv, 0, key, 0, 16);
    byte[] iv = new byte[16];
    Array.Copy(keyAndIv, 16, iv, 0, 16);

    Aes aes = new AesManaged();
    aes.Key = key;
    aes.IV = iv;
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;

    return aes;
  }

  public static byte[] Encrypt(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce, byte[] data){
    Aes aes = DeriveKeyAndIv(privateKey, publicKey, nonce);
    return aes.CreateEncryptor().TransformFinalBlock(data, 0, data.Length);
  }

  public static byte[] Decrypt(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce, byte[] encryptedData){
    Aes aes = DeriveKeyAndIv(privateKey, publicKey, nonce);
    return aes.CreateDecryptor().TransformFinalBlock(encryptedData,0, encryptedData.Length);
  }
}

// Usage:

ECDiffieHellmanCng key1 = new ECDiffieHellmanCng();    
ECDiffieHellmanCng key2 = new ECDiffieHellmanCng();

byte[] data = Encoding.UTF8.GetBytes("TestTestTestTes");
byte[] nonce = Encoding.UTF8.GetBytes("whatever");

byte[] encryptedData = StaticStaticDiffieHellman.Encrypt(key1, key2.PublicKey, nonce, data);

Console.WriteLine(encryptedData.Length); // 16

byte[] decryptedData = StaticStaticDiffieHellman.Decrypt(key2, key1.PublicKey, nonce, encryptedData);

Console.WriteLine(Encoding.UTF8.GetString(decryptedData));
11
ответ дан 3 December 2019 в 09:40
поделиться

ECDiffieHellmanCNG - это производная от оригинального протокола обмена ключами Диффи-Хеллмана.
Он не предназначен для шифрования сообщений, а скорее для вычисления одного и того же секретного значения на обоих концах.

Здесь приведена некоторая информация о ECDiffieHellmanCNG и его назначении.

0
ответ дан 3 December 2019 в 09:40
поделиться
Другие вопросы по тегам:

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