x25519-nostd

Crates.iox25519-nostd
lib.rsx25519-nostd
version0.1.0
created_at2025-12-22 11:25:36.131478+00
updated_at2025-12-22 11:25:36.131478+00
descriptionPure-Rust X25519 (Curve25519) ECDH implementation for no_std/bare-metal targets (avoids LLVM SIMD issues)
homepagehttps://github.com/artst3in/x25519-nostd
repositoryhttps://github.com/artst3in/x25519-nostd
max_upload_size
id1999581
size34,205
The Architect (artst3in)

documentation

https://docs.rs/x25519-nostd

README

x25519-nostd

Pure-Rust X25519 (Curve25519) elliptic curve Diffie-Hellman implementation for no_std and bare-metal targets.

Why This Crate Exists

The standard curve25519-dalek and x25519-dalek crates (from RustCrypto) fail to compile on certain bare-metal targets like x86_64-unknown-none with LLVM errors:

LLVM ERROR: Do not know how to split the result of this operator!

This happens because these crates use SIMD intrinsics that aren't available on all targets. This pure-Rust implementation avoids SIMD entirely, making it portable to any Rust target.

Features

  • 100% Pure Rust: No assembly, no SIMD, no platform-specific code
  • no_std compatible: Works in bare-metal and embedded environments
  • Constant-time: Side-channel resistant Montgomery ladder
  • RFC 7748 compliant: Passes official test vectors
  • Simple API: Drop-in replacement for other X25519 implementations

Security Properties

  • 128-bit security level
  • Constant-time operations (resistant to timing attacks)
  • 32-byte keys (compact and efficient)
  • ~100k operations/sec on modern CPUs

Usage

Add to your Cargo.toml:

[dependencies]
x25519-nostd = "0.1"

Key Exchange

use x25519_nostd::{public_key, diffie_hellman};

// Alice generates a keypair
let alice_secret = [0x42u8; 32];  // In practice, use secure random
let alice_public = public_key(&alice_secret);

// Bob generates a keypair
let bob_secret = [0x07u8; 32];
let bob_public = public_key(&bob_secret);

// Both compute the same shared secret
let alice_shared = diffie_hellman(&alice_secret, &bob_public);
let bob_shared = diffie_hellman(&bob_secret, &alice_public);

assert_eq!(alice_shared, bob_shared);

WireGuard-style Usage

use x25519_nostd::{public_key, diffie_hellman};

// Generate static keypair
let static_secret = [/* secure random 32 bytes */];
let static_public = public_key(&static_secret);

// Compute shared secret with peer
let peer_public = [/* peer's public key */];
let shared_secret = diffie_hellman(&static_secret, &peer_public);

// Use shared_secret with a KDF (like BLAKE2s or HKDF)

Algorithm

X25519 performs scalar multiplication on Curve25519:

  • Curve equation: y² = x³ + 486662x² + x
  • Prime field: p = 2^255 - 19
  • Base point: u = 9
  • Scalar clamping: s[0] &= 248, s[31] &= 127, s[31] |= 64

Uses the Montgomery ladder for constant-time scalar multiplication.

Implementation Details

  • Field elements represented as 5 limbs of 51 bits each (255 bits total)
  • Montgomery ladder for constant-time point multiplication
  • Field arithmetic modulo 2^255 - 19
  • Inversion using Fermat's little theorem: a^(p-2) ≡ a^(-1) (mod p)
  • No heap allocations

Performance

On modern x86_64 CPUs:

  • ~100k key exchanges per second
  • ~10 µs per scalar multiplication

(Performance varies by target; bare-metal may differ)

Compatibility

Tested on:

  • x86_64-unknown-none (bare-metal)
  • x86_64-unknown-linux-gnu (std)
  • Other targets should work but are untested

Security Notes

  1. Never reuse secret keys: Generate new ephemeral keys for each session
  2. Use a KDF: The raw shared secret should be passed through HKDF or similar
  3. Validate public keys: Check for small-subgroup attacks in your protocol
  4. Use secure randomness: Never use weak RNGs for key generation

Testing

Run the test suite:

cargo test

Includes RFC 7748 test vectors.

License

Licensed under Apache License 2.0.

References

Contributing

Contributions welcome! This crate was extracted from a bare-metal OS project to help the Rust embedded and bare-metal community overcome LLVM SIMD limitations.

Commit count: 0

cargo fmt