Search code examples
javascriptcryptographyelliptic-curvediffie-hellman

ECDH Key-Exchange with public keys of different lengths?


I'm working on a ECDH key-exchange implementation at the moment. I am using the P-384 curve for that. Other curves would be possible too, but I think the implementations should be quite similar.

Client (Javascript) and Server(Java) want to find a shared secret and therefore

1) The server creates a public and a private key.

2) The server sends the the public key to the client. Note: The public key is 120 bytes long.

3) The client creates private and public key. Note: public key is 97 bytes long and the private key has 48 bytes.

4) The client tries to calculate the shared secret. However,I get a "Bad argument" error.

On the client-side i use Google-Closure-Library with the e2e package. ( https://code.google.com/p/end-to-end/source/browse/javascript/crypto/e2e#e2e%2Fecc )

For implementation i had a look in the ecdh.js and the ecdh_test.html files.

My implementation on client side looks like that:

var serverPublicKeyStringAsHex = "3076301006072a8648ce3d020106052b8104....." //*
var serverPublicKey = goog.crypt.hexToByteArray(serverPublicKeyStringAsHex)
var bobKeyPair = e2e.ecc.Protocol.generateKeyPair("P_384"); 
var bobECDH = new e2e.ecc.Ecdh("P_384");
var bobMessage = bobECDH.bob(serverPublicKey, bobKeyPair['privKey']);

As mentioned, I get a "bad argument" error in the console. More detailed: Screenshot of the FF-console

I wanted to know if this error might appear because the length of the servers public key is wrong? If that's the reason, what might be the problem in my implementation? I am using the same EC on server-side.

With this "public-key-length" question I found out, that there are uncompressed and compressed representations of keys. However, I don't think that that might be my problem, as the key lenghts (server public key: 120 bytes, client public key: 97 bytes) don't match the described patterns ( field size + 1 versus 2* field size + 1)

Thanks for any kind of help, as I have spent so many hours on that problem and don't know what I could try next..

*If it is important to know, that's the full public key: 3076301006072a8648ce3d020106052b8104002203620004f87dc79943b20e0f57d61f8b7d02425baa4d1220b8b8c1e3596f5ab49ae6ad2acffad95e5860231821b4aedefe5cf1d0262563cffdc8dbe4f28973ebebf3985ba50c7b275888934dcd607007c288a5afaf196834395983cd7f01c548e5edca0b


Solution

  • What you have here is an ASN.1 encoded public key (probably X9.42 compatible). I presume that the JavaScript simply expects the uncompressed point encoded therein. So you need to parse the ASN.1 and retrieve the uncompressed point at offset 23 (decimal) within the public key.