This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to generate public/private key and implement ECDHSecret with .NET framework

Dear Sir

I'd like to develop the Window APP for Mesh (like nRF Mesh).

And I've face a problem. The ECDHSecret key of the Windows side didn't match the device side(Thingy).

Theoretically, ECDHSecret key should be the same on both side. 

Here is part of my code.

Generate public/private key:

private CngKey provisioner_key;

byte[] eccprivcyblob;

byte[] provisioner_pub;



private void generateKeyPairs()
{
    try
    {
        
        provisioner_key = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256, null, new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowPlaintextArchiving });
        eccprivcyblob = provisioner_key.Export(CngKeyBlobFormat.EccPrivateBlob);
        provisioner_pub = provisioner_key.Export(CngKeyBlobFormat.EccPrivateBlob);
        
        //BCRYPT_ECDH_PUBLIC_P256_MAGIC = 0x314B4345
        ulong dwMagic = 0;
        for (int i = 3; i >= 0; --i)
        {
            dwMagic = (dwMagic << 8 | provisioner_pub[i]);
        }
        if (dwMagic == BCRYPT_ECDH_PUBLIC_P256_MAGIC)
        {
            ulong keysize = 0;
            for (int i = 7; i >= 4; --i)
            {
                keysize = (keysize << 8 | provisioner_pub[i]);
            }
        mPublicKey = new byte[keysize * 2];
        int index = 8;
    
        for (int j = 0; j < mPublicKey.Length; ++index, ++j)
        {
            mPublicKey[j] = provisioner_pub[index];
        }
    }
}
    catch (Exception e)
    {
        WriteListBox(e.StackTrace, listBox_result, false);
    }
}

GenerateSharedECDHSecret

private byte[] generateSharedECDHSecret()
{
    byte[] dEccPublicBlob = new byte[dPublicKey.Length + 8];
    //BCRYPT_ECDH_PUBLIC_P256_MAGIC = 0x314B4345;
    dEccPublicBlob[0] = 0x45;
    dEccPublicBlob[1] = 0x43;
    dEccPublicBlob[2] = 0x4B;
    dEccPublicBlob[3] = 0x31;
    dEccPublicBlob[4] = (byte)(dPublicKey.Length / 2);
    Array.Copy(dPublicKey, 0, dEccPublicBlob, 8, dPublicKey.Length);
    
    dcngKey = CngKey.Import(dEccPublicBlob, CngKeyBlobFormat.EccPublicBlob);
    
    var provisionerAlgo = new ECDiffieHellmanCng(provisioner_key);
    return provisionerAlgo.DeriveKeyMaterial(dcngKey);
}

If I miss something?

Thanks.

Related