3

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;
frenzy man
  • 81
  • 1
  • 7
  • .Net has a [Diffie Hellman](https://msdn.microsoft.com/en-us/library/system.security.cryptography.ecdiffiehellmancng(v=vs.110).aspx) implementation. I don't know if it will give the same results as the Python code, but its worth a look at least. –  Feb 09 '18 at 06:04
  • Thanks that worked, but there were some modifications. I have updated the working code – frenzy man Feb 09 '18 at 07:00
  • The Client Key Exchange is still rejected. Not sure how to create pre_master_secret for ECDHE – frenzy man Feb 09 '18 at 07:06
  • Sorry actually the above code did not work. It is throwing the following error: Unhandled Exception: System.Security.Cryptography.CryptographicException: The parameter is incorrect. at System.Security.Cryptography.NCryptNative.ImportKey(SafeNCryptProviderHandle provider, Byte[] keyBlob, String format) at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, String curveName, CngKeyBlobFormat format, CngProvider provider) at handshake.ClientKeyExchange.CreateCKE() at sslC.sslC.Main() – frenzy man Feb 09 '18 at 08:26
  • After reading through a bit, particularly the RFC, it states that "The negotiated key (Z) is used as the pre_master_secret, and is converted into the master_secret, as specified above". Modified the code accordingly. Client Key Exchange message just has the public key created with the same DH curve whose name is sent by server. Pre master secret has the symmetric key. The handshake is still failing :( – frenzy man Feb 13 '18 at 10:18

0 Answers0