I'm trying to refactor some client-side code from BouncyCastle to Microsoft Cng. I've figured out how to convert key format(ECC key blobs) between them, but I couldn't calculate the same secret.

Currently, the client uses Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement.CalculateAgreement() to calculate the shared secret. The length of the shared secret depends on the curve(e.g, length of shared secrets for SecP224k1 is 28 bytes).

Microsoft Cng(System.Security.Cryptography.ECDiffieHellman) provides several methods: DeriveKeyMaterial, DeriveKeyFromHash. However, none of them returns a result of 28 bytes. DeriveKeyFromHash returns bytes of 16/20/32/48/64 depends on HashAlgorithm, and DeriveKeyMaterial returns the same 32 bytes as DeriveKeyFromHash(SHA256).

Edit: Microsoft Cng's DeriveKey returns Hashed secret.

How to calculate the same secret using Microsoft Cng?


Thanks to @Dave Satchell 's comment.

I go inside to .Net Framework source code. All DeriveKey calls System.Security.Cryptography.NCryptNative.UnsafeNativeMethods.NCryptDeriveKey, which is P/Invoke of ncrypt.dll. You had to pass a key derivation function to NCryptDeriveKey

For anyone who still want to calculate it without BouncyCastle or OpenSSL: I've calculate the shared secret by translating python code.
You may need to implement your own BigInteger or using System.Numerics;
Note: System.Numerics.BigInteger is little endian, and % (mod) works different in C# and Python.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.