# How to derive a symmetric key from ECDH shared secret?

I am trying to implement the internal primitives of ECDH. Currently I'm able to multiply the receiver's public EC point with the sender's private key to arrive at the shared EC point. Next step is to input the x-coordinate of the shared point which is a bignum to a hashing function. The curve is secp521r1 so the shared x-coordinate is of size 66 bytes.

## Question 1

What format must the x-coordinate bignum be converted to before hashing it? The other party is openssl.

Is something like below sufficient...

...
print_hex(hash_input_buffer, shared_x_coordinate_bignum_bytes, 66);
...

void print_hex(unsigned char* to, unsigned char* from, int len)
{
for (int i = 0; i < len; ++i)
{
sprintf((char*)to + (i * 2), "%02x", from[i]);
}
}


OR

sprintf(hash_input_buffer, "%64x", shared_x_coordinate_bignum_bytes);


## Question 2

If the hashing function is SHA-512 and I want to derive an AES-256 key from it, should I just take the first 32 bytes of the 64 byte hash output?

• For Q2, yes that is perfectly sufficient – Richie Frame Sep 4 '15 at 6:18
• Regarding your update "the other party is openssl" do you mean that you are going to use it in TLS? (In which case you should do what TLS does.) – otus Sep 4 '15 at 9:48
• It is one-pass Diffie Hellman. We have the public key of the receiver and they will decrypt our CMS object using openssl. Following your line of thought, we basically need to replicate > openssl cms -encrypt -aes256 ecdh_kdf_md:sha512 -in ... -out ...  – sce Sep 4 '15 at 22:27
• So if you're using it in CMS, do what CMS does (which is mostly SEC1). – dave_thompson_085 Sep 5 '15 at 5:16

The general idea to derive keys from (ephemeral) Diffie-Hellman key agreement is to use a KBKDF - a key based key derivation function. KBKDFs are mostly ill defined with regards to what security requirements they adhere to. Fortunately creating a KBKDF isn't thought to be too hard. Using a cryptographically secure hash generally gets you a long way. You should however note that in that case the hash should not be vulnerable to timing- and other side channel attacks.

The input of a KBKDF or a hash is bits. Generally though only bytes are used as input. So you should be using the 66 bytes of the shared secret directly. Your conversion to hexadecimals likely already leaks side channel (timing) information. So the answer to the first question is: don't convert the x-coordinate at all.

You can indeed take any part of the SHA-512 hash as key. It is however more standard within the cryptographic community to take the first - leftmost - bytes of the resulting hash value. So that should answer question 2: just use the leftmost bytes as you're already doing.

If you want to be standards compliant and use a KBKDF then please take a look at HKDF-expand.

• 3.6.1 ANS X9.63 Key Derivation Function: what ended up working was a hash of the x-coordinate (bytes left in the native bignum format) || 00000001 (4 octet counter) || SharedInfo (depends on the implementation, we had to use an ASN1 structure indicating id-aes256-wrap) – sce Sep 11 '15 at 20:14
• I think that one is called KDF2 :) – Maarten Bodewes Sep 11 '15 at 22:07

What format must the x-coordinate bignum be converted to before hashing it?

Any format works as long as it uniquely encodes the shared secret and is used by all parties. So if your code doesn't need to interact with other implementations, you can use whichever you like.

If you need interoperability, you need to look at what others are using. E.g. SP 800-56 defines an integer-to-string conversion in Appendix C.2.

If the hashing function is SHA512 and I want to derive an AES256 key from it, should I just take the first 32 bytes of the 64 byte hash output?

Yes, that is fine. However, you can again find more complicated key derivation functions in the document I linked. E.g. if the keys are not ephemeral, you will probably want to add some additional data to allow deriving multiple keys from the same shared secret.

• The latest current version of SP 800-56 is at: nvlpubs.nist.gov/nistpubs/SpecialPublications/… I would edit it in myself, but the change is "2" to "3", and I need to change at least six characters (and I don't have edit rights, so I can't make the change + add some junk, then remove the junk). – Martin Bonner supports Monica Dec 14 '18 at 14:54
• @MartinBonner thanks, updated. Does not look like anything relevant to my answer changed. – otus Dec 14 '18 at 16:50