poly1305-nostd

Crates.iopoly1305-nostd
lib.rspoly1305-nostd
version0.1.0
created_at2025-12-22 11:25:22.806079+00
updated_at2025-12-22 11:25:22.806079+00
descriptionPure-Rust Poly1305 MAC implementation for no_std/bare-metal targets (avoids LLVM SIMD issues)
homepagehttps://github.com/artst3in/poly1305-nostd
repositoryhttps://github.com/artst3in/poly1305-nostd
max_upload_size
id1999580
size27,623
The Architect (artst3in)

documentation

https://docs.rs/poly1305-nostd

README

poly1305-nostd

Pure-Rust Poly1305 MAC implementation for no_std and bare-metal targets.

Why This Crate Exists

The standard poly1305 crate (from RustCrypto) fails 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 the crate uses 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 implementation
  • RFC 8439 compliant: Passes official test vectors
  • Simple API: Drop-in replacement for other Poly1305 implementations

Security Properties

  • 128-bit authentication tag
  • One-time MAC (key must be unique per message)
  • Constant-time operations (no secret-dependent branches)
  • ~10 cycles/byte on modern x86_64

Usage

Add to your Cargo.toml:

[dependencies]
poly1305-nostd = "0.1"

One-shot MAC

use poly1305_nostd::Poly1305;

let key = [0u8; 32];  // Must be unique per message
let message = b"Hello, world!";

let tag = Poly1305::mac(&key, message);
assert_eq!(tag.len(), 16);

Incremental MAC

use poly1305_nostd::Poly1305;

let key = [0u8; 32];
let mut poly = Poly1305::new(&key);

poly.update(b"Hello, ");
poly.update(b"world!");

let tag = poly.finalize();

Algorithm

Poly1305 is a one-time authenticator designed by Daniel J. Bernstein:

  1. Clamp the 'r' portion of the key
  2. Process message in 16-byte blocks
  3. Accumulate: a = ((a + block) * r) mod (2^130 - 5)
  4. Add 's' portion of key: tag = (a + s) mod 2^128

Implementation Details

  • Uses 26-bit limb representation for field arithmetic
  • Field operations modulo 2^130 - 5
  • Avoids arithmetic overflow through careful reduction
  • No heap allocations

Performance

On modern x86_64 CPUs:

  • ~10 cycles/byte for bulk operations
  • ~2 µs for 1 KB message

(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

Testing

Run the test suite:

cargo test

Includes RFC 8439 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