# Public-key signatures

## Example (combined mode)

```c
#define MESSAGE (const unsigned char *) "test"
#define MESSAGE_LEN 4

unsigned char pk[crypto_sign_PUBLICKEYBYTES];
unsigned char sk[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(pk, sk);

unsigned char signed_message[crypto_sign_BYTES + MESSAGE_LEN];
unsigned long long signed_message_len;

crypto_sign(signed_message, &signed_message_len,
            MESSAGE, MESSAGE_LEN, sk);

unsigned char unsigned_message[MESSAGE_LEN];
unsigned long long unsigned_message_len;
if (crypto_sign_open(unsigned_message, &unsigned_message_len,
                     signed_message, signed_message_len, pk) != 0) {
    /* incorrect signature! */
}
```

### Example (detached mode)

```c
#define MESSAGE (const unsigned char *) "test"
#define MESSAGE_LEN 4

unsigned char pk[crypto_sign_PUBLICKEYBYTES];
unsigned char sk[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(pk, sk);

unsigned char sig[crypto_sign_BYTES];

crypto_sign_detached(sig, NULL, MESSAGE, MESSAGE_LEN, sk);

if (crypto_sign_verify_detached(sig, MESSAGE, MESSAGE_LEN, pk) != 0) {
    /* incorrect signature! */
}
```

### Example (multi-part message)

```c
#define MESSAGE_PART1 \
    ((const unsigned char *) "Arbitrary data to hash")
#define MESSAGE_PART1_LEN 22

#define MESSAGE_PART2 \
    ((const unsigned char *) "is longer than expected")
#define MESSAGE_PART2_LEN 23

unsigned char pk[crypto_sign_PUBLICKEYBYTES];
unsigned char sk[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(pk, sk);

crypto_sign_state state;
unsigned char sig[crypto_sign_BYTES];

/* signature creation */

crypto_sign_init(&state)
crypto_sign_update(&state, MESSAGE_PART1, MESSAGE_PART1_LEN);
crypto_sign_update(&state, MESSAGE_PART2, MESSAGE_PART2_LEN);
crypto_sign_final_create(&state, sig, NULL, sk);

/* signature verification */

crypto_sign_init(&state)
crypto_sign_update(&state, MESSAGE_PART1, MESSAGE_PART1_LEN);
crypto_sign_update(&state, MESSAGE_PART2, MESSAGE_PART2_LEN);
if (crypto_sign_final_verify(&state, sig, pk) != 0) {
    /* message forged! */
}
```

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

```c
int crypto_sign_keypair(unsigned char *pk, unsigned char *sk);
```

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

```c
int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk,
                             const unsigned char *seed);
```

Using `crypto_sign_seed_keypair()`, the key pair can also be deterministically derived from a single key `seed` (`crypto_sign_SEEDBYTES` bytes).

## Combined mode

```c
int crypto_sign(unsigned char *sm, unsigned long long *smlen_p,
                const unsigned char *m, unsigned long long mlen,
                const unsigned char *sk);
```

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

```c
int crypto_sign_open(unsigned char *m, unsigned long long *mlen_p,
                     const unsigned char *sm, unsigned long long smlen,
                     const unsigned char *pk);
```

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.

```c
int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
                         const unsigned char *m, unsigned long long mlen,
                         const unsigned char *sk);
```

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.

```c
int crypto_sign_verify_detached(const unsigned char *sig,
                                const unsigned char *m,
                                unsigned long long mlen,
                                const unsigned char *pk);
```

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

```c
int crypto_sign_init(crypto_sign_state *state);
```

The `crypto_sign_init()` function initializes the state `state`. This function must be called before the first `crypto_sign_update()` call.

```c
int crypto_sign_update(crypto_sign_state *state,
                       const unsigned char *m, unsigned long long mlen);
```

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:

```c
int crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig,
                             unsigned long long *siglen_p,
                             const unsigned char *sk);
```

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.

```c
int crypto_sign_final_verify(crypto_sign_state *state, const unsigned char *sig,
                             const unsigned char *pk);
```

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:

```c
int crypto_sign_ed25519_sk_to_seed(unsigned char *seed,
                                   const unsigned char *sk);

int crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk);
```

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 using `crypto_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

* [Edwards-Curve Digital Signature Algorithm (EdDSA)](https://datatracker.ietf.org/doc/html/rfc8032)
* [The Provable Security of Ed25519: Theory and Practice](https://eprint.iacr.org/2020/823.pdf)
* [Seems Legit: Automated Analysis of Subtle Attacks on Protocols that Use Signatures](https://eprint.iacr.org/2019/779.pdf)
* [Taming the many EdDSAs](https://eprint.iacr.org/2020/1244.pdf)

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
