TL;博士; 我还没有找到使用 NIST SP 800-56A 第 5.8.1 节中描述的 KDF 派生对称密钥的方法,仅使用 .NET 4.0 中的内置类
好消息(对我来说 :-))是在 .NET 4.0 中可以使用可爱的 BouncyCastle 库(NuGet:Install-Package BouncyCastle-Ext -Version "1.7.0")。就是这样:
STEP 1:获取对方的公钥
根据您的情况,这可能是从证书中读取的,或者作为包含加密数据的消息的一部分提供给您。获得 Base64 编码的公钥后,将其读入 Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters 对象,如下所示:
var publicKeyBytes = Convert.FromBase64String(base64PubKeyStr);
ECPublicKeyParameters otherPartyPublicKey = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes);
第 2 步:读取您的私钥
这通常涉及从 PFX/P12 证书中读取私钥。运行代码的 Windows 帐户应该可以访问 PFX/P12,此外,如果将证书导入证书存储,您需要通过 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 步:计算共享密钥
IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("ECDH");
aKeyAgree.Init(privateKey);
BigInteger sharedSecret = aKeyAgree.CalculateAgreement(otherPartyPublicKey);
byte[] sharedSecretBytes = sharedSecret.ToByteArray();
第 4 步:准备计算对称密钥所需的信息:
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 步:导出对称密钥
// 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。使用 Org.BouncyCastle.Security.WrapperUtilities 通过调用 WrapperUtilities.GetWrapper("AES//") 例如“AES/CBC/PKCS7”来获取 IWrapper。这也将取决于两个通信方之间的协议。
使用对称密钥和初始化向量 (IV) 初始化密码 (IWrapper) 并调用 Unwrap 方法以获取纯文本字节。最后,使用所使用的字符编码(例如 UTF8/ASCII/Unicode)转换为字符串文字