Public-key signatures
Example (combined mode)
Example (detached mode)
Example (multi-part message)
Purpose
In this system, a signer generates a key pair consisting of:
A secret key, which you can use to append a signature to any number of messages.
A public key, which anybody can use to verify that the signature appended to a message was issued by the creator of the public key.
Verifiers need to already know and ultimately trust a public key before messages signed using it can be verified.
Warning: this is different from authenticated encryption. Appending a signature does not change the representation of the message itself.
Key pair generation
The crypto_sign_keypair()
function randomly generates a secret key and a corresponding public key. The public key is put into pk
(crypto_sign_PUBLICKEYBYTES
bytes) and the secret key into sk
(crypto_sign_SECRETKEYBYTES
bytes).
Using crypto_sign_seed_keypair()
, the key pair can also be deterministically derived from a single key seed
(crypto_sign_SEEDBYTES
bytes).
Combined mode
The crypto_sign()
function prepends a signature to a message m
, whose length is mlen
bytes, using the secret key sk
.
The signed message, which includes the signature plus an unaltered copy of the message, is put into sm
and is crypto_sign_BYTES + mlen
bytes long.
If smlen
is not a NULL
pointer, then the actual length of the signed message is stored in smlen
.
The crypto_sign_open()
function checks that the signed message sm
, whose length is smlen
bytes, has a valid signature for the public key pk
.
If the signature isn’t valid, then the function returns -1
.
On success, it puts the message without the signature into m
, stores its length in mlen
if mlen
is not a NULL
pointer, and returns 0
.
Detached mode
In detached mode, the signature is stored without attaching a copy of the original message to it.
The crypto_sign_detached()
function signs the message m
, whose length is mlen
bytes, using the secret key sk
and puts the signature into sig
, which can be up to crypto_sign_BYTES
bytes long.
The actual length of the signature is put into siglen
if siglen
is not NULL
.
It is safe to ignore siglen
and always consider a signature as crypto_sign_BYTES
bytes long; shorter signatures will be transparently padded with zeros if necessary.
The crypto_sign_verify_detached()
function verifies that sig
is a valid signature for the message m
, whose length is mlen
bytes, using the signer’s public key pk
.
It returns -1
if signature verification fails and 0
on success.
Multi-part messages
If the message doesn’t fit in memory, then it can be provided as a sequence of arbitrarily-sized chunks.
This uses the Ed25519ph signature system, which pre-hashes the message. In other words, what gets signed is not the message itself but its image through a hash function.
If the message can fit in memory and be supplied as a single chunk, then the single-part API should be preferred.
Note: Ed25519ph(m)
is intentionally not equivalent to Ed25519(SHA512(m))
.
If, for some reason, you need to pre-hash the message yourself, then use the multi-part crypto_generichash_*()
APIs and sign the 512-bit output, preferably prefixed by your protocol name (or anything that will make the hash unique for a given use case).
The crypto_sign_init()
function initializes the state state
. This function must be called before the first crypto_sign_update()
call.
Add a new chunk m
of length mlen
bytes to the message that will eventually be signed.
After all parts have been supplied, one of the following functions can be called:
The crypto_sign_final_create()
function computes a signature for the previously supplied message using the secret key sk
and puts it into sig
.
If siglen_p
is not NULL
, then the length of the signature is stored at this address.
It is safe to ignore siglen
and always consider a signature as crypto_sign_BYTES
bytes long; shorter signatures will be transparently padded with zeros if necessary.
The crypto_sign_final_verify()
function verifies that sig
is a valid signature using the public key pk
for the message whose content has been previously supplied using crypto_update()
.
Extracting the seed and the public key from the secret key
The secret key includes the seed (either a random seed or the one given to crypto_sign_seed_keypair()
) and public key.
While the public key can always be derived from the seed, the precomputation saves a significant amount of CPU cycles when signing.
If required, Sodium provides two functions to extract the seed and public key from the secret key:
The crypto_sign_ed25519_sk_to_seed()
function extracts the seed from the secret key sk
and copies it into seed
(crypto_sign_SEEDBYTES
bytes).
The crypto_sign_ed25519_sk_to_pk()
function extracts the public key from the secret key sk
and copies it into pk
(crypto_sign_PUBLICKEYBYTES
bytes).
Data structures
crypto_sign_state
, whose size can be retrieved usingcrypto_sign_statebytes()
Constants
crypto_sign_PUBLICKEYBYTES
crypto_sign_SECRETKEYBYTES
crypto_sign_BYTES
crypto_sign_SEEDBYTES
Algorithm details
Single-part signature: Ed25519
Multi-part signature: Ed25519ph
References
Notes
crypto_sign_verify()
and crypto_sign_verify_detached()
are only designed to verify signatures computed using crypto_sign()
and crypto_sign_detached()
.
The original NaCl crypto_sign_open()
implementation overwrote 64 bytes after the message, whereas the libsodium implementation doesn’t write past the end of the message.
Ed25519ph (used by the multi-part API) was implemented in libsodium 1.0.12.
The Ed25519 system was designed to compute deterministic signatures.
Non-deterministic (but also non-standard) signatures can be produced by compiling libsodium with the ED25519_NONDETERMINISTIC
macro defined.
Computing an Ed25519 signature requires an Edwards25519 secret and a hashing prefix. But applications do not directly supply them: they are both internally derived from the seed.
One of these secrets is the scalar the Edwards25519 base point is multiplied with. That scalar is computed by calling crypto_hash_sha512(seed)
and truncating the output to the first 32 bytes. There's nothing specific to libsodium here, this is how Ed25519 signatures work and have been standardized.
Last updated