When Public Key and Symmetric Key Work Together … Perfectly

With ECC (Elliptic Curve Cryptography), we have an opportunity to use both the power of public key encryption, with the speed and security…

Photo by Markus Winkler on Unsplash

When Public Key and Symmetric Key Work Together … Perfectly

With ECC (Elliptic Curve Cryptography), we have an opportunity to use both the power of public-key encryption, with the speed and security of symmetric key encryption. And, so we slowly move to the best practice for encryption, where there’s an increasing consensus around:

  • Public key encryption curve: P256, P384, P521, X25519 and X448.
  • Hashing method for key derivation (HKDF): SHA256, SHA384 and SHA512.
  • Symmetric key: 128-bit AES GCM and 256-bit AES GCM.

All of the above methods are compatible with most systems. For this Bob and Alice will pick a curve to define their key pair, and then use given hashing methods to derive an encryption key. This is normally achieved with HKDF (HMAC Key Derivation Function). For the actual encryption, we can use symmetric-key encryption, as this is the most efficient and much faster than public key encryption. Overall, with this, there is a general move towards using AEAD (Authenticated Encryption with Additional Data). A typical mode for this is GCM. So let’s build a hybrid encryption method with Golang.

Bob meets Alice

Now, let’s say that Bob will send an encrypted message to Alice. Alice will then generate a key pair (a public key and a private key). She then sends her public key to Bob, and he then uses this to derive a symmetric key for the encryption (S). He then encrypts the message using K and with AES GCM. Bob receives the cipher (C) and a value of R. From R, she can then derive S from her private key. With this key, she can decrypt the cipher text to derive the plaintext message.

In this method, Alice generates a random private key (dA) and the takes a point on an elliptic curve (G) and then determines her public key (QA):

QA=dA×G

G and QA are thus points on an elliptic curve. Alice then sends QA (her public key) to Bob. Next, Bob will generate:

R=r×G

S=r×QA

and where r is a random number generated by Bob. The symmetric key (S) is then used to encrypt a message. Alice will then receive the encrypted message along with R. She is then able to determine the same encryption key with:

S=dA×R

which is:

S=dA×(r×G)

S=r×(dA×G)

S=r×QA

and which is the same as the key that Bob generated. The method is illustrated here:

Here is the code [here]:

and a sample run for P256 and SHA-256 [here]:

Public key type: HPKE_KEM_P256_HKDF_SHA256
Params kem_id: 16 kdf_id: 1 aead_id: 2
Key exchange parameters:
Ciphersize: 65
EncapsulationSeedSize: 32
PrivateKeySize: 32
PublicKeySize: 65
SeedSize: 32
SharedKeySize: 32
Cipher parameters:
Key Length: 32
Key derivation function:
Extract size: 32
Message: Testing 123
Cipher: 353065393764366564633530623733346632376261653466376532663130343731353562323961633964373432666539656237616464
Decipher: Testing 123

Conclusions

We have libraries such as OpenSSL, and which carry a whole lot of baggage with them. With this, the support for a range of methods often introduces bugs and opportunities for security flaws. With libraries such as Cloudflare CIRCL, we don’t carry the legacy, and the methods used are often the best around. So, go do hybrid:

https://asecuritysite.com/golang/go_hybrid

If you want to learn more about ECIES, try here:

https://asecuritysite.com/ecies

and on CIRCL:

https://asecuritysite.com/circl