rscrypto 0.4.0

Pure Rust Cryptography: RSA, Ed25519, X25519, SHA-2/3, BLAKE2/3, AES-GCM/GCM-SIV, X/ChaCha20-Poly1305, Argon2, HMAC/HKDF, CRC. no_std, WASM, hardware acceleration.
Documentation

rscrypto

Crates.io Docs.rs CI RSA Gates MSRV 1.91.0 License: MIT OR Apache-2.0

Pure Rust cryptography: RSA, Ed25519, X25519, AEADs, hashes, KDFs, password hashing, CRCs, no_std, WASM, and hardware acceleration in one dependency.

rscrypto is a single primitive stack for projects that care about binary size, deployment control, and speed without dragging in mandatory C, OpenSSL, or system library coupling.

Use one leaf feature for one primitive, a group for a subset of primitives, or full for the full crate surface. The portable Rust backend is always present. SIMD and ASM are only accelerators.

Current benchmark evidence: Linux CI is currently 1.60x fastest-external geomean with 3,958 / 6,525 wins and 5,878 / 6,525 wins-or-ties. Apple Silicon local macOS/aarch64 is 1.41x fastest-external geomean with 373 / 725 wins and 693 / 725 wins-or-ties.

Why rscrypto?

  • RSA is a first class citizen. Strict DER import/export, RSA-PSS, RSASSA-PKCS1-v1_5, OAEP, RSAES-PKCS1-v1_5, FIPS 186-5 A.1.3 probable-prime key generation in code, X.509/JWT/COSE/TLS profile mapping, blinded private operations, and reusable scratch APIs.
  • One coherent primitive stack. Avoid composing a dozen crates with different APIs, feature models, and security conventions.
  • Small builds stay small. Enable sha2, blake3, aes-gcm, chacha20poly1305, ed25519, x25519, argon2, or any other leaf without pulling in the world.
  • Portable Rust is the source of truth. SIMD and ASM paths are accelerators; the portable backend remains the reference impl.
  • Hardware dispatch is built in. x86/x86_64, Arm/AArch64, Apple Silicon, IBM Z, IBM POWER, RISC-V, and WASM all have portable fallbacks, w/ optimized kernels where they pay.
  • no_std is a first-class target. Server, CLI, embedded, bare-metal, and WASM builds use the same crate and feature model.
  • Audit knobs are explicit. portable-only collapses runtime capability detection to the portable backend; getrandom, serde, and rayon are opt-in.
  • Security hygiene is part of the API. Opaque verification errors, constant-time equality, zeroized secret types, strict arithmetic, official vectors, fuzzing, Miri, and cross-CPU CI are built into the project discipline.

rscrypto is a primitives crate. It is not a TLS stack, PKI toolkit, protocol implementation, or FIPS 140-3 validated module.

Install

Minimal no_std SHA-2 build:

[dependencies]
rscrypto = { version = "0.3.1", default-features = false, features = ["sha2"] }

Full primitive stack w/ OS randomness enabled:

[dependencies]
rscrypto = { version = "0.3.1", features = ["full", "getrandom"] }

Use default-features = false for constrained no_std builds. Enable getrandom only when you need APIs that generate salts, keys, nonces, or RSA key-gen entropy from the operating system.

Quick Start

use rscrypto::{Digest, Sha256};

let one_shot = Sha256::digest(b"hello world");

let mut h = Sha256::new();
h.update(b"hello ");
h.update(b"world");

assert_eq!(h.finalize(), one_shot);

The common API shape is deliberately simple: one-shot when convenient, streaming when it's needed.

Verify RSA Signatures

[dependencies]
rscrypto = { version = "0.3.1", default-features = false, features = ["rsa"] }
use rscrypto::{RsaPssProfile, RsaPublicKey};

fn verify_release_signature(public_key_der: &[u8], message: &[u8], signature: &[u8]) -> bool {
  let Ok(key) = RsaPublicKey::from_spki_der(public_key_der) else {
    return false;
  };

  key.verify_pss(RsaPssProfile::Sha256, message, signature).is_ok()
}

For repeated verification with the same key, allocate scratch once:

