# Ed25519 & X25519

```c
#define FIO_ED25519
#include "fio-stl.h"
```

Elliptic-curve cryptography over Curve25519: Ed25519 for signatures and X25519 for key exchange. Both provide 128-bit security with compact 32-byte keys.

**Security note:** this implementation has not been independently audited. Use at your own risk, and prefer a tested cryptographic library when available.

### Ed25519 Digital Signatures

- Secret key: 32 bytes
- Public key: 32 bytes
- Signature: 64 bytes

#### `fio_ed25519_keypair`

```c
SFUNC void fio_ed25519_keypair(uint8_t secret_key[32], uint8_t public_key[32]);
```

Generates a new random Ed25519 key pair.

#### `fio_ed25519_public_key`

```c
SFUNC void fio_ed25519_public_key(uint8_t public_key[32],
                                  const uint8_t secret_key[32]);
```

Derives the public key from a secret key.

#### `fio_ed25519_sign`

```c
SFUNC int fio_ed25519_sign(uint8_t signature[64],
                           const void *message,
                           size_t len,
                           const uint8_t secret_key[32],
                           const uint8_t public_key[32]);
```

Signs a message. Returns `0` on success, `-1` on failure. The signature is deterministic.

#### `fio_ed25519_verify`

```c
SFUNC int fio_ed25519_verify(const uint8_t signature[64],
                             const void *message,
                             size_t len,
                             const uint8_t public_key[32]);
```

Verifies a signature. Returns `0` on success, `-1` on failure.

### X25519 Key Exchange

- Secret key: 32 bytes
- Public key: 32 bytes
- Shared secret: 32 bytes

#### `fio_x25519_keypair`

```c
SFUNC void fio_x25519_keypair(uint8_t secret_key[32], uint8_t public_key[32]);
```

Generates a new random X25519 key pair.

#### `fio_x25519_public_key`

```c
SFUNC void fio_x25519_public_key(uint8_t public_key[32],
                                 const uint8_t secret_key[32]);
```

Derives the public key from a secret key.

#### `fio_x25519_shared_secret`

```c
SFUNC int fio_x25519_shared_secret(uint8_t shared_secret[32],
                                   const uint8_t secret_key[32],
                                   const uint8_t their_public_key[32]);
```

Computes a shared secret. Returns `0` on success, `-1` if the result is the all-zero point.

**Note:** pass the shared secret through a KDF such as HKDF before using it as an encryption key.

### Key Conversion

#### `fio_ed25519_sk_to_x25519`

```c
SFUNC void fio_ed25519_sk_to_x25519(uint8_t x_secret_key[32],
                                    const uint8_t ed_secret_key[32]);
```

Converts an Ed25519 secret key to an X25519 secret key.

#### `fio_ed25519_pk_to_x25519`

```c
SFUNC void fio_ed25519_pk_to_x25519(uint8_t x_public_key[32],
                                    const uint8_t ed_public_key[32]);
```

Converts an Ed25519 public key to an X25519 public key.

### ECIES Public-Key Encryption

#### `FIO_X25519_CIPHERTEXT_LEN`

```c
#define FIO_X25519_CIPHERTEXT_LEN(message_len) ((message_len) + 48)
```

Plaintext plus 32-byte ephemeral public key and 16-byte MAC.

#### `FIO_X25519_PLAINTEXT_LEN`

```c
#define FIO_X25519_PLAINTEXT_LEN(ciphertext_len)                               \
  ((ciphertext_len) > 48 ? ((ciphertext_len)-48) : 0)
```

Reverses `FIO_X25519_CIPHERTEXT_LEN`. Returns `0` for invalid ciphertext.

#### `fio_x25519_encrypt`

```c
SFUNC int fio_x25519_encrypt(uint8_t *ciphertext,
                             const void *message,
                             size_t message_len,
                             fio_crypto_enc_fn encryption_function,
                             const uint8_t recipient_pk[32]);
```

Encrypts a message to an X25519 public key. Ciphertext format: `ephemeral_pk || mac || encrypted_data`.

**Parameters:**
- `ciphertext` — output buffer (`message_len + 48` bytes).
- `message` — plaintext.
- `message_len` — plaintext length.
- `encryption_function` — e.g., `fio_chacha20_poly1305_enc`.
- `recipient_pk` — recipient's 32-byte X25519 public key.

**Returns:** `0` on success, `-1` on failure.

#### `fio_x25519_decrypt`

```c
SFUNC int fio_x25519_decrypt(uint8_t *plaintext,
                             const uint8_t *ciphertext,
                             size_t ciphertext_len,
                             fio_crypto_dec_fn decryption_function,
                             const uint8_t recipient_sk[32]);
```

Decrypts a message using the recipient's X25519 secret key.

**Parameters:**
- `plaintext` — output buffer (`ciphertext_len - 48` bytes).
- `ciphertext` — ciphertext from `fio_x25519_encrypt`.
- `ciphertext_len` — total ciphertext length (must be at least 48).
- `decryption_function` — e.g., `fio_chacha20_poly1305_dec`.
- `recipient_sk` — recipient's 32-byte X25519 secret key.

**Returns:** `0` on success, `-1` on failure.

### Example

```c
#define FIO_ED25519
#include "fio-stl.h"

int main(void) {
  uint8_t sk[32], pk[32], sig[64];
  fio_ed25519_keypair(sk, pk);

  const char *msg = "hello, ed25519";
  fio_ed25519_sign(sig, msg, strlen(msg), sk, pk);

  if (fio_ed25519_verify(sig, msg, strlen(msg), pk)) {
    printf("bad signature\n");
    return 1;
  }
  return 0;
}
```

------------------------------------------------------------
