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)
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