Doing ECDHE key exchange using C#

2019-05-15 16:31发布

问题:

I am trying to do ECDHE key exchange over TLS 1.2 using .net. The server is responding with a server_key_exchange message, which begins with 04, so I guess it is unencrypted. From my understanding the first 32 bits of the message are considered as a value X, and the next 32 bits are considered as a value Y. Using these, and the elliptic curve (say secp256r1), the value of public key of server is created. I am referring to the following python code from OpenTLS:

class ECDHE_RSA_Key_Exchange: 
    def __init__(self, server_key_exchange): 
        curve_code = bytes_to_hex(server_key_exchange[5:7]) 
        print('Elliptic curve: ' + elliptic_curves[curve_code]) 
        self.curve = reg.get_curve(elliptic_curves[curve_code]) 
        x = bytes_to_int(server_key_exchange[9:9+32]) 
        y = bytes_to_int(server_key_exchange[9+32:9+64]) 
        self.server_pubKey = ec.Point(self.curve, x, y) 

Was looking at C# resources for achieving the same. Below is some of the porting that I could do:

int skeLen = this.sKeyExch_hs[7];
skeLen = skeLen - 1;

byte[] sPubKey = new byte[skeLen];
Buffer.BlockCopy(this.sKeyExch_hs, 9, sPubKey, 0, skeLen);

ECDiffieHellmanCng ecdhCngClient = new ECDiffieHellmanCng(256);

this.client_pub_key = ecdhCngClient.PublicKey.ToByteArray();

byte[] i = {0x04};

this.client_pub_key = this.client_pub_key.Skip(8).ToArray();

this.client_pub_key = i.Concat(this.client_pub_key).ToArray();

byte[] x = {0x45, 0x43, 0x4B, 0x31, 0x20, 0, 0, 0};

sPubKey = x.Concat(sPubKey).ToArray();

ECDiffieHellmanPublicKey serverKey = ECDiffieHellmanCngPublicKey.FromByteArray(sPubKey, CngKeyBlobFormat.EccPublicBlob);

byte[] symmKey = ecdhCngClient.DeriveKeyMaterial(serverKey);

this.pre_master_secret = symmKey;

this.pre_master_secret_list = new List<byte>(this.pre_master_secret);

byte client_pub_key_len = (byte) this.client_pub_key.Length;

this.ckeMessage = new List<byte>();
this.ckeMessage.Add(client_pub_key_len);
this.ckeMessage.AddRange(this.client_pub_key);

return this.ckeMessage;