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.
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.