Resolution: Won't Do
Affects Version/s: None
Fix Version/s: None
Erlang/OTP is currently using OpenSSL to provide is cryptography features. However, there are a lot of ways that OpenSSL's API can be misused easily by well-intended developers that don't possess a background in cryptography engineering.
- Using `RAND_bytes()` in an application that forks, since it isn't the OS's CSPRNG.
- Encrypting with AES-ECB or AES-CBC mode, without a MAC.
- Encrypting with AES-CCM or AES-GCM and reusing a nonce (which is likely, given how small the nonce is for these modes).
- Encrypting large messages with RSA in "ECB mode" (breaking the message into chunks and encrypting each message with the RSA public key independently)
- Encrypting messages with RSA but using PKCS1v1.5 padding (see: Daniel Bleichenbacher's 1998 padding oracle attack)
- Using Weierstrass curves for ECDH or ECDSA, and forgetting to validate that the point received are on the order of the curve. (This leaks your secret key.)
- Using ECDSA and reusing a nonce. (Sony did this with the PS3 ECDSA signing.)
An attractive alternative would be to use libsodium, for which bindings already exist. https://download.libsodium.org/doc/bindings_for_other_languages/
With libsodium you get:
- X25519 (ECDH over Curve25519), which is implements a Montgomery ladder construction and is constant-time. See RFC 7748.
- Ed25519 (EdDSA over Curve25519), which uses deterministic nonces and is also side-channel-resistant. See RFC 8032.
- Xsalsa20poly1305, which uses an extended-nonce Salsa20 so you can safely generate a 192-bit random nonce for each message and never worry about collisions. (Birthday collision: 50% after 2^96 messages, which can each be up to 2^72 bytes long. a.k.a. Not going to happen before the heat death of the universe.)
- Argon2i for password validation and key derivation.
- SipHash for hash tables.
Furthermore, the API provided by libsodium lends towards a lower incidence of misuse. In pseudocode:
key = randombytes_buf(32)
nonce = randombytes_buf(24) /* or a constant */
ciphertext = crypto_secretbox(plaintext, nonce, key)
decrypted = crypto_secretbox_open(ciphertext, nonce, key)
Public key encryption is handled by crypto_box() or crypto_box_seal(). All of these features are documented here: https://download.libsodium.org/doc/