2010-07-07 56 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