use rscrypto::{RsaPssProfile, RsaPublicKey, RsaSignatureProfile};

fn verify_batch(public_key_der: &[u8], signed_messages: &[(&[u8], &[u8])]) -> bool {
  let Ok(key) = RsaPublicKey::from_spki_der(public_key_der) else {
    return false;
  };
  let mut scratch = key.public_scratch();

  signed_messages.iter().all(|(message, signature)| {
    key
      .verify_signature_with_scratch(
        RsaSignatureProfile::pss(RsaPssProfile::Sha256),
        message,
        signature,
        &mut scratch,
      )
      .is_ok()
  })
}

Enable getrandom for RSA key gen, signing salt/blinding, OAEP encryption randomness, and private-op blinding. RSA key generation uses getrandom to seed an internal HMAC_DRBG, then follows the crate's FIPS 186-5 Appendix A.1.3 probable-prime generation contract:

[dependencies]
rscrypto = { version = "0.3.1", default-features = false, features = ["rsa", "getrandom"] }

Encrypt Data

[dependencies]
rscrypto = { version = "0.3.1", default-features = false, features = ["chacha20poly1305"] }
use rscrypto::{Aead, ChaCha20Poly1305, ChaCha20Poly1305Key, aead::Nonce96};

let key = ChaCha20Poly1305Key::from_bytes([0x11; 32]);
let nonce = Nonce96::from_bytes([0x22; Nonce96::LENGTH]);
let cipher = ChaCha20Poly1305::new(&key);

let aad = b"transfer:v1";
let mut message = *b"pay bob 10";

let tag = cipher
  .encrypt_in_place(&nonce, aad, &mut message)
  .expect("encryption succeeds");

cipher
  .decrypt_in_place(&nonce, aad, &mut message, &tag)
  .expect("authentication succeeds");

assert_eq!(&message, b"pay bob 10");

Hash Passwords

[dependencies]
rscrypto = { version = "0.3.1", default-features = false, features = ["argon2", "phc-strings", "getrandom"] }
use rscrypto::{Argon2Params, Argon2VerifyPolicy, Argon2id};

let password = b"correct horse battery staple";
let params = Argon2Params::new().build().expect("valid Argon2 params");
let encoded = Argon2id::hash_string(&params, password).expect("password hash created");

assert!(
  Argon2id::verify_string_with_policy(
    password,
    &encoded,
    &Argon2VerifyPolicy::default(),
  )
  .is_ok()
);

What You Get

Need Included Feature path
Cryptographic Hashes SHA-2, SHA-3, SHAKE, cSHAKE256, BLAKE2, BLAKE3, Ascon-Hash/XOF/CXOF hashes or leaf features
MACs and KDFs HMAC-SHA-2, KMAC256, HKDF-SHA-2, PBKDF2-HMAC-SHA-2 auth or leaf features
Password Hashing Argon2d/i/id, scrypt, PHC string encode/verify auth, argon2, scrypt, phc-strings
Public-key Primitives Ed25519 signatures, RSA signing/verification/OAEP/RSAES-PKCS1-v1_5/key generation, X25519 key exchange auth, signatures, ed25519, rsa, x25519
AEAD Encryption AES-128/256-GCM, AES-128/256-GCM-SIV, ChaCha20-Poly1305, XChaCha20-Poly1305, AEGIS-256, Ascon-AEAD128 aead or leaf features
Checksums CRC-16, CRC-24, CRC-32, CRC-32C, CRC-64/XZ, CRC-64/NVMe checksums or leaf features
Fast Non-crypto Hashes XXH3-64/128, RapidHash 64/128 xxh3, rapidhash

Fast non-cryptographic hashes and CRCs are for indexing, checksumming, dedup, and integrity plumbing. Do not use them for passwords, signatures, MACs, key derivation, or authentication.

Flags are layered deliberately:

  • Leaf Primitives: sha2, blake3, aes-gcm, ed25519, x25519, crc32, etc.
  • Families/Groups: hashes, checksums, macs, kdfs, password-hashing, aead, signatures, key-exchange.
  • Deployment Controls: std, alloc, getrandom, parallel, serde, serde-secrets, portable-only.

