您可以使用ECDiffieHellman加密消息。您有两个选项:静态ECDH和静态临时ECDH:
对于静态ECDH,接收方需要知道发送方的公钥(这可能是应用程序中的一个选项,也可能不是)。您还应该有一些对此消息唯一的数据(它可能是从协议或数据库行中的其他位置获得的序列号,或者其他任何数据,也可能是nonce)。然后使用ECDH生成一个密钥并用它加密数据。这将为您提供所需的16字节的加密数据长度,但这并不是完全不对称的:加密程序还能够解密消息(同样:这在您的应用程序中可能是问题,也可能不是问题)。
静态临时密钥有点不同:这里加密程序生成一个临时(临时)EC密钥对。然后他使用这个密钥对和接收者的公钥来生成一个可以用来加密数据的密钥。最后,他将临时密钥对的公钥与加密数据一起发送给接收器。这可能更适合您的应用程序,但使用ECDH-256和AES,完整的加密数据现在将是2*32+16=80字节(正如GregS所指出的,您只需发送公钥的x坐标就可以节省32字节,但我不相信.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));