facil.io

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