問題描述
我手頭的任務需要使用 NIST SP 800-56A 第 5.8.1 節中描述的密鑰派生函數派生密鑰材料.我不是密碼學專家,所以如果問題很幼稚,請原諒.這是我到目前為止所做的:
I have a task at hand that requires deriving key material using the key derivation function described in NIST SP 800-56A, section 5.8.1. I'm not an expert in Cryptography so please excuse me if the question is naive. Here's what I've done so far:
- 我有對方的公鑰和我的私鑰
現在我嘗試使用 ECDH 1.3.132.1.12 使用 C# (.NET 4) ECDiffieHellmanCng 類生成共享密鑰,如下所示:
- I have the other party's public key and my private key
Now I try to generate the shared secret using ECDH 1.3.132.1.12 using C# (.NET 4) ECDiffieHellmanCng class like so:
// 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
最后這樣做:
ecDiffieHellmanCng.DeriveKeyMaterial(otherPartyPublicKey:);
在哪里/如何設置其他參數 Algorithm ID、Party U Info、Party V Info?
Where/how do I set the other parameters Algorithm ID, Party U Info, Party V Info?
編輯我愿意使用其他庫,例如 Bouncy Castle(只要它們可以從 .NET 調用)
EDIT I am open to using other libraries like Bouncy Castle (provided they can be called from .NET)
推薦答案
TL;DR;我還沒有找到使用 NIST SP 800-56A 第 5.8.1 節中描述的 KDF 派生對稱密鑰的方法,僅使用 .NET 4.0 中的內置類
TL;DR; I haven't found a way to derive the symmetric key using KDF described in NIST SP 800-56A, section 5.8.1 using built-in classes in .NET 4.0 alone
好消息(對我來說 :-))是在 .NET 4.0 中使用可愛的 BouncyCastle 庫(NuGet:Install-Package BouncyCastle-Ext -Version "1.7.0")是可能的.方法如下:
The good news (for me :-)) is that it IS possible in .NET 4.0 using the lovely BouncyCastle library (NuGet: Install-Package BouncyCastle-Ext -Version "1.7.0"). Here's how:
第一步:獲取對方的公鑰
STEP 1: Get other party's public key
根據您的情況,這可能會從證書中讀取或作為包含加密數據的消息的一部分發送給您.獲得 Base64 編碼的公鑰后,將其讀入 Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters 對象,如下所示:
Depending on your scenario, this may be read from a certificate or come to you as part of the message containing the encrypted data. Once you have the Base64 encoded public-key, read it into a Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters object like so:
var publicKeyBytes = Convert.FromBase64String(base64PubKeyStr);
ECPublicKeyParameters otherPartyPublicKey = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes);
第 2 步:讀取您的私鑰
STEP 2: Read your private-key
這通常涉及從 PFX/P12 證書中讀取私鑰.運行代碼的 Windows 帳戶應該可以訪問 PFX/P12,此外,如果將證書導入證書存儲區,您需要通過所有任務"->管理 certmgr.msc 中的私鑰"菜單授予權限
This would most-commonly involve reading the private key from a PFX/P12 certificate. The windows account running the code should have access to the PFX/P12 and additionally, if the certificate is imported into a certificate store, you'll need to grant permissions via the All Tasks -> manage private key menu in certmgr.msc
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;
}
}
}
}
第 3 步:計算共享密鑰
STEP 3: Compute the shared secret
IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("ECDH");
aKeyAgree.Init(privateKey);
BigInteger sharedSecret = aKeyAgree.CalculateAgreement(otherPartyPublicKey);
byte[] sharedSecretBytes = sharedSecret.ToByteArray();
第 4 步:準備計算對稱密鑰所需的信息:
STEP 4: Prepare information required to compute symmetric key:
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();
第 5 步:導出對稱密鑰
STEP 5: Derive the symmetric key
// 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);
現在您已準備好進行解密的對稱密鑰.要使用 AES 執行解密,可以使用 BouncyCastle IWrapper.通過調用 WrapperUtilities.GetWrapper("AES//") 例如使用 Org.BouncyCastle.Security.WrapperUtilities 獲取 IWrapperAES/CBC/PKCS7".這也取決于兩個通信方之間的協議.
Now you have the symmetric key ready to do the decryption. To perform decryption using AES, BouncyCastle IWrapper can be used. Obtain an IWrapper using Org.BouncyCastle.Security.WrapperUtilities by calling WrapperUtilities.GetWrapper("AES//") e.g. "AES/CBC/PKCS7". This will also depend on the agreement between the two communicating parties.
使用對稱密鑰和初始化向量 (IV) 初始化密碼 (IWrapper) 并調用 Unwrap 方法以獲取純文本字節.最后,使用所使用的字符編碼(例如 UTF8/ASCII/Unicode)轉換為字符串文字
Initialize the cipher (IWrapper) with symmetric key and initialization vector (IV) and call the Unwrap method to get plain-text bytes. Finally, convert to string literal using the character encoding used (e.g. UTF8/ASCII/Unicode)
這篇關于.NET 中的 ECDiffieHellmanCng 是否具有實現 NIST SP 800-56A 第 5.8.1 節的密鑰派生函數的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!