2010-07-07 22 views
10

Tôi muốn mã hóa rất ít dữ liệu (chính xác 15 byte) thành một thông điệp ngắn nhất có thể (tối ưu, không dài hơn 16 byte) bằng cách sử dụng hệ thống mật mã khóa công khai .Mã hóa khóa công khai kích cỡ tin nhắn tối thiểu trong .NET

Hệ thống khóa công khai tiêu chuẩn, RSA, không may tạo ra các thông báo lớn bằng các khóa của nó, tức là khoảng 100 byte, tùy thuộc vào kích thước khóa. Để làm cho mọi thứ trở nên khó khăn hơn, tôi chỉ có thể sử dụng thư viện khung .NET, nghĩa là không có bên thứ ba.

Tôi đã đọc một chút về mật mã elip đường cong trong wikipedia và văn bản dường như cho thấy rằng các kích thước khóa thường ngắn hơn nhiều so với khóa RSA.

Dịch này có dịch thành tin nhắn ngắn không? Lớp .NET ECDiffieHellmanCng có thể được sử dụng để de/mã hóa tin nhắn không? Dường như nó có cấu trúc lớp khác nhau, ví dụ, RSA hoặc mật mã đối xứng.

+0

Công mật mã chìa khóa phụ thuộc vào kích thước phím lớn bởi vì ngày nay các máy tính nhanh chóng có thể phá vỡ thậm chí phím 256-bit trong một vài giờ. Nếu nhu cầu bảo mật cao thì bạn không nên sử dụng các phím nhỏ. OW chỉ sử dụng một khóa đối xứng. – apoorv020

+3

@ apoorv020; tuyên bố của bạn là không chính xác khi áp dụng cho mật mã khóa công khai đường cong elip. –

Trả lời

10

Bạn có thể sử dụng ECDiffieHellman để mã hóa tin nhắn. Bạn có hai tùy chọn: ECDH tĩnh tĩnh và ECDH tĩnh điện tạm thời:

Đối với tĩnh ECDH người nhận sẽ cần phải biết khóa công khai của người gửi (điều này có thể hoặc không phải là tùy chọn trong ứng dụng của bạn). Bạn cũng nên có một số dữ liệu duy nhất cho thông báo này (nó có thể là một số sê-ri bạn nhận được từ một nơi khác trong giao thức hoặc hàng cơ sở dữ liệu hoặc bất kỳ thứ gì hoặc nó có thể là một nonce). Sau đó, bạn sử dụng ECDH để tạo khóa bí mật và sử dụng khóa đó để mã hóa dữ liệu của mình. Điều này sẽ cung cấp cho bạn độ dài dữ liệu được mã hóa mong muốn là 16 byte, nhưng nó không hoàn toàn không đối xứng: bộ mã hóa cũng có thể giải mã tin nhắn (một lần nữa: điều này có thể hoặc không có vấn đề trong ứng dụng của bạn).

Tĩnh điện tạm thời có một chút khác biệt: tại đây bộ mã hóa tạo ra cặp khóa EC tạm thời (không lâu). Sau đó, anh ta sử dụng cặp khóa này cùng với khóa công khai của người nhận để tạo ra một khóa bí mật có thể được sử dụng để mã hóa dữ liệu. Cuối cùng, anh ta gửi chìa khóa công khai của cặp khóa tạm thời cho người nhận cùng với dữ liệu được mã hóa. Điều này có thể phù hợp hơn với ứng dụng của bạn, nhưng dữ liệu được mã hóa hoàn chỉnh sẽ là 2 * 32 + 16 = 80 byte bằng ECDH-256 và AES (như GregS lưu ý bạn có thể lưu 32 byte bằng cách chỉ gửi tọa độ x của công chúng- , nhưng tôi không tin rằng .NET cho thấy chức năng tính toán lại tọa độ y).

Dưới đây là một lớp học nhỏ sẽ làm ECDH tĩnh tĩnh:

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

Bạn có thể lưu 32 byte chỉ bằng cách gửi tọa độ x của khóa công cộng tạm thời. –

+0

Cảm ơn! ECDH tĩnh tĩnh dường như là những gì tôi đang tìm kiếm. Bạn có biết liệu tôi có thể sử dụng các lớp .NET ECDH để mã hóa tin nhắn không? Như Sani đã chỉ ra, điều này dường như không phải là chức năng chính của họ. – Jens

+0

@Jens: Tôi đã thêm một ví dụ nhỏ –

0

ECDiffieHellmanCNG là một dẫn xuất của Giao thức trao đổi khóa Diffie-Hellman gốc.
Nó không nhằm mục đích mã hóa tin nhắn mà là tính toán cùng một giá trị bí mật trên cả hai đầu.

Here là một số thông tin về ECDiffieHellmanCNG và mục đích của nó.

+0

Cảm ơn bạn đã nhập! Tôi đã hy vọng rằng tôi bằng cách nào đó có thể lạm dụng thuật toán được sử dụng trong lớp này cho mục đích của tôi. =) – Jens

Các vấn đề liên quan