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.