I'm currently looking into OpenSSL and its API and I'm not really familiar with cryptography. So I was looking at the example on asymmetric encryption of an envelope. And it says the message is symmetrically encrypted with a session key that is then encrypted with the actual asymmetric key. Then my question would be how are the session keys generated and how could I search to find this concept in some other programming language.


1 Answer 1


The session key can be generated with a CSPRNG by Alice. Alice and Bob will already have static key pairs that don't change. Alice and Bob will create ephemeral key pairs, and these are newly generated every session.

Alice then signs her ephemeral public key with her static private key and sends this to Bob - this public key doesnt have to be encrypted in any way as it is a public key. Bob receives this, and verifies the signature using Alice's static public key. Bob goes through the same protocol so Alice can have his ephemeral public key.

Now there are two ways that this can go - a KEX (key exchange) or a KEM (key encapsulation mechanism).

For a KEX, both Alice and Bob combine their own ephemeral private key with the others public key, using DH(E) or ECCDH(E). This leaves them both with the same shared secret, which can be passed through HKDF to create a correctly formatted symmetric key of the desired length.

For a KEM, Alice would create a symmetric key of desired length, sign it with her static private key, and then encrypts it with Bob's ephemeral public key, and sends it to Bob, who can decrypt and verify they key. RSA would have to be used for this.

For a programming languages there's usually a module for pseudorandom numbers (PRNG) and for cryptographically secure pseudorandom number generators (CSPRNG). In Python, the random module is a PRNG, and the secrets module or os.urandom is a CSPRNG. For cryptography, there is a PyCryptodome or cryptography among some others.

  • $\begingroup$ There are also typically different pairs of keys for signing and encryption. And static Diffie-Hellman, if you chose an algorithm that uses that instead of encryption. $\endgroup$ Dec 11, 2019 at 23:58
  • $\begingroup$ Thanks, updated answer $\endgroup$
    – SamG101
    Dec 12, 2019 at 8:02
  • $\begingroup$ Thanks for the answer. I have one more question: It says EVP_Sealinit generates a key (of the right length?, so 256bits here). And does it encrypt this key with the PublicKey (RSA i guess) or the provided type? So then does EVP_SealUpdate encrypt the plaintext with the type or the PublicKey? If it does encrypt with the type provided, then how does SealInit generate the right key length? $\endgroup$
    – Nerix
    Dec 12, 2019 at 16:53
  • $\begingroup$ The symmetric key length encrypted_key_len is passed into the function as a parameter, and so will be predefined. I believe that this symmetric key is then encrypted with the recipients public key (RSA). Any messages after the symmetric key is sent will be encrypted with this symmetric key. The keylength will be a fixed size, as it will have gone through something similar to HKDF, to create a key of length 256-bits, for example. $\endgroup$
    – SamG101
    Dec 12, 2019 at 17:02
  • $\begingroup$ ekl is a parameter but it is a pointer used for output; ekl[i] is set to the length of the encryption under pubk[i] of the secret key, which is very different from the length of the secret key itself. And nothing similar to HKDF is used; in particular for RSA this is a (simple) key wrapping, NOT RSA-KEM. See the man page. @Nerix: each EVP_CIPHER object has a fixed key length even when the algorithm itself doesn't e.g. EVP_aes_256_cbc() vs EVP_aes_128_cbc() $\endgroup$ Dec 13, 2019 at 4:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.