2010-07-07 13 views
10

Ich möchte sehr wenig Daten (15 Bytes um genau zu sein) in eine so kurz wie möglich (optimal, nicht länger als 16 Bytes) Nachricht mit einem Kryptografiesystem mit öffentlichem Schlüssel verschlüsseln .Minimale Nachrichtengröße Public Key-Verschlüsselung in .NET

Das Standardsystem mit öffentlichem Schlüssel, RSA, produziert leider so große Nachrichten wie seine Schlüssel, das sind ungefähr 100 Bytes, abhängig von der Schlüsselgröße. Um die Dinge schwieriger zu machen, kann ich nur .NET-Framework-Bibliotheken verwenden, d. H. Keine dritte Partei.

Ich habe ein wenig über elliptische Kurven Kryptographie in der Wikipedia gelesen und der Text scheint darauf hinzudeuten, dass Schlüsselgrößen dort in der Regel viel kürzer sind als RSA-Schlüssel.

Kann dies auch in Kurznachrichten übersetzt werden? Kann die .NET ECDiffieHellmanCng Klasse zum Entschlüsseln von Nachrichten verwendet werden? Es scheint eine andere Klassenstruktur zu haben als zB RSA oder die symmetrischen Chiffren.

+0

Public-Key-Kryptographie auf große Schlüsselgrößen abhängig, weil heutige schnelle Computer sogar 256-Bit-Schlüssel in ein paar Stunden brechen können. Wenn der Sicherheitsbedarf hoch ist, sollten Sie keine kleinen Schlüssel verwenden. OW verwenden Sie einfach einen symmetrischen Schlüssel. – apoorv020

+3

@apoorv020; Ihre Anweisung ist falsch, wenn sie auf die Kryptografie öffentlicher Schlüssel mit elliptischen Kurven angewendet wird. –

Antwort

10

Sie können ECDiffieHellman zum Verschlüsseln von Nachrichten verwenden. Sie haben zwei Optionen: Statisch-statisch ECDH und statisch-kurzlebig ECDH:

Für statisch-statische ECDH muss der Empfänger den öffentlichen Schlüssel des Absenders kennen (dies ist in Ihrer Anwendung möglicherweise nicht möglich). Sie sollten auch einige Daten haben, die für diese Nachricht eindeutig sind (es könnte sich um eine Seriennummer handeln, die Sie von einer anderen Stelle in der Protokoll- oder Datenbankzeile oder was auch immer erhalten, oder es könnte eine Nonce sein). Dann verwenden Sie ECDH, um einen geheimen Schlüssel zu generieren und damit Ihre Daten zu verschlüsseln. Dadurch erhalten Sie die gewünschte verschlüsselte Datenlänge von 16 Byte, aber sie ist nicht vollständig asymmetrisch: Der Verschlüssler kann auch die Nachrichten entschlüsseln (wiederum: Dies könnte in Ihrer Anwendung ein Problem darstellen).

Statisch-ephemeral ist ein bisschen anders: Hier generiert der Verschlüssler ein temporäres (ephemeres) EC-Schlüsselpaar. Er verwendet dann dieses Schlüsselpaar zusammen mit dem öffentlichen Schlüssel des Empfängers, um einen geheimen Schlüssel zu erzeugen, der zum Verschlüsseln der Daten verwendet werden kann. Schließlich sendet er den öffentlichen Schlüssel des ephemeren Schlüsselpaares zusammen mit den verschlüsselten Daten an den Empfänger. Dies passt vielleicht besser in Ihre Anwendung, aber die kompletten verschlüsselten Daten sind jetzt 2 * 32 + 16 = 80 Bytes mit ECDH-256 und AES (wie GregS bemerkt, dass Sie 32 Bytes speichern können, indem Sie nur die X-Koordinate der Schlüssel, aber ich glaube nicht, dass .NET die Funktionalität zur Neuberechnung der Y-Koordinate verfügbar macht).

Hier ist eine kleine Klasse, die statische statische ECDH tun:

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

Sie können 32 Bytes speichern, indem Sie nur die X-Koordinate des kurzlebigen öffentlichen Schlüssels senden. –

+0

Danke! Die statisch-statische ECDH scheint genau das zu sein, wonach ich gesucht habe. Wissen Sie, ob und wie ich die .NET ECDH-Klassen zum Verschlüsseln einer Nachricht verwenden kann? Sani wies darauf hin, dass dies nicht ihre Hauptfunktion zu sein scheint. – Jens

+0

@Jens: Ich habe ein kleines Beispiel hinzugefügt –

0

ECDiffieHellmanCNG ist eine Ableitung des ursprünglichen Diffie-Hellman-Schlüsselaustauschprotokolls.
Es ist nicht zum Verschlüsseln von Nachrichten gedacht, sondern zum Berechnen des gleichen geheimen Werts an beiden Enden.

Here ist ein paar Informationen über ECDiffieHellmanCNG und seinen Zweck.

+0

Danke für die Eingabe! Ich hatte gehofft, dass ich den in dieser Klasse verwendeten Algorithmus für meinen Zweck irgendwie missbrauchen könnte. =) – Jens