public static byte[] DeriveKey(CngKey externalPubKey, CngKey privateKey, int keyBitLength, byte[] algorithmId, byte[] partyVInfo, byte[] partyUInfo, byte[] suppPubInfo) { using (var cng = new ECDiffieHellmanCng(privateKey)) { using (SafeNCryptSecretHandle hSecretAgreement = cng.DeriveSecretAgreementHandle(externalPubKey)) { using (var algIdBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_ALGORITHMID, algorithmId)) using (var pviBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_PARTYVINFO, partyVInfo)) using (var pvuBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_PARTYUINFO, partyUInfo)) using (var spiBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_SUPPPUBINFO, suppPubInfo)) { using (var parameters = new NCrypt.NCryptBufferDesc(algIdBuffer, pviBuffer, pvuBuffer, spiBuffer)) { uint derivedSecretByteSize; uint status = NCrypt.NCryptDeriveKey(hSecretAgreement, "SP800_56A_CONCAT", parameters, null, 0, out derivedSecretByteSize, 0); if (status != BCrypt.ERROR_SUCCESS) throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", status)); var secretKey = new byte[derivedSecretByteSize]; status = NCrypt.NCryptDeriveKey(hSecretAgreement, "SP800_56A_CONCAT", parameters, secretKey, derivedSecretByteSize, out derivedSecretByteSize, 0); if (status != BCrypt.ERROR_SUCCESS) throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", status)); return Arrays.LeftmostBits(secretKey, keyBitLength); } } } } }
public NCryptBufferDesc(params NCrypt.NCryptBuffer[] buffers) { this.cBuffers = (uint)buffers.Length; this.ulVersion = 0; this.pBuffers = Marshal.AllocHGlobal(((IEnumerable <NCrypt.NCryptBuffer>)buffers).Sum <NCrypt.NCryptBuffer>((NCrypt.NCryptBuffer buf) => Marshal.SizeOf(buf))); int num = 0; NCrypt.NCryptBuffer[] nCryptBufferArray = buffers; for (int i = 0; i < (int)nCryptBufferArray.Length; i++) { NCrypt.NCryptBuffer nCryptBuffer = nCryptBufferArray[i]; Marshal.StructureToPtr(nCryptBuffer, this.pBuffers + num, false); num += Marshal.SizeOf(nCryptBuffer); } }