Derive Key with ECDiffieHellmanP256

This solution is only confirmed working on Windows 10 64-bit. It is confirmed not working on Windows 8.1 64 bit, and is untested on other platforms.

The problem is that ECDiffieHellmanP256 is not a hash algorithm, but you are specifying to use a hash key derivation function. Your KeyDerivationFunction should be set to ECDiffieHellmanKeyDerivationFunction.Tls, and you need to specify the seed and label for the KDF.

Your fixed code looks like this:

var key1 = Convert.FromBase64String("BOAiqZO6ucAzDlZKKhF1aLjNpU8+R2Pfsz4bQzNpV145D+agNxvLqyu5Q2tLalK2w31RpoDHE8Sipo0m2jiX4WA=").ToList();
var keyType = new byte[] { 0x45, 0x43, 0x4B, 0x31 };
var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 };
key1.RemoveAt(0);
key1 = keyType.Concat(keyLength).Concat(key1).ToList();

ECDiffieHellmanCng a = new ECDiffieHellmanCng();
a.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Tls;

byte[] label = new byte[32];
string labelStr = "The purpose";
Encoding.ASCII.GetBytes(labelStr, 0, labelStr.Length, label, 0);
a.Label = label;

byte[] seed = new byte[32];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(seed);
a.Seed = seed;

a.HashAlgorithm = CngAlgorithm.ECDiffieHellmanP256;
a.KeySize = 256;

CngKey k = CngKey.Import(key1.ToArray(), CngKeyBlobFormat.EccPublicBlob);
byte[] derivedMaterial = a.DeriveKeyMaterial(k);

Note that I set a nonsense value to the a.Label property.

The NIST SP 800-108 publication defines the label as:

Label – A string that identifies the purpose for the derived keying material, which is encoded as a binary string.

I'm not sure what the purpose should be set to in your specific context. If anyone has a better understanding what this string should be, please leave a comment.

Also note that if you're going to call this function repeatedly, you should probably keep a persistent copy of the RNGCryptoServiceProvider and use that.

Thanks to a comment by Simon Mourier which got me on the right track.