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;