Full Feature Inventory: docs/features.md. Public Type Inventory: docs/types.md.

Constant-Time Verification

rscrypto treats constant-time as a release evidence claim, not a style claim. For a release commit, ct.yaml must finish green with the complete artifact set below, and ct.toml is the machine-readable source of truth for which primitives, kernels, targets, and gates are required. The policy and invalidation rules live in docs/constant-time.md.

A green CT release run uploads compact evidence for the physical runner lanes that mirror the public benchmark matrix:

Physical lane Target evidence Artifact
AMD Zen4, AMD Zen5, Intel Ice Lake, Intel Sapphire Rapids Linux x86_64 artifact/provenance review, LLVM IR/ASM/object heuristics, DudeCT, and BINSEC ct-amd-zen4, ct-amd-zen5, ct-intel-icl, ct-intel-spr
AWS Graviton3 and Graviton4 Linux aarch64 artifact/provenance review, LLVM IR/ASM/object heuristics, DudeCT, and BINSEC ct-graviton3, ct-graviton4
RISE RISC-V Linux riscv64gc artifact/provenance review, LLVM IR/ASM/object heuristics, and DudeCT. BINSEC is not claimed for RISC-V today because the current BINSEC/RISC-V workflow does not complete the release-sized HMAC/HKDF/KMAC/PBKDF2/RSA leaf proofs within the CI proof budget. ct-rise-riscv
IBM z16 / s390x Linux s390x artifact/provenance review, LLVM IR/ASM/object heuristics, and DudeCT. BINSEC is not claimed for s390x today. ct-ibm-s390x
IBM Power10 / ppc64le Linux powerpc64le artifact/provenance review, LLVM IR/ASM/object heuristics, and DudeCT. BINSEC is not claimed for little-endian POWER today. ct-ibm-power10
Apple Silicon Local macOS aarch64 artifact/provenance review, LLVM IR/ASM/object heuristics, and DudeCT through just ct-full. BINSEC is not claimed for Mach-O today. local ct-evidence/ package

Each CT artifact contains a short README.md, ct-report-<lane>.md, ct-report-<lane>.json, host provenance, the full CT log, and any failed or inconclusive component reports. For public release notes, pin the exact green run URL and commit next to these artifact names.

The CT tooling is checked in under tools/ and scripts/ct/: stable harness entrypoints, the DudeCT runner, the BINSEC harness generator, manifest validation, full-run orchestration, and artifact packaging.

Secret-bearing primitive coverage is deliberately explicit:

Surface Required CT evidence
Equality and verification leaves Constant-time equality, secret-byte equality, HMAC-SHA-2 verification, KMAC256 verification, keyed BLAKE2/BLAKE3 leaves, HKDF output derivation, and PBKDF2 verification leaves.
AEAD authentication and symmetric transforms AES-128/256-GCM, AES-128/256-GCM-SIV, ChaCha20-Poly1305, XChaCha20-Poly1305, AEGIS-256, and Ascon-AEAD128 required leaves, including AES rounds, GHASH, POLYVAL, Poly1305, tag generation, and open/authentication failure shape.
Public-key secret operations X25519 scalar multiplication, Ed25519 signing and secret public-key derivation, RSA private signing/decryption leaves, RSA private-operation window selection, and bounded private-component validation leaves.
Password hashing Argon2i secret-bearing hash leaves and final verification comparisons are CT-gated. Argon2d, Argon2id, and scrypt are classified as best-effort for local side-channel CT because their algorithms use data-dependent memory access; their final comparisons and parser/failure boundaries still run through the security test/fuzz evidence.
Public-only work Raw hashes, checksums, non-cryptographic hashes, public-key verification math, DER/PHC parsing, serialization, key generation, OS randomness, and benchmark-only paths are not blanket constant-time claims unless ct.toml promotes a specific leaf.

RSA has a second dedicated gate because private-key code deserves extra scrutiny: rsa.yaml uploads rsa-miri-linux-x64, rsa-leakage-linux-x64, and rsa-leakage-linux-arm64 artifacts for release review.

Performance

