2015-07-10 15 views
11

Ich habe eine Aufgabe, die Schlüsselmaterial mit Hilfe der Schlüsselherleitungsfunktion ableiten muss, die in NIST SP 800-56A, Abschnitt beschrieben wird 5.8.1. Ich bin kein Experte in Kryptographie, also entschuldigen Sie bitte, wenn die Frage naiv ist. Hier ist, was ich bisher getan:Hat ECDiffieHellmanCng in .NET eine Schlüsselableitungsfunktion, die NIST SP 800-56A implementiert, Abschnitt 5.8.1

  1. Ich habe die andere Partei der öffentlichen Schlüssel und meinen privaten Schlüssel
  2. Jetzt versuche ich den gemeinsamen geheimen Schlüssel zu erzeugen, mit ECDH 1.3.132.1.12 mit C# (.NET 4) ECDiffieHellmanCng Klasse wie folgt:

    // The GetCngKey method reads the private key from a certificate in my Personal certificate store 
    
    CngKey cngPrivateKey = GetCngKey(); 
    
    ECDiffieHellmanCng ecDiffieHellmanCng = new ECDiffieHellmanCng(cngPrivateKey); 
    
    ecDiffieHellmanCng.HashAlgorithm = CngAlgorithm.ECDiffieHellmanP256; 
    ecDiffieHellmanCng.KeyDerivationFunction = ?? // What do I set here 
    

Schließlich tun:

ecDiffieHellmanCng.DeriveKeyMaterial(otherPartyPublicKey:); 

Wo/wie setze ich die anderen Parameter Algorithmus ID, Party U Info, Party V Info?

EDIT Ich bin offen für die Verwendung anderer Bibliotheken wie Bouncy Castle (vorausgesetzt, sie können von .NET aufgerufen werden)

Antwort

8

TL; DR; Ich habe keinen Weg gefunden, um den symmetrischen Schlüssel mit KDF abgeleitet NIST SP 800-56A, Abschnitt 5.8.1 mit eingebauten Klassen in .NET 4.0 allein

Die gute Nachricht (für mich :-)) ist, dass es in .NET 4.0 möglich ist, die schöne BouncyCastle-Bibliothek zu verwenden (NuGet: Install-Package BouncyCastle-Ext-Version "1.7.0"). Hier ist, wie:

Schritt 1: Holen andere Partei der öffentlichen Schlüssel

auf Ihrem Szenario Je, dies von einem Zertifikat gelesen werden kann oder kommen zu Ihnen als Teil der Nachricht, die verschlüsselten Daten enthalten. Sobald Sie die Base64 codiert Public-Key haben, lesen Sie es in ein Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters Objekt wie folgt:

var publicKeyBytes = Convert.FromBase64String(base64PubKeyStr); 
ECPublicKeyParameters otherPartyPublicKey = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes); 

SCHRITT 2: Lesen Sie Ihre privaten Schlüssel

Dies würde die Meist Dazu gehört das Lesen des privaten Schlüssels aus einem PFX/P12-Zertifikat. Das Windows-Konto, auf dem der Code ausgeführt wird, sollte Zugriff auf das PFX/P12 haben. Wenn das Zertifikat in einen Zertifikatspeicher importiert wird, müssen Sie darüber hinaus Berechtigungen über das Menü Alle Tasks -> privaten Schlüssel verwalten in certmgr.msc

erteilen
using (StreamReader reader = new StreamReader(path)) 
{ 
    var fs = reader.BaseStream; 
    string password = "<password for the PFX>"; 
    Pkcs12Store store = new Pkcs12Store(fs, passWord.ToCharArray()); 

    foreach (string n in store.Aliases) 
    { 
     if (store.IsKeyEntry(n)) 
     { 
      AsymmetricKeyEntry asymmetricKey = store.GetKey(n); 

      if (asymmetricKey.Key.IsPrivate) 
      { 
       ECPrivateKeyParameters privateKey = asymmetricKey.Key as ECPrivateKeyParameters; 
      } 
     } 
    } 
} 

Schritt 3: berechnen der geheimen gemeinsam genutzten

IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("ECDH"); 
aKeyAgree.Init(privateKey); 
BigInteger sharedSecret = aKeyAgree.CalculateAgreement(otherPartyPublicKey); 
byte[] sharedSecretBytes = sharedSecret.ToByteArray(); 

SCHRITT 4: vorbereiten Informationen symmetrische Schlüssel zu berechnen, benötigt:

byte[] algorithmId = Encoding.ASCII.GetBytes(("<prependString/Hex>" + "id-aes256-GCM")); 
byte[] partyUInfo = Encoding.ASCII.GetBytes("<as-per-agreement>"); 
byte[] partyVInfo = <as-per-agreement>; 
MemoryStream stream = new MemoryStream(algorithmId.Length + partyUInfo.Length + partyVInfo.Length); 
var sr = new BinaryWriter(stream); 
sr.Write(algorithmId); 
sr.Flush(); 
sr.Write(partyUInfo); 
sr.Flush(); 
sr.Write(partyVInfo); 
sr.Flush(); 
stream.Position = 0; 
byte[] keyCalculationInfo = stream.GetBuffer(); 

Schritt 5: sy Leite Mmetrischer Schlüssel

// NOTE: Use the digest/Hash function as per your agreement with the other party 
IDigest digest = new Sha256Digest(); 
byte[] symmetricKey = new byte[digest.GetDigestSize()]; 
digest.Update((byte)(1 >> 24)); 
digest.Update((byte)(1 >> 16)); 
digest.Update((byte)(1 >> 8)); 
digest.Update((byte)1); 
digest.BlockUpdate(sharedSecret, 0, sharedSecret.Length); 
digest.BlockUpdate(keyCalculationInfo, 0, keyCalculationInfo.Length); 
digest.DoFinal(symmetricKey, 0); 

Jetzt haben Sie den symmetrischen Schlüssel bereit, die Entschlüsselung durchzuführen. Um die Entschlüsselung mit AES durchzuführen, kann BouncyCastle IWrapper verwendet werden. Beziehen eines IWrapper mit Org.BouncyCastle.Security.WrapperUtilities durch Aufrufen von WrapperUtilities.GetWrapper ("AES //") z. "AES/CBC/PKCS7". Dies hängt auch von der Vereinbarung zwischen den beiden kommunizierenden Parteien ab.

Initialisieren Sie die Chiffre (IWrapper) mit symmetrischem Schlüssel und Initialisierungsvektor (IV) und rufen Sie die Unwrap-Methode auf, um Nur-Text-Bytes zu erhalten. Schließlich, um String zu konvertieren wörtliche die Zeichenkodierung verwendet, um (zB UTF-8/ASCII/Unicode)

+0

Auf der Verschlüsselungsseite hat BouncyCastle die ConcatenationKDFGenerator Klasse https://github.com/bcgit/bc-csharp/blob/0801c1543f0cafc79c44b225e53c973bdd1b0a0f/ crypto/src/krypto/Vereinbarung/kdf/VerkettungKdfGenerator.cs – Sentinel