Skip to main content
Version: 0.3.0

Ed448

Ed448 digital signatures (RFC 8032). Header: pkc/ed448/noxtls_ed448.h.

Algorithm overview​

Ed448 is an EdDSA signature scheme over Curve448. It follows the same model as Ed25519 but targets a higher security margin, with larger key and signature sizes.

Enablement​

  • NOXTLS_CFG_FEATURE_ED448=ON (CMake, default OFF), which defines NOXTLS_FEATURE_ED448.
  • Requires public-key support (NOXTLS_FEATURE_PKC) and SHA-3/SHAKE256 (NOXTLS_FEATURE_SHA3).

Implementation in 0.3.0​

Rewritten in 0.3.0

Before 0.3.0, the Ed448 code did not compile when NOXTLS_FEATURE_ED448 was enabled, and its arithmetic did not follow RFC 8032 (wrong curve constants, point addition, square root, clamping, and secret-key expansion). It has been rewritten, with the public API unchanged, and now passes the RFC 8032 section 7.4 test vectors and OpenSSL test vectors for the pure, ctx, and ph variants and for streaming verification. Any Ed448 keys or signatures made with locally patched earlier sources do not match RFC 8032 and must be regenerated.

  • Portable C99. Field arithmetic in GF(2^448 - 2^224 - 1) uses 16 limbs of 28 bits with 32×32→64-bit multiplies, so it suits 32-bit cores. The field code uses no heap and no bignum calls; scalars modulo the group order L use the bignum module.
  • Constant time. Field selection and canonicalization, and scalar multiplication (double-and-always-add), do not branch on secret data. Secret intermediates are erased.
  • RFC 8032 hashing. Clamping sets bit 447 and clears the last octet, the secret key is expanded as SHAKE256(sk, 114), and dom4 is included in every hash, including streaming verification.
  • Strict verification. Point decoding (RFC 8032 section 5.2.3) rejects set reserved bits, y ≥ p, points not on the curve, and x = 0 with the sign bit set. Verification rejects a signature whose S is not less than L or has a non-zero last octet, and checks the cofactored equation [4][S]B = [4](R + [k]A).
  • Performance. On an x64 MSVC Release build, signing and verification each take about 4 ms. Expect considerably longer on microcontrollers.

Pros and cons​

Pros

  • Higher security margin than Ed25519.
  • Deterministic EdDSA design with strong modern cryptographic properties.
  • Suitable for conservative, long-horizon security requirements.

Cons

  • Larger signatures/keys and slower performance than Ed25519.
  • More limited ecosystem and interoperability support.
  • Signature-only primitive; pair with separate key agreement where needed.

When to use​

  • Use where policy mandates stronger signature margins than Ed25519.
  • Fit for high-assurance or long-term validation contexts.
  • For mainstream interoperability and speed, Ed25519 is usually preferred.

Constants​

  • NOXTLS_ED448_PRIVATE_KEY_SIZE = 57
  • NOXTLS_ED448_PUBLIC_KEY_SIZE = 57
  • NOXTLS_ED448_SIGNATURE_SIZE = 114
  • NOXTLS_ED448_CONTEXT_MAX = 255 (maximum Ed448ctx context length)
  • NOXTLS_ED448_SCALAR_CLAMP_BYTE55_AND = 0xFF and NOXTLS_ED448_SCALAR_CLAMP_BYTE55_OR = 0x80 (changed in 0.3.0 to follow RFC 8032 section 5.2.5)

All functions return NOXTLS_RETURN_SUCCESS on success. The verify functions return NOXTLS_RETURN_SUCCESS only for a valid signature, and an error code for an invalid signature, an invalid public key or R encoding, or invalid arguments.

API​

noxtls_ed448_generate_key​

noxtls_return_t noxtls_ed448_generate_key(uint8_t private_key[57], uint8_t public_key[57]);

Generate private/public key pair.

noxtls_ed448_public_key​

noxtls_return_t noxtls_ed448_public_key(const uint8_t private_key[57], uint8_t public_key[57]);

Derive public key from private key seed.

noxtls_ed448_sign​

noxtls_return_t noxtls_ed448_sign(const uint8_t private_key[57],
const uint8_t *message,
uint32_t message_len,
uint8_t signature[114]);

Sign message with Ed448.

noxtls_ed448_verify​

noxtls_return_t noxtls_ed448_verify(const uint8_t public_key[57],
const uint8_t *message,
uint32_t message_len,
const uint8_t signature[114]);

Verify Ed448 signature.

Streaming verification​

New in the 0.3.0 line. Verify a message that arrives in pieces without assembling it in one buffer. The context holds the public key, the signature, and the SHAKE256 state. It holds no private key.

noxtls_return_t noxtls_ed448_verify_stream_init(noxtls_ed448_verify_stream_ctx_t *ctx,
const uint8_t public_key[57],
const uint8_t signature[114]);
noxtls_return_t noxtls_ed448_verify_stream_update(noxtls_ed448_verify_stream_ctx_t *ctx,
const uint8_t *message_part,
uint32_t message_part_len);
noxtls_return_t noxtls_ed448_verify_stream_final(noxtls_ed448_verify_stream_ctx_t *ctx);

noxtls_ed448_verify_stream_final() returns NOXTLS_RETURN_SUCCESS only when the signature is valid. Initialize a new context for each message.

Streaming verification produces the same result as noxtls_ed448_verify() for PureEdDSA signatures. In 0.3.0 it includes dom4 in the hash as RFC 8032 requires; earlier code omitted it.

noxtls_ed448ctx_sign / noxtls_ed448ctx_verify​

noxtls_return_t noxtls_ed448ctx_sign(const uint8_t private_key[57],
const uint8_t *context,
uint32_t context_len,
const uint8_t *message,
uint32_t message_len,
uint8_t signature[114]);
noxtls_return_t noxtls_ed448ctx_verify(const uint8_t public_key[57],
const uint8_t *context,
uint32_t context_len,
const uint8_t *message,
uint32_t message_len,
const uint8_t signature[114]);

Ed448 with a context string (RFC 8032). context_len must be 1 to NOXTLS_ED448_CONTEXT_MAX (255) bytes, and verification must use the same context as signing.

noxtls_ed448ph_sign / noxtls_ed448ph_verify​

noxtls_return_t noxtls_ed448ph_sign(const uint8_t private_key[57],
const uint8_t *message,
uint32_t message_len,
uint8_t signature[114]);
noxtls_return_t noxtls_ed448ph_verify(const uint8_t public_key[57],
const uint8_t *message,
uint32_t message_len,
const uint8_t signature[114]);

Ed448ph (RFC 8032): the message is prehashed as the first 64 bytes of SHAKE256(message). Pass the original message, not a digest; the functions compute the prehash. Ed448ph signatures are not interchangeable with Ed448 or Ed448ctx signatures.