2010-07-07 57 views
10

我想使用公钥加密系统将很少的数据(准确地说是15个字节)加密成尽可能短的(最好不超过16字节)邮件。.NET中的最小邮件大小公钥加密

不幸的是,标准公钥系统RSA生成的密钥大小与其密钥一样大,大约为100字节,具体取决于密钥大小。 为了让事情变得更加困难,我只能使用.NET框架库,即没有第三方。

我已经读了一些关于维基百科中的椭圆曲线密码术的文章,那里的文字似乎暗示着密钥大小通常比RSA密钥短得多。

这是否也转换为短消息? NET ECDiffieHellmanCng类可以用于解密/加密邮件吗?它似乎具有不同的类结构,例如RSA或对称密码。

+0

公共密钥加密依赖于大的密钥尺寸,因为今天的高速计算机能够在几个小时甚至突破256位密钥。如果安全需求很高,那么你不应该使用小键盘。 OW只是使用对称密钥。 – apoorv020 2010-07-07 16:11:50

+3

@ apoorv020;您的声明在应用于椭圆曲线公钥加密时是不正确的。 – 2010-07-07 23:13:08

回答

10

您可以使用ECDiffieHellman来加密邮件。您有两种选择:静态ECDH和静态短暂ECDH:对于静态静态ECDH,接收方需要知道发送方公钥(这可能是也可能不是您的应用中的选项)。您还应该拥有一些对此消息唯一的数据(它可能是您从协议或数据库中的其他位置获得的序列号 - 行或其他内容,或者它可能是随机数)。然后您使用ECDH生成一个密钥并使用它来加密您的数据。这会给你所需的加密数据长度为16个字节,但它不是完全不对称的:加密器也能够解密这些消息(再次说明:这可能是或者可能不是你的应用程序中的问题)。

Static-ephemeral有点不同:这里的加密器会生成一个临时(临时)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)); 
+1

只需发送临时公钥的x坐标,即可保存32个字节。 – 2010-07-07 23:17:52

+0

谢谢!静电静电ECDH似乎是我正在寻找的。你碰巧知道我是否以及如何使用.NET ECDH类来加密消息?正如Sani指出的那样,这似乎不是他们的主要功能。 – Jens 2010-07-08 06:22:15

+0

@Jens:我已经添加了一个小例子 – 2010-07-08 08:15:30

0

ECDiffieHellmanCNG是原始Diffie-Hellman密钥交换协议的推导。
它不是用于加密消息,而是计算两端的相同秘密值。

Here是ECDiffieHellmanCNG及其用途的一些信息。

+0

感谢您的输入!我希望我能以某种方式滥用本课程中使用的算法来达到我的目的。 =) – Jens 2010-07-08 06:19:35