ns_crypto - Low level cryptographic functions based on the OpenSSL crypto library
These functions perform low-level cryptographic functions based on the OpenSSL crypto library. These commands are only implemented when NaviServer was compiled with OpenSSL support. The level of support depends on the version of OpenSSL. Versions earlier than OpenSSL 1.0 are not supported.
For some higher level functions (e.g. performing e.g. digest or HMAC operations of huge amounts of data) see e.g.ns_md and ns_hmac.
Note: some common options are described in a separate section below.
encrypt data following the Authenticated Encryption with Associated Data (AEAD) scheme, which provides confidentiality, integrity, and authenticity. Currently, only GCM mode (Galois/Counter Mode) is supported. For details about AEAD in GCM mode, see e.g. https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
AEAD has the following properties:
Nobody will be able to get any information about the encrypted plaintext, except the length.
Without the key it is impossible to change the plaintext underlying the ciphertext undetected.
Encrypting the message and decrypting the ciphertext is done with the same key.
The encryption is randomized. Two messages with the same plaintext will not yield the same ciphertext. This prevents attackers from knowing which ciphertext corresponds to a given plaintext.
The function returns a dict consisting of bytes and the authentication tag used for decryption.
The option -aad can be used to specify Additional Authenticated Data (AAD), which is data handled by encryption, which is sent in clear text. The encryption still provides authenticity for AAD. AAD can be used e.g. for addresses, ports, sequence numbers, protocol version numbers.
The option -cipher can be used to specify the used cipher such as e.g. aes-128-gcm (default) or aes-256-gcm. Possible values are defined by OpenSSL.
The option -iv specifies the initialization vector (IV) for encryption. IV is essentially a nonce value, a value that is unique within the specified context (see the NIST publication for details).
The option -key specifies the key for the encryption.
The argument input is the data to be encrypted.
When the option -binary is specified, it applies to -key, -aad, -iv, input.
% ns_crypto::aead::encrypt string -cipher aes-128-gcm -iv 123456789 -key secret "hello world" bytes fa260f97eae35e3e3df0b7 tag 93654f78fd189b559c091acb410a0040
This function implements the inverse function of ns_crypto::aead::encrypt string. Note that the resulting tag of the encryption result is used as an input for decryption. The result is a byte string of the decrypted input (no dict).
When the option -binary is specified, it applies to -key, -aad, -iv, and -tag. The argument input (the cipher text) is always treated as byte array.
% set d [ns_crypto::aead::encrypt string -cipher aes-128-gcm -iv 123456789 \ -key secret -encoding binary \ "hello world"] % ns_crypto::aead::decrypt string -cipher aes-128-gcm -iv 123456789 \ -key secret -tag [dict get $d tag] \ -encoding binary [dict get $d bytes]
Compute a password hash or a derived key based on the Argon2 family of functions (RFC 9106, published in 2021) and return the hash (named "tag" in the RFC) in the specified encoding (default hex).
Argon2 is a modern replacement for crypt and bcrypt and derives more secret keys from a secret string. Argon2 was selected as the winner of the 2015 Password Hashing Competition and is the recommended password hashing algorithm of the OWASP project. The algorithm is defined in 3 different variants, named Argon2d (providing resistance GPU cracking attacks), Argon2i (resist side-channel attacks) and Argon2id (hybrid version, based on Argon2d and Argon2i).
Argon2 has several parameters to provide control over execution time, required memory, and degree of parallelism to tailor security requirements of a site, to provide high security against modern password cracking hardware. The function requires the compilation of NaviServer against OpenSSL 3.2 or newer. The names of the parameters correspond to the names of the parameters provided for the C-level API, so additional information can be obtained from the OpenSSL documentation.
When the option -binary is specified, it applies to the input parameters -ad, -password, -salt, and -secret.
The provided -salt must be at least 8 bytes.
The option -iter can be used to specify the number of iterations of the algorithm (sometimes named "passes"). The default value is 3.
The option -lanes can be used to specify the number of memory segments that can be processed in parallel. The number of used threads depends on the -threads parameter. The provided value influences the result. The default value of "lanes" is 1.
The option -memcost can be used to specify the memory cost specified in 1 KB blocks. The default value is 1024 (i.e. 1 MB).
The option -outlen can be used to specify the length of the resulting tag in bytes. The default value is 64.
The option -secret can be used to specify an additional secret (sometimes called pepper) to be used an optional secret data used along the password.
The option -threads can be used to specify the number of threads for the computation of the lanes. The provided value does not influence the result, but just the duration of the command. The default value is 1.
The option -variant can be used to specify the variant of the command. The default value is "Argon2id".
% ::ns_crypto::argon2 -variant argon2id -salt saltsalt -password 42 -outlen 16 d508696098fa42e70058a3141d1c7464
Generate an EC pemfile without the need of an external command. If no -name is provided (name of the elliptic curve), prime256v1 is assumed. An other popular candidate is secp384r1. The -pem denotes the name of the output file, which is in PEM format.
This function requires OpenSSL compiled with EC support enabled.
% ns_crypto::eckey generate -name prime256v1 -pem /tmp/priv.key.pem
When the option -binary is specified, it applies to -string.
This function requires OpenSSL compiled with EC support enabled.
Obtain the private key in various encodings from an elliptic curve PEM file. When the .pem-file is secured by a passphrase, this has to be provided via -passphrase.
This function requires OpenSSL compiled with EC support enabled.
Generate a shared secret based on the private key from the .pem file and the provided public key. When the .pem file is secured by a passphrase, this has to be provided via -passphrase.
When the option -binary is specified, it applies to pubkey.
This function requires OpenSSL 1.1 or newer, compiled with EC support enabled.
Obtain the public key in various encodings from an elliptic curves PEM file. When the .pem file is secured by a passphrase, this has to be provided via -passphrase.
This function requires OpenSSL compiled with EC support enabled.
Return a keyed-hash message authentication code (HMAC) for the specified key and message using the specified message digest algorithm and return it in the specified encoding. An HMAC is a message authentication code of a key (secret) with a message. It may be used to simultaneously verify both the data integrity and the authentication of a message. For details of HMAC, consult RFC 4231.
When the option -binary is specified, it applies to key and message.
% ns_hmac string -digest sha256 "Jefe" "what do ya want for nothing?" 5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843
This low-level function operates just on an input string (which has to be in memory). In order to compute HMACs on large data, use ns_hmac.
Return a message digest for the provided message and return it in the specified encoding. Optionally, this function can return a signature based on the provided private key, or it can verify such a signature.
When the option -binary is specified, it applies to message.
% ns_crypto::md string -digest sha256 "what do ya want for nothing?" b381e7fec653fc3ab9b178272366b8ac87fed8d31cb25ed1d0e1f3318644c89c
This low-level function operates just on an input string (which has to be in memory). In order to compute digests on large data (such as from files), use ns_md.
The ns_crypto::md string interface can be as well used for digital signing and verification of the signature, when the respective keys are passed in as PEM files. When the PEM file is secured by a passphrase, the option -passphrase ... has to be used to decipher the key.
The option -sign pemfile is used to sign the given message.
The options -verify pemfile and -signature signatureString can be used to verify a signature using the private key from provided PEM file. The signatureString is required to be a binary string, therefore, produced with the output option -encoding binary in the example below:
% set sig [::ns_crypto::md string \ -digest sha1 \ -encoding binary \ -sign /usr/local/src/naviserver/myprivate.pem \ "abcdefghijklmnopqrstuxvwxyz\n"] % set vfy [::ns_crypto::md string \ -digest sha1 \ -verify /usr/local/src/naviserver/myprivate.pem \ -signature $sig \ "abcdefghijklmnopqrstuxvwxyz\n"] 1
The PEM files provided to -sign and -verify are private keys that can have the following key types: CMAC, DSA, ECDSA, HMAC and RSA.
Derive keys based on message digests. See: RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF) https://tools.ietf.org/html/rfc5869
When the option -binary is specified, it applies to message.
This function requires OpenSSL 1.1.0.
Sign a message according to the Voluntary Application Server Identification (VAPID) for Web Push https://www.rfc-editor.org/rfc/rfc8292.html
Essentially, this is a special form of a signed message digest based on elliptic curve cryptography. See also: Generic Event Delivery Using HTTP Push https://tools.ietf.org/html/rfc8030
The signing key is taken from the provided .pem file. When the .pem file is secured by a passphrase, this has to be provided via -passphrase.
When the option -binary is specified, it applies to message.
This function requires OpenSSL compiled with EC support enabled.
Return the specified number of random bytes in the specified encoding (default hex).
% ns_crypto::randombytes 20 3191eb4360a3dc9b5ef667641b264d43aa1019aa
Compute a password hash based on the scrypt Password-Based Key Derivation Function (RFC 7914) and return the specified number of random bytes in the specified encoding (default hex).
The scrypt function is a modern replacement for crypt and bcrypt and derives more secret keys from a secret string. It is based on memory-hard functions, which offer added protection against attacks using custom hardware and GPU arrays. The function requires the compilation of NaviServer against OpenSSL 3.0 or newer.
The scrypt function is as well used in many cryptocurrencies as a proof-of-work algorithm.
Colin Percival. 2009. Stronger key derivation via sequential memory-hard functions. In BSDCan 09: The Technical BSD Conference.
When the option -binary is specified, it applies to -salt and -secret.
% ::ns_crypto::scrypt -secret "password" -salt NaCl -n 1024 -r 8 -p 16 fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b373162 2eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640 % time {::ns_crypto::scrypt -secret "password" -salt NaCl -n 1024 -r 8 -p 16} 42011 microseconds per iteration
Compute a password hash based on PBKDF2 (Password-Based Key Derivation Function 2, RFC 2898). This function is used to reduce vulnerabilities of brute-force attacks against password hashes and is used e.g. in SCRAM (Salted Challenge Response Authentication Mechanism). It can be used e.g. for SCRAM-sha1 and SCRAM-sha-256. The hash function of SCRAM is PBKDF2 (RFC2898) with HMAC as the pseudorandom function (PRF) and with dkLen == output length of HMAC == output length of the digest function.
The function requires at least OpenSSL 1.1.1.
When the option -binary is specified, it applies to -salt and -secret.
The option -dklen specifies the length of the output key and is by default the same as the output length of the used digest.
The option -iterations specifies the number of iterations (repeated HMAC operations) and defaults to 4096. RFC 7677 recommends 15K iterations.
% ::ns_crypto::pbkdf2_hmac -secret "password" -iterations 4096 -salt "salt" -digest sha1 4b007901b765489abead49d926f721d065a429c1 % time {::ns_crypto::pbkdf2_hmac -secret "pass\0word" -iterations 15000 -salt "sa\0lt" -dklen 16} 16027 microseconds per iteration