NaviServer Built-in Commands – 5.1.0
ns_crypto - Low level cryptographic functions based on the OpenSSL crypto library
These functions provide low-level cryptographic operations based on the OpenSSL crypto library. These commands are only implemented when NaviServer was compiled with OpenSSL support. The available command set depends on the OpenSSL version used at build time. Versions earlier than OpenSSL 1.1 are not supported.
The commands cover both primitive operations (such as message digests, HMAC, password-based key derivation, authenticated encryption, and random byte generation) and public-key based operations such as key generation, digital signatures, key agreement, and key encapsulation.
In addition to classical cryptographic algorithms, NaviServer supports modern and post-quantum cryptography when available via OpenSSL providers. This includes post-quantum signature schemes (e.g. ML-DSA, SLH-DSA) and key encapsulation mechanisms (e.g. ML-KEM), enabling applications to prepare for cryptographic environments resilient against attacks based on quantum algorithms such as Shor's algorithm.
For some higher level functions (e.g. digest or HMAC operations on huge amounts of data) see for example ns_md and ns_hmac.
The newer public-key related command families are grouped by cryptographic purpose rather than by concrete key type. These newer purpose-oriented groups depend on provider-based OpenSSL support and are therefore available only with newer OpenSSL versions. In particular, ns_crypto::agreement requires OpenSSL 3.0 or newer, while post-quantum oriented commands such as ns_crypto::kem and parts of ns_crypto::signature require OpenSSL 3.5 or newer.
ns_crypto::signature provides commands for digital signature algorithms. Its purpose is to generate signing keys, extract public keys, create signatures, and verify signatures. This family covers classical algorithms such as RSA as well as newer and post-quantum algorithms such as Ed25519, ML-DSA, SLH-DSA, or SM2 depending on OpenSSL support.
ns_crypto::agreement provides commands for key agreement algorithms. Its purpose is to generate agreement keys, extract public keys, and derive shared secrets from a private key and a peer public key. Typical examples are X25519, X448, ECDH via EC keys, and finite field Diffie-Hellman groups, depending on OpenSSL support.
ns_crypto::kem provides commands for key encapsulation mechanisms. Its purpose is to generate KEM keys, extract public keys, encapsulate shared secrets for a recipient, and decapsulate them again. This family is used in particular for post-quantum key establishment mechanisms such as ML-KEM, depending on OpenSSL support.
ns_crypto::key provides generic key inspection and extraction operations independent of the key type. Its purpose is to query properties of keys (e.g. type, capabilities such as signature, KEM, or agreement support) and to provide a uniform interface for working with PEM-encoded key material across all algorithm families.
This grouping is intended to make the API easier to understand and use. Instead of requiring users to start from a concrete key type and then determine which operations are applicable, the command structure follows the intended cryptographic task: signing, shared-secret derivation, key encapsulation, or generic key inspection and extraction. This makes the interface clearer for modern algorithms, where several unrelated key families may serve the same purpose, and it allows new OpenSSL-supported algorithms to be integrated more naturally.
The API is designed to align with modern cryptographic practice, including post-quantum and hybrid key establishment mechanisms introduced in recent OpenSSL versions.
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]
Generate a new key pair for key agreement.
This command provides key generation for key agreement algorithms analogous to ns_crypto::signature generate for signature algorithms and ns_crypto::kem generate for key encapsulation mechanisms.
The key type is selected via -name. The value is passed to OpenSSL's provider-based key management layer and is therefore not restricted to a fixed set of algorithms. The available values depend on the OpenSSL version and configured providers.
upported values include key agreement algorithms such as X25519 and X448.
Not all OpenSSL key types support key agreement operations. When a key type that does not provide key agreement is specified, the command returns an error.
When -name is omitted, a provider-dependent default algorithm is used (currently X25519 when available).
The option -group specifies the domain parameters or named group used for key generation. For the EC algorithm, the option -group specifies the elliptic curve to use and defaults to prime256v1. For key agreement algorithms such as DH and DHX, this option is required and must be set to a valid group name supported by the underlying OpenSSL provider (e.g., prime256v1, ffdhe2048, or modp_2048). For algorithms with fixed domain parameters such as X25519 and X448, the -group option is optional and typically not needed; when provided, it must match the algorithm name. An error is returned if an unsupported or incompatible group is specified.
Valid group names depend on the underlying OpenSSL provider. Common examples are prime256v1, ffdhe2048, and modp_2048. Please check used OpenSSL documentation.
The generated key is returned as a PEM encoded private key. When -outfile is specified, the key is written to the provided file instead.
The generated PEM contains the private key; the corresponding public key can be obtained via ns_crypto::agreement pub.
# Generate a new key using the default algorithm set pem [ns_crypto::agreement generate] # Generate a specific agreement key set pem [ns_crypto::agreement generate -name X448] # Generate a key and write it to a file ns_crypto::agreement generate -name X25519 -outfile /tmp/agreement.pem # Generate an X25519 agreement key set pem [ns_crypto::agreement generate -name X25519] # Generate an EC agreement key on a named curve set pem [ns_crypto::agreement generate -name EC -group prime256v1] # Generate a DH agreement key for a named safe-prime group set pem [ns_crypto::agreement generate -name DH -group ffdhe2048] # Generate a DHX agreement key for a MODP group set pem [ns_crypto::agreement generate -name DHX -group modp_2048]
This function requires OpenSSL 3.0 or newer.
Return the public key corresponding to an agreement key.
This command is analogous to ns_crypto::signature pub and ns_crypto::kem pub, providing a uniform interface for extracting public keys from PEM-encoded key material.
The argument to -pem may be either a PEM file name or a PEM string containing a private key. When the private key is encrypted, provide the passphrase via -passphrase.
The key must support key agreement operations.
The result is returned as a PEM encoded public key (BEGIN PUBLIC KEY). When -outfile is specified, the result is written to the provided file instead.
# Extract the public key from a private key set pubpem [ns_crypto::agreement pub -pem /tmp/agreement.pem] # Write the public key to a file ns_crypto::agreement pub -pem /tmp/agreement.pem -outfile /tmp/agreement-pub.pem
This function requires OpenSSL 3.0 or newer.
Derive a shared secret via key agreement.
The local key is provided via -pem and must contain a private key in PEM format. The peer key is provided via -peer and must contain a public key in PEM format. Both arguments may be either PEM file names or PEM strings.
When the private key is encrypted, provide the passphrase via -passphrase.
Both keys must support key agreement operations and must be compatible with each other.
The derived shared secret is returned encoded according to -encoding, which defaults to hex.
This command implements key agreement (shared secret derivation). It does not support key transport mechanisms such as RSA. Post-quantum key establishment is provided via ns_crypto::kem encapsulate and ns_crypto::kem decapsulate.
# Derive a shared secret via X25519
set pemA [ns_crypto::agreement generate -name X25519]
set pemB [ns_crypto::agreement generate -name X25519]
set pubA [ns_crypto::agreement pub -pem $pemA]
set pubB [ns_crypto::agreement pub -pem $pemB]
set secretA [ns_crypto::agreement derive -pem $pemA -peer $pubB]
set secretB [ns_crypto::agreement derive -pem $pemB -peer $pubA]
string equal $secretA $secretB
# Obtain the shared secret as binary data
set secret [ns_crypto::agreement derive \
-pem $pemA \
-peer $pubB \
-encoding binary]
This function requires OpenSSL 3.0 or newer.
Computes 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 required option -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
Construct an elliptic curve public key from affine point coordinates. The coordinates are provided via -x and -y and are interpreted either as Tcl binary data when -binary is specified, or as ordinary strings otherwise.
The elliptic curve is selected via -curve. For prime256v1 (a.k.a. secp256r1) the coordinates must be 32 bytes each.
The result is returned either as a PEM encoded public key (BEGIN PUBLIC KEY) when -format pem is selected (the default), or as DER encoded SubjectPublicKeyInfo when -format der is selected.
When -outfile is specified, the generated public key is written to the provided file. Otherwise, it is returned as the command result.
When -format der is selected and no -outfile is specified, the result is returned as binary Tcl data. If a textual representation is required, it can be obtained using Tcl commands such as binary encode.
The command validates that the provided coordinates form a valid point on the selected curve. Invalid points raise an error.
This function requires OpenSSL compiled with EC support enabled.
ns_crypto::eckey generate -name prime256v1 -outfile /tmp/p256-priv.pem
set pub [ns_crypto::eckey pub -pem /tmp/p256-priv.pem -encoding binary]
if {[string length $pub] != 65 || [string index $pub 0] ne "\x04"} { error "bad point"}
set x [string range $pub 1 32]
set y [string range $pub 33 64]
# Return the reconstructed public key as PEM string
set pubpem [ns_crypto::eckey fromcoords -curve prime256v1 -x $x -y $y -binary]
# Write the reconstructed public key directly to a PEM file
ns_crypto::eckey fromcoords -curve prime256v1 -x $x -y $y -binary \
-outfile /tmp/p256-pub.pem
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 -outfile denotes the name of the output file, which is in PEM format. If -outfile is not specified, the command returns the PEM encoded private key as result.
This function requires OpenSSL compiled with EC support enabled.
% ns_crypto::eckey generate -name prime256v1 -outfile /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. It is possible to provide the filename of the PEM file or its content as a string. 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. It is possible to provide the filename of the PEM file or its content as a string. 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.
Returns the public key corresponding to the provided elliptic curve private key.
The argument to -pem may be either a PEM file name or a PEM string. When the private key is encrypted, provide the passphrase via -passphrase.
The default output format is raw. In this format, the public key is returned as the uncompressed EC point (leading 0x04, followed by X and Y coordinates). The representation is encoded according to -encoding, which defaults to hex.
When -format pem is specified, the result is returned as a PEM encoded SubjectPublicKeyInfo structure (i.e., a BEGIN PUBLIC KEY block).
When -format der is specified, the result is returned as a DER encoded SubjectPublicKeyInfo. If no -outfile is specified, the DER data is returned as binary Tcl Data.
When -outfile is specified, the result is written to the provided file instead of being returned. This option requires -format pem or -format der.
The option -encoding is only valid with -format raw.
# Return public key in raw format (default hex encoding) set pub [ns_crypto::eckey pub -pem /tmp/p256-priv.pem] # Return public key in raw format with binary encoding set pubBin [ns_crypto::eckey pub -pem /tmp/p256-priv.pem -encoding binary] # Return public key as PEM string set pubpem [ns_crypto::eckey pub -pem /tmp/p256-priv.pem -format pem] # Write public key as PEM file ns_crypto::eckey pub -pem /tmp/p256-priv.pem -format pem -outfile /tmp/p256-pub.pem # Return public key as DER (binary Tcl value) set pubder [ns_crypto::eckey pub -pem /tmp/p256-priv.pem -format der]
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.
Generate a new private key for use with key encapsulation mechanisms.
The key type is selected via -name. The available values depend on the OpenSSL version and configured providers. Typical examples are ML-KEM-* and, depending on OpenSSL support, EC for EC-based KEM operation.
The option -group specifies the domain parameters or named group used for key generation. For the EC algorithm, the option -group specifies the elliptic curve to use and defaults to prime256v1. For algorithms with fixed domain parameters or algorithms that do not use named groups, this option is not supported.
The generated key is returned as a PEM encoded private key. When -outfile is specified, the key is written to the provided file instead.
# Generate an ML-KEM key set pem [ns_crypto::kem generate -name ml-kem-768] # Generate an EC key usable for KEM encapsulation set pem [ns_crypto::kem generate -name EC -group prime256v1]
This function requires OpenSSL 3.5.
Returns the public key corresponding to the provided private key.
The argument to -pem may be either a PEM file name or a PEM string. When the private key is encrypted, provide the passphrase via -passphrase.
The key must represent a key encapsulation mechanism (KEM) key.
When -outfile is specified, the public key is written to the file. Otherwise, it is returned as command result.
# Obtain the public key as PEM string set pub [ns_crypto::kem pub -pem $pem]
This function requires OpenSSL 3.5.
Encapsulate a shared secret for a KEM public key.
The argument to -pem may be either a PEM file name or a PEM string. It may contain a KEM public key or private key. When a private key is provided, the corresponding public key is derived automatically. If the private key is encrypted, specify the passphrase via -passphrase.
The key must represent a key encapsulation mechanism (KEM) key.
The result is a dictionary containing the keys ciphertext and secret. Both values are encoded according to -encoding. When -encoding is omitted, the result values are returned as hex.
# Encapsulate via PEM private key set pem [ns_crypto::kem generate] set r [ns_crypto::kem encapsulate -pem $pem] # Encapsulate via PEM public key set pub [ns_crypto::kem pub -pem $pem] set r [ns_crypto::kem encapsulate -pem $pub] dict get $r ciphertext dict get $r secret
This function requires OpenSSL 3.5.
Decapsulate a shared secret from a KEM ciphertext using the provided private key.
The argument to -pem may be either a PEM file name or a PEM string. When the private key is encrypted, provide the passphrase via -passphrase.
The key must represent a key encapsulation mechanism (KEM) key.
The argument to -ciphertext must contain the ciphertext as binary data.
The recovered shared secret is returned encoded according to -encoding. When -encoding is omitted, the result is returned as hex.
Important: -ciphertext expects binary ciphertext. Therefore, when using the default hex output of ns_crypto::kem encapsulate, decode the ciphertext value before passing it via -ciphertext. Alternatively, request -encoding binary from ns_crypto::kem encapsulate.
# Decapsulate from default hex output
set pem [ns_crypto::kem generate]
set r [ns_crypto::kem encapsulate -pem $pem]
set ct [dict get $r ciphertext]
set secret [ns_crypto::kem decapsulate \
-pem $pem \
-ciphertext [binary decode hex $ct]]
# Decapsulate from binary output
set pub [ns_crypto::kem pub -pem $pem -encoding binary]
set r [ns_crypto::kem encapsulate \
-name ml-kem-768 \
-pub $pub \
-encoding binary]
set ct [dict get $r ciphertext]
set secret [ns_crypto::kem decapsulate \
-pem $pem \
-ciphertext $ct \
-encoding binary]
This function requires OpenSSL 3.5.
Generate a new private key of the specified type.
This command provides generic provider-based key generation. In contrast to the purpose-oriented command families ns_crypto::signature, ns_crypto::agreement, and ns_crypto::kem, it does not require that the generated key supports a particular cryptographic operation.
The key type is selected via -name. The available values depend on the OpenSSL version and configured providers.
The option -group specifies the domain parameters or named group used for key generation. For the EC algorithm, the option -group specifies the elliptic curve to use and defaults to prime256v1. For algorithms such as DH and DHX, this option is required. For algorithms with fixed domain parameters such as X25519 and X448, it is optional and typically not needed.
The generated key is returned as a PEM encoded private key. When -outfile is specified, the key is written to the provided file instead.
This command is intended as a generic fallback for key types supported by OpenSSL. Whether a generated key can be used with ns_crypto::signature, ns_crypto::agreement, or ns_crypto::kem depends on the capabilities of the key type and can be inspected via ns_crypto::key info.
# Generate a generic SM2 key set pem [ns_crypto::key generate -name SM2] # Generate an EC key on a named curve set pem [ns_crypto::key generate -name EC -group prime256v1] # Generate a DH key for a named group set pem [ns_crypto::key generate -name DH -group ffdhe2048] # Generate a generic EC key and use it for signatures set pem [ns_crypto::key generate -name EC -group prime256v1] set sig [ns_crypto::signature sign -pem $pem -- "hello world"]
This function requires OpenSSL 3.0 or newer.
Return information about a key stored in PEM format.
The argument to -pem may be either a PEM file name or a PEM string. It may contain either a public or a private key. When the key is encrypted, provide the passphrase via -passphrase.
The result is a Tcl dictionary containing properties of the key. The available fields depend on the key type and the OpenSSL version.
The dictionary always contains at least:
type — the key type as returned by ns_crypto::key type
signature — boolean indicating whether the key provides a digital signature algorithm ((i.e., supports sign/verify operations directly). This is independent of digest support; key agreement (e.g., X25519) and encapsulation (ML-KEM) keys do not support signatures.
requiresdigest — boolean indicating whether the signature algorithm requires a message digest (hash function) to be specified. This field is only present when signature is true.
For classical algorithms (e.g., RSA, DSA, ECDSA), a digest such as sha256 must be provided. For algorithms with built-in hashing (e.g., Ed25519, Ed448, ML-DSA, SLH-DSA), no digest is required and specifying one is not supported.
kem - boolean indicating whether the key provides a key encapsulation mechanism.
Additional fields may include:
bits — key size in bits (e.g., RSA, DSA, DH, EC)
curve — curve name for elliptic curve keys (e.g., prime256v1)
securityBits — the estimated cryptographic strength of the key.
securityCategory — an integer indicating the security category of the key as defined by the underlying OpenSSL provider.
The field bits denotes the size of the key or its domain parameters, while securityBits denotes the estimated cryptographic strength of the key. These values differ for many algorithms (e.g., RSA-2048 has 2048 bits but about 112 bits of security).
Security categories are primarily used for post-quantum algorithms and correspond to standardized security levels (e.g., NIST PQC categories 1, 3, and 5). Higher values indicate stronger security guarantees against both classical and quantum attacks.
This field is only present when the OpenSSL provider exposes this information. It is typically available for post-quantum algorithms such as ML-KEM and ML-DSA, but not for classical algorithms like RSA or EC.
The presence and naming of fields depend on the key type and OpenSSL capabilities. New fields may be added in future versions as additional key properties become available.
This command is intended for lightweight inspection of keys. It does not perform validation beyond what OpenSSL provides.
# Inspect key properties
set info [ns_crypto::key info -pem /tmp/key.pem]
dict get $info type
dict exists $info bits
dict exists $info curve
if {[dict get $info type] eq "ec"} {
puts "curve: [dict get $info curve]"
}
Extract the raw private key material from a PEM-encoded private key.
The argument to -pem may be either a PEM file name or a PEM string. It must contain a private key. When the private key is encrypted, provide the passphrase via -passphrase.
The result is returned in an algorithm-specific raw representation, where supported. The output encoding is controlled via -encoding, which defaults to hex.
Return the public key corresponding to the provided key.
The argument to -pem may be either a PEM file name or a PEM string. It may contain either a public key or a private key. When a private key is provided, the corresponding public key is derived. When the private key is encrypted, provide the passphrase via -passphrase.
When -format is omitted, the default format is raw. In this case, the public key is returned in an algorithm-specific raw representation encoded according to -encoding, which defaults to hex.
When -format pem is specified, the public key is returned as a PEM encoded SubjectPublicKeyInfo (BEGIN PUBLIC KEY). In this case, -outfile may be used to write the result to a file.
The option -outfile is supported only together with -format pem.
# Obtain the raw public key as hex set pub [ns_crypto::key pub -pem $pem] # Obtain the raw public key as binary set pub [ns_crypto::key pub -pem $pem -encoding binary] # Obtain the public key as PEM set pubpem [ns_crypto::key pub -pem $pem -format pem] # Write the PEM encoded public key to a file ns_crypto::key pub -pem $pem -format pem -outfile /tmp/key-pub.pem
Return the type of a key stored in PEM format.
The argument to -pem may be either a PEM file name or a PEM string. It may contain either a public or a private key. When the key is encrypted, provide the passphrase via -passphrase.
The result is a lowercase string naming the key type as reported by OpenSSL (e.g., rsa, ec, ed25519, ml-kem-768). The exact naming depends on the OpenSSL version and available providers.
This command is a thin wrapper around OpenSSL key type introspection and does not impose its own naming scheme.
# Determine key type
set type [ns_crypto::key type -pem /tmp/key.pem]
if {$type eq "ec"} {
puts "elliptic curve key"
}
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. It is possible to provide the filename of the PEM file or its content as a string.
The options -verify pemfile and -signature signatureString can be used to verify a signature using the private key from provided PEM file. It is possible to provide the filename of the PEM file or its content as a string. 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://datatracker.ietf.org/doc/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://datatracker.ietf.org/doc/html/rfc8030
The signing key is taken from the provided .pem file. It is possible to provide the filename of the PEM file or its content as a string. 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.
Returns the specified number of random bytes in the specified encoding (default hex).
% ns_crypto::randombytes 20 3191eb4360a3dc9b5ef667641b264d43aa1019aa
Generate a new private key for use with signature algorithms.
The key type is selected via -name. The available values depend on the OpenSSL version and configured providers. Typical examples are RSA, EC, Ed25519, Ed448, ML-DSA-*, SLH-DSA-*, and SM2, depending on OpenSSL support.
The option -group specifies the domain parameters or named group used for key generation. For the EC algorithm, the option -group specifies the elliptic curve to use and defaults to prime256v1. For algorithms with fixed domain parameters or algorithms that do not use named groups, this option is not supported.
The generated key is returned as a PEM encoded private key. When -outfile is specified, the key is written to the provided file instead.
# Generate an ML-DSA signing key set pem [ns_crypto::signature generate -name ml-dsa-65] # Generate an EC signing key on a named curve set pem [ns_crypto::signature generate -name EC -group prime256v1] # Generate an SM2 signing key set pem [ns_crypto::signature generate -name SM2]
This function requires OpenSSL 3.0 or newer.
Return the public key corresponding to a signature key.
This command is analogous to ns_crypto::kem pub and ns_crypto::eckey pub, providing a uniform interface for extracting public keys from PEM-encoded key material.
The argument to -pem may be either a PEM file name or a PEM string containing a private or public key. When the private key is encrypted, provide the passphrase via -passphrase.
The result is returned as a PEM encoded public key (BEGIN PUBLIC KEY). When -outfile is specified, the result is written to the provided file instead.
# Extract public key from private key set pubpem [ns_crypto::signature pub -pem /tmp/sigkey.pem] # Write public key to file ns_crypto::signature pub -pem /tmp/sigkey.pem -outfile /tmp/sigpub.pem
Create a signature over the provided message using the specified private key.
The argument to -pem may be either a PEM file name or a PEM string containing a private key. When the private key is encrypted, provide the passphrase via -passphrase.
By default, message is treated as a character string. When -binary is specified, the message is interpreted as raw binary data.
For key types requiring an external digest, the digest algorithm may be selected via -digest. When omitted, a suitable default is used. For example, sha256 is used for many classical signature algorithms, while sm3 is used for SM2.
For key types using an internal digest, such as Ed25519 and Ed448, the option -digest is not supported.
The option -id specifies the distinguishing identifier used for signature algorithms that support such a parameter. At present this applies to SM2 keys. The same identifier must be used for signing and verification. When -id is omitted for SM2, the OpenSSL default identifier is used.
The resulting signature is returned encoded according to -encoding, which defaults to hex.
# Create an RSA signature with the default digest set sig [ns_crypto::signature sign -pem $pem -- "hello world"] # Create an Ed25519 signature set sig [ns_crypto::signature sign -pem $pem -- "hello world"] # Create an SM2 signature using the default SM2 digest and identifier set sig [ns_crypto::signature sign -pem $pem -- "hello world"] # Create an SM2 signature with an explicit identifier set sig [ns_crypto::signature sign -pem $pem -id "alice@example.com" -- "hello world"]
Verify a signature over the provided message using the specified key.
The argument to -pem may be either a PEM file name or a PEM string containing a public key or a private key. When a private key is provided, the corresponding public key is used. When the key is encrypted, provide the passphrase via -passphrase.
By default, message is treated as a character string. When -binary is specified, the message is interpreted as raw binary data.
The argument to -signature must be provided as binary data. When the signature is stored in textual form such as hex or base64url, it must be decoded before calling this command.
For key types requiring an external digest, the digest algorithm may be selected via -digest. When omitted, a suitable default is used.
The option -id specifies the distinguishing identifier for algorithms that support it, currently SM2. When verifying such signatures, the same identifier that was used during signing must be provided. When -id is omitted for SM2, the OpenSSL default identifier is used.
The result is 1 for a valid signature and 0 for an invalid signature.
# Verify an RSA or EC signature
ns_crypto::signature verify -pem $pub -signature [binary decode hex $sig] -- "hello world"
# Verify an SM2 signature with an explicit identifier
ns_crypto::signature verify -pem $pub -id "alice@example.com" \
-signature [binary decode hex $sig] -- "hello world"
Computes 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
Computes a password hash based on PBKDF2 (Password-Based Key Derivation Function 2, RFC 2898) in the length of nrbtyes. 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
Returns a newly generated UUID string in canonical textual form "8-4-4-4-12" (36 lowercase hexadecimal characters plus 4 hyphens). The result is always NUL-free ASCII suitable for storage in CHAR(36), VARCHAR(36), or database UUID types.
If no -version is specified, the command returns a Version 4 (UUIDv4) identifier for backward compatibility with the historical ns_uuid command. UUIDv4 values are generated from cryptographic random bytes and include no timestamp information, providing maximum entropy and privacy without revealing creation time. (UUIDv4 is specified in RFC 4122)
When -version v7 is specified, the command returns a Version 7 (UUIDv7) identifier as defined in RFC 9562. UUIDv7 values embed the current time in milliseconds in the high-order bits and random data in the remaining bits. They are globally unique and monotonically increasing with creation time, which improves index locality and insertion performance in databases and ordered data stores. However, UUIDv7 values encode their creation time, so they can reveal when an ID was generated.
% ns_crypto::uuid 3191eb43-60a3-4c9b-a3dc-9b5ef667641b % ns_crypto::uuid -version v4 75a2d2a1-7d67-4d59-8a2f-8e4f0eba4b36 % ns_crypto::uuid -version v7 018fa74a-9f4c-7d82-9a5f-b59e22f14d35
The built-in historical command ns_uuid is equivalent to ns_crypto::uuid -version v4 and is retained for backward compatibility with existing applications and persisted identifiers.