| Crates.io | chacha20poly1305-nostd |
| lib.rs | chacha20poly1305-nostd |
| version | 0.1.0 |
| created_at | 2025-12-22 11:26:26.737148+00 |
| updated_at | 2025-12-22 11:26:26.737148+00 |
| description | Pure-Rust ChaCha20-Poly1305 AEAD implementation for no_std/bare-metal targets (avoids LLVM SIMD issues) |
| homepage | https://github.com/artst3in/chacha20poly1305-nostd |
| repository | https://github.com/artst3in/chacha20poly1305-nostd |
| max_upload_size | |
| id | 1999582 |
| size | 32,595 |
Pure-Rust ChaCha20-Poly1305 AEAD (Authenticated Encryption with Associated Data) implementation for no_std and bare-metal targets.
The standard chacha20poly1305 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 depends on other crates that use SIMD intrinsics unavailable on all targets. This pure-Rust implementation avoids SIMD entirely, making it portable to any Rust target.
no_std compatible: Works in bare-metal and embedded environmentsAdd to your Cargo.toml:
[dependencies]
chacha20poly1305-nostd = "0.1"
use chacha20poly1305_nostd::ChaCha20Poly1305;
let key = [0u8; 32]; // 256-bit key
let nonce = [0u8; 12]; // 96-bit nonce (MUST be unique per message)
let cipher = ChaCha20Poly1305::new(&key).unwrap();
// Encrypt
let plaintext = b"Hello, Luna!";
let ciphertext = cipher.encrypt(&nonce, plaintext, None).unwrap();
// ciphertext = encrypted_data || 16-byte authentication tag
// Decrypt
let decrypted = cipher.decrypt(&nonce, &ciphertext, None).unwrap();
assert_eq!(decrypted, plaintext);
use chacha20poly1305_nostd::ChaCha20Poly1305;
let key = [0u8; 32];
let nonce = [0u8; 12];
let cipher = ChaCha20Poly1305::new(&key).unwrap();
let plaintext = b"Secret message";
let aad = b"public header"; // Authenticated but not encrypted
// Encrypt with AAD
let ciphertext = cipher.encrypt(&nonce, plaintext, Some(aad)).unwrap();
// Decrypt with AAD (must match!)
let decrypted = cipher.decrypt(&nonce, &ciphertext, Some(aad)).unwrap();
assert_eq!(decrypted, plaintext);
// Wrong AAD fails authentication
let result = cipher.decrypt(&nonce, &ciphertext, Some(b"wrong"));
assert!(result.is_err());
ChaCha20-Poly1305 combines two primitives:
ChaCha20: Stream cipher for encryption
Poly1305: Message authentication code
AAD || pad || ciphertext || pad || lengthspoly1305-nostd for authenticationchacha20 crate (no SIMD issues)On modern x86_64 CPUs:
(Performance varies by target; bare-metal may differ)
Tested on:
x86_64-unknown-none (bare-metal)x86_64-unknown-linux-gnu (std)chacha20-poly1305@openssh.com cipherRun the test suite:
cargo test
Includes RFC 8439 Appendix A.5 test vector.
Licensed under Apache License 2.0.
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.