. net中的ecdiffiehellmang有实现NIST SP 800-56A章节5.8.1的密钥派生函数吗?

本文关键字:密钥 派生 函数 章节 ecdiffiehellmang 中的 实现 NIST 800-56A SP net | 更新日期: 2023-09-27 18:01:52

我手头有一个任务,需要使用NIST SP 800-56A第5.8.1节中描述的密钥派生函数派生密钥材料。我不是密码学专家,所以如果这个问题很幼稚,请原谅我。下面是我到目前为止所做的:

  1. 我有对方的公钥和我的私钥
  2. 现在我尝试使用c#()使用ECDH 1.3.132.1.12生成共享密钥。. NET 4) ecdiffiehellmanng类如下:

    // 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:);

其他参数在哪里/如何设置算法ID、第三方信息、第三方信息?

编辑我愿意使用其他库,如Bouncy Castle(只要它们可以从。net调用)

. net中的ecdiffiehellmang有实现NIST SP 800-56A章节5.8.1的密钥派生函数吗?

好消息(对我来说:-))是,在。net 4.0中使用可爱的BouncyCastle库(NuGet: Install-Package BouncyCastle- ext - version "1.7.0")是可能的。方法如下:

步骤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

中的All Tasks ->管理私钥菜单授予权限。
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//")获取IWrapper。"AES/CBC PKCS7"。这也将取决于通信双方之间的协议。

使用对称密钥和初始化向量(IV)初始化密码(IWrapper),并调用Unwrap方法获得纯文本字节。最后,使用所使用的字符编码(例如UTF8/ASCII/Unicode)将其转换为字符串文字