rind distills great cryptography into a pure-Rust library for rustls and MoQ, as fast as aws-lc-rs and ring and built by rustc alone.
- No C toolchain. rind's assembly lives in Rust source, so
cargo buildneeds only rustc and a linker: no C compiler, cmake, nasm, or perl, for the host or a cross target. A rustls client builds faster over rind than over aws-lc-rs or ring. - Verified where it counts. On x86_64 and aarch64, rind's elliptic-curve, RSA, and ML-KEM arithmetic builds on s2n-bignum's formally verified assembly, and rind's own Lean proofs carry X25519 and Ed25519 from its API down to it, as Verified code lists. rind prefers verified code, and ALGORITHMS.md marks ⚡ each place it runs faster unverified code instead.
- As fast as aws-lc-rs and ring. rind matches or beats both on nearly every operation TLS and QUIC run, from the handshake to each packet's AEAD. Where another library is ahead, as ring and aws-lc-rs are at RSA-2048 signing on x86_64, and aws-lc-rs is at AES-GCM and short messages on Apple silicon, where rind alone sets DIT around each call, Known gaps says so, with the quest that closes the gap or the reason it stays.
BENCHMARKS.md has the times behind this chart: every operation on each host and CPU tier, against aws-lc-rs, ring, RustCrypto, Graviola, libcrux, and OpenSSL, with each library's build time, binary size, and build tools.
rind is new, so exercise due caution.
rind-rustls is a rustls CryptoProvider. Turn off rustls's default
features, which compile aws-lc-rs:
[dependencies]
rind-rustls = "0.23"
rustls = { version = "0.23", default-features = false, features = ["std", "tls12"] }Install it at startup, then use rustls as normal:
// Refuses a CPU missing a feature rind requires.
rind_rustls::default_provider()?.install_default().unwrap();Its README shows a provider that links only the algorithms a binary names.
The rind crate's own API covers AES-GCM, ChaCha20-Poly1305, and
XChaCha20-Poly1305, QUIC header protection, X25519 and ECDH, ML-KEM-768,
ECDSA, Ed25519, and RSA signatures, RSA-OAEP, SHA-1, SHA-2, and SHA-3, HMAC,
HKDF, PBKDF2, and AES key wrap. Each algorithm is a constant and each key
type has one role, so misuse fails to compile:
use rind::signature::{EcdsaKeyPair, PublicKey, sign, verify};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// An error naming the missing CPU feature, rather than a panic later.
rind::cpu::check()?;
let key_pair = EcdsaKeyPair::generate(&sign::ECDSA_P256_SHA256_ASN1)?;
let signature = key_pair.sign(b"hello")?;
let encoded = key_pair.public_key();
let public_key = PublicKey::new(&verify::ECDSA_P256_SHA256_ASN1, encoded.as_ref())?;
public_key.verify(b"hello", signature.as_ref())?;
Ok(())
}docs.rs documents every module, and ARCHITECTURE.md describes the API's shape.
Each crate's README shows its setup.
| Crate | For |
|---|---|
| rind-ring | ring 0.17's API, name for name: rename the dependency, with no code changes |
| rind-dimpl | DTLS 1.2 and 1.3 through dimpl |
| rind-jsonwebtoken | JWTs through jsonwebtoken |
| rind-object-store | S3, Azure, and GCS request signing through object_store |
| rind-rcgen | certificates through rcgen |
| rind-instant-acme | ACME through instant-acme, unpublished until instant-acme releases the interface it targets |
rind runs on x86_64, aarch64, and 32-bit arm, and fails to compile for any
other architecture. CI tests Linux (glibc and musl), macOS, and Windows on
x86_64 and aarch64, iOS in the simulator, and Android on aarch64, armv7, and
x86_64. Any x86_64 CPU runs it,
aarch64 needs NEON, and every operation panics on a CPU missing a feature
rind requires: call rind::cpu::check() at startup to get an error naming
it instead, as rind_rustls::default_provider() does.
PLATFORMS.md lists what each architecture runs without each
feature.
Paste this into your coding agent, in your repository:
Move this repository from ring or aws-lc-rs to rind, following
https://raw.githubusercontent.com/moq-dev/rind/main/MIGRATE.md
It migrates on a local branch, reports the build time, binary size, benchmarks, and tests before and after, and asks before opening a PR or filing an issue. To migrate by hand, MIGRATING.md maps each ring and aws-lc-rs item to rind's.
AI reviews and contributions are welcome. rind plans its work as quests,
Markdown files under quest/, with skills for Claude Code and
Codex. With quest installed, have your agent run
/quest-plan to propose a change or report a finding, or /quest-start to
take a quest from the backlog. CONTRIBUTING.md covers
building, testing, and how a PR lands.
- ALGORITHMS.md: whose code runs each algorithm on each CPU, what of it is formally verified, its sources and their licenses, and how the main paths work.
- PLATFORMS.md: the CPU features each architecture requires, and what runs without the optional ones.
- ARCHITECTURE.md: the API's design, its modules, and the layers beneath them.
- BENCHMARKS.md: every operation's time, build time, and binary size, against the other libraries.
rind began as a fork of Graviola by Joe Birr-Pixton, and no longer tracks it. Graviola is an outstanding project: a fast, carefully designed cryptography library with a refreshingly simple Rust-only build. rind owes it its starting point, much of its code, and the example it follows. If Graviola covers your needs, please give it a look and support its authors.
aws-lc-rs is excellent, too. It is the library we would use if we did not need to build without C. AWS-LC supplies many of rind's implementations, and aws-lc-rs is our reference for behavior, differential tests, and performance.
The credit for the underlying algorithms, implementations, and proofs belongs to their authors, including s2n-bignum, HACL*, libcrux, fiat-crypto, and the other projects ALGORITHMS.md lists. rind's contribution is to distill and integrate their work.
The rind logo is a tribute to Graviola's fruit illustration,
reimagined as a curled strip of its protective rind. A wordmark
for dark backgrounds starts white ind beneath the curl and extends it to
the right.
rind's own code is licensed under Apache-2.0 OR ISC OR MIT-0. Code copied from other projects keeps its source's license, which LICENSE lists.