Current public benchmark evidence comes from two full passes that are both updated regularly and programmatically:

  • Linux (CI): Nine Linux runners across Intel/ARM x86/x86_64, ARM/aarch64, IBM Power/ppc64le, IBM Z/s390x, and RISC-V.
  • Apple Silicon: local macOS/aarch64 full run.

Current source: Linux CI run #27227999222, created 2026-06-09 18:43:21 UTC, and local Apple Silicon run benchmark_results/2026-06-09/macos/aarch64/results.txt; both are for commit 7dbf097a8db537fc85943f5ae6b2fd2dcc06342b.

Speedup is external_crate_time / rscrypto_time; values above 1.00x mean rscrypto is faster.

Area Compared Against Result
Linux CI fastest external strongest matched Rust baseline per case 1.60x geomean
Linux CI scorecard fastest external 3,958 wins / 6,525 pairs
Linux CI wins or ties fastest external 5,878 / 6,525 pairs
Apple Silicon fastest external strongest matched Rust baseline per case 1.41x geomean
Apple Silicon scorecard fastest external 373 wins / 725 pairs
Apple Silicon wins or ties fastest external 693 / 725 pairs
Linux CI all matched pairs every external comparison row 1.76x geomean; 9,352 / 10,174 wins-or-ties
Checksums Linux CI / Apple Silicon 2.52x / 2.66x geomean
Hashes, MACs, XOFs Linux CI / Apple Silicon 1.41x / 1.10x geomean
Auth/KDF Linux CI / Apple Silicon 1.24x / 1.01x geomean
Password hashing Linux CI / Apple Silicon 0.96x / 1.07x geomean
Public-key Linux CI / Apple Silicon 1.10x / 1.03x geomean
RSA import + verify Linux CI / Apple Silicon 1.55x / 1.46x geomean
AEAD Linux CI / Apple Silicon 1.56x / 1.48x geomean

The honest weak spots right now: Linux scrypt/password hashing, Linux ChaCha20-Poly1305 rows against ring and aws-lc-rs, near-parity Ed25519/X25519 operations, RISE RISC-V checksum point losses, and Apple Silicon SHA3/XXH3 plus localized BLAKE3/CRC32(C) rows. See benchmark_results/OVERVIEW.md for raw runs, methodology, platform scorecards, and loss tables.

Portability And Acceleration

rscrypto keeps the portable Rust path as the byte-for-byte authority. ISA kernels are selected only when the target and runtime CPU support them.

Target family Acceleration examples
x86 / x86_64 SSE4.2, AVX2, AVX-512, AES-NI, SHA-NI, VAES, VPCLMULQDQ
Arm / AArch64 / Apple Silicon NEON, AES, PMULL, SHA2, SHA3, SVE2-PMULL
IBM Z CPACF, MSA, VGFM
POWER / ppc64le POWER8/9/10 vector and crypto extensions
RISC-V RVV, Zbc, Zvkned, Zvbc
WASM SIMD128 where available, portable fallback everywhere

Use portable-only when you need deterministic dispatch, audit-constrained builds, or a portable backend only.

Full platform matrix: docs/platforms.md. Architecture notes: docs/architecture.md.

Security

  • Scoped constant-time verification and secret-bearing operations; docs/security.md names the boundary.
  • Opaque verification errors that avoid leaking failure details.
  • Secret-bearing types zeroize on drop and mask Debug.
  • Strict arithmetic for counters, lengths, offsets, and indices.
  • AEAD failed-open paths wipe output buffers.
  • Portable and accelerated backends are differentially tested for byte-identical output.
  • Official test vectors, Wycheproof coverage where applicable, fuzz corpus replay, and Miri run in CI.
  • RSA private-operation release claims require the dedicated RSA Miri and first-order leakage gates.

Read docs/security.md before shipping cryptographic code. For compliance posture, see docs/compliance.md.

Vulnerabilities should be reported through GitHub Private Vulnerability Reporting or the process in SECURITY.md.

Do not report real-world vulnerabilities through public GitHub issues.

Docs

MSRV

Rust 1.91.0.

The pinned nightly in rust-toolchain.toml is used for Miri, fuzzing, and exotic-architecture checks.

License

Dual-licensed under Apache-2.0 or MIT, at your option.