Skip to main content

rscrypto/
lib.rs

1//! Pure Rust cryptography, hardware-accelerated on ten architectures. `no_std` first.
2//!
3//! `rscrypto` is a single-crate cryptography stack: hashes, AEADs, MACs, KDFs,
4//! password hashing, signatures, key exchange, and checksums. Enable one leaf
5//! feature for a minimal build (`sha2`, `aes-gcm`, `ed25519`, anything) or
6//! `full` for the entire primitive set. Zero default dependencies; `getrandom`,
7//! `serde`, and `rayon` are opt-in.
8//!
9//! The portable Rust path is the byte-for-byte authority. SIMD and ASM kernels
10//! are accelerators, differential-tested against the portable path on every
11//! release. Three-tier dispatch (compile-time `target_feature` → runtime
12//! detection → portable fallback) picks the fastest safe backend at runtime;
13//! without `std`, only the compile-time tier runs.
14//!
15//! ```toml
16//! [dependencies]
17//! rscrypto = { version = "0.1", default-features = false, features = ["sha2"] }
18//! ```
19//!
20//! # Guides
21//!
22//! - Repository README: <https://github.com/loadingalias/rscrypto#readme>
23//! - Runnable examples: <https://github.com/loadingalias/rscrypto/tree/main/examples>
24//! - Additional docs: <https://github.com/loadingalias/rscrypto/tree/main/docs>
25//! - Security guidance: <https://github.com/loadingalias/rscrypto/blob/main/docs/security.md>
26//!
27//! # API Shape
28//!
29//! - Checksums: `Type::checksum(data)` or `new` / `update` / `finalize`.
30//! - Digests: `Type::digest(data)` or `new` / `update` / `finalize`.
31//! - XOFs: `Type::xof(data)` or `new` / `update` / `finalize_xof`.
32//! - MACs: `Type::mac(key, data)` and `Type::verify_tag(key, data, tag)`.
33//! - AEADs: typed keys and nonces, with combined and detached APIs.
34#![cfg_attr(
35  feature = "sha2",
36  doc = r#"
37# Quick Start
38
39```rust
40use rscrypto::{Digest, Sha256};
41
42let digest = Sha256::digest(b"hello world");
43
44let mut h = Sha256::new();
45h.update(b"hello ");
46h.update(b"world");
47assert_eq!(h.finalize(), digest);
48```
49"#
50)]
51#![cfg_attr(
52  feature = "chacha20poly1305",
53  doc = r#"
54# AEAD
55
56```rust
57use rscrypto::{Aead, ChaCha20Poly1305, ChaCha20Poly1305Key, aead::Nonce96};
58
59let key = ChaCha20Poly1305Key::from_bytes([0x11; 32]);
60let nonce = Nonce96::from_bytes([0x22; Nonce96::LENGTH]);
61let cipher = ChaCha20Poly1305::new(&key);
62
63let mut buffer = *b"data";
64let tag = cipher.encrypt_in_place(&nonce, b"aad", &mut buffer)?;
65cipher.decrypt_in_place(&nonce, b"aad", &mut buffer, &tag)?;
66assert_eq!(&buffer, b"data");
67# Ok::<(), Box<dyn std::error::Error>>(())
68```
69"#
70)]
71#![cfg_attr(
72  all(feature = "password-hashing", feature = "getrandom"),
73  doc = r#"
74# Password Hashing
75
76```rust
77use rscrypto::{Argon2Params, Argon2VerifyPolicy, Argon2id};
78
79let params = Argon2Params::new().build()?;
80let encoded = Argon2id::hash_string(&params, b"correct horse battery staple")?;
81
82assert!(
83  Argon2id::verify_string_with_policy(
84    b"correct horse battery staple",
85    &encoded,
86    &Argon2VerifyPolicy::default(),
87  )
88  .is_ok()
89);
90# Ok::<(), Box<dyn std::error::Error>>(())
91```
92"#
93)]
94//! # Feature Groups
95//!
96//! - `checksums`: CRC families.
97//! - `hashes`: SHA-2, SHA-3, BLAKE2, BLAKE3, Ascon, XXH3, RapidHash.
98//! - `auth`: MACs, KDFs, password hashing, Ed25519, X25519.
99//! - `aead`: AES-GCM, AES-GCM-SIV, ChaCha20-Poly1305, XChaCha20-Poly1305, AEGIS-256, Ascon-AEAD128.
100//! - `full`: all public primitive families.
101//!
102//! Leaf features are available for size-conscious builds.
103//!
104//! # Security Posture
105//!
106//! Constant-time MAC, AEAD, and signature verification with `black_box`
107//! barriers. Opaque verification errors that leak no failure detail. Zeroize
108//! on drop for every secret-bearing type. `strict_*` arithmetic on counters
109//! and lengths; release builds keep `overflow-checks = true`. Continuous
110//! libFuzzer with corpus replay in CI; Miri on the portable backends.
111//!
112//! `rscrypto` is a primitives crate, not a FIPS 140-3 validated module. It
113//! exposes FIPS-aligned primitives (AES-256-GCM, SHA-2, SHA-3 / SHAKE, HMAC,
114//! KMAC, HKDF, PBKDF2) alongside non-FIPS ones. The `portable-only` feature
115//! flag forces dispatch to the constant-time portable backend for FIPS /
116//! DO-178C / ISO 26262 / IEC 62443 deployments. See the security guidance
117//! for nonce lifecycle, PHC verification limits, and platform fallback notes.
118
119#![cfg_attr(not(test), deny(clippy::unwrap_used))]
120#![cfg_attr(not(test), deny(clippy::expect_used))]
121#![cfg_attr(not(test), deny(clippy::indexing_slicing))]
122// Exotic-architecture backends require nightly-only features (inline asm +
123// portable_simd + unstable target-feature flags). Primary targets (x86_64,
124// aarch64, wasm) compile on stable Rust 1.91.0.
125#![cfg_attr(target_arch = "powerpc64", feature(portable_simd, powerpc_target_feature))]
126// s390x VGFM backend uses vector asm + portable SIMD, and
127// target_feature_inline_always is still required for inline vector helpers.
128#![cfg_attr(
129  target_arch = "s390x",
130  feature(asm_experimental_reg, portable_simd, target_feature_inline_always)
131)]
132// riscv64 backends use nightly target-feature flags; individual backend
133// families opt into asm register classes, crypto intrinsics, or portable SIMD.
134#![cfg_attr(target_arch = "riscv64", feature(riscv_target_feature))]
135#![cfg_attr(
136  all(
137    target_arch = "riscv64",
138    any(
139      feature = "crc16",
140      feature = "crc24",
141      feature = "crc32",
142      feature = "crc64",
143      feature = "xxh3",
144      feature = "aes-gcm",
145      feature = "aes-gcm-siv",
146      feature = "aegis256"
147    )
148  ),
149  feature(asm_experimental_reg)
150)]
151#![cfg_attr(
152  all(
153    target_arch = "riscv64",
154    any(feature = "sha2", feature = "aes-gcm", feature = "aes-gcm-siv", feature = "aegis256")
155  ),
156  feature(riscv_ext_intrinsics)
157)]
158#![cfg_attr(
159  all(
160    target_arch = "riscv64",
161    any(feature = "blake3", feature = "chacha20poly1305", feature = "xchacha20poly1305")
162  ),
163  feature(portable_simd)
164)]
165#![cfg_attr(target_arch = "riscv32", feature(riscv_ext_intrinsics, riscv_target_feature))]
166#![cfg_attr(docsrs, feature(doc_cfg))]
167#![cfg_attr(not(feature = "std"), no_std)]
168
169#[cfg(feature = "alloc")]
170extern crate alloc;
171
172// Tests use alloc types (Vec, String) for constructing inputs regardless of feature flags.
173// The alloc crate is always in the sysroot; this brings the name into scope for test builds
174// when the `alloc` feature is off.
175#[cfg(all(test, not(feature = "alloc")))]
176extern crate alloc;
177
178// Tests use std-backed runtime feature detection and the test harness regardless
179// of whether the crate's `std` feature is enabled.
180#[cfg(any(feature = "std", test))]
181extern crate std;
182
183#[macro_use]
184mod macros;
185
186// Internal modules (not published as separate crates)
187#[cfg(any(
188  feature = "aes-gcm",
189  feature = "aes-gcm-siv",
190  feature = "chacha20poly1305",
191  feature = "xchacha20poly1305",
192  feature = "aegis256",
193  feature = "ascon-aead",
194  feature = "ed25519",
195  feature = "x25519"
196))]
197#[macro_use]
198mod hex;
199
200#[cfg(any(
201  feature = "aes-gcm",
202  feature = "aes-gcm-siv",
203  feature = "chacha20poly1305",
204  feature = "xchacha20poly1305",
205  feature = "aegis256",
206  feature = "ascon-aead"
207))]
208pub mod aead;
209#[cfg(any(
210  feature = "hmac",
211  feature = "hkdf",
212  feature = "kmac",
213  feature = "ed25519",
214  feature = "x25519",
215  feature = "phc-strings",
216  feature = "argon2",
217  feature = "scrypt"
218))]
219pub mod auth;
220#[doc(hidden)]
221mod backend;
222pub mod platform;
223pub mod traits;
224
225#[cfg(any(feature = "crc16", feature = "crc24", feature = "crc32", feature = "crc64"))]
226pub mod checksum;
227
228/// Implement [`std::io::Read`] for an [`Xof`](crate::traits::Xof) type by
229/// delegating to `squeeze`.
230#[cfg(any(feature = "sha3", feature = "blake3", feature = "ascon-hash"))]
231macro_rules! impl_xof_read {
232  ($type:ty) => {
233    #[cfg(feature = "std")]
234    impl std::io::Read for $type {
235      #[inline]
236      fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
237        self.squeeze(buf);
238        Ok(buf.len())
239      }
240    }
241  };
242}
243
244mod secret;
245
246#[cfg(any(
247  feature = "sha2",
248  feature = "sha3",
249  feature = "blake2b",
250  feature = "blake2s",
251  feature = "blake3",
252  feature = "ascon-hash",
253  feature = "xxh3",
254  feature = "rapidhash"
255))]
256pub mod hashes;
257
258#[cfg_attr(
259  not(any(feature = "kmac", feature = "ascon-hash", feature = "sha3")),
260  allow(dead_code)
261)]
262#[inline]
263#[track_caller]
264pub(crate) fn bytes_to_bits(len: usize) -> u64 {
265  let Ok(bytes) = u64::try_from(len) else {
266    panic!("byte length exceeds u64");
267  };
268  let Some(bits) = bytes.checked_mul(8) else {
269    panic!("byte length bit count exceeds u64");
270  };
271  bits
272}
273
274// Checksum re-exports.
275
276#[cfg(feature = "aead")]
277pub use aead::{AeadBufferError, OpenError};
278#[cfg(feature = "aegis256")]
279pub use aead::{Aegis256, Aegis256Key, Aegis256Tag};
280#[cfg(feature = "aes-gcm")]
281pub use aead::{Aes256Gcm, Aes256GcmKey, Aes256GcmTag};
282#[cfg(feature = "aes-gcm-siv")]
283pub use aead::{Aes256GcmSiv, Aes256GcmSivKey, Aes256GcmSivTag};
284#[cfg(feature = "ascon-aead")]
285pub use aead::{AsconAead128, AsconAead128Key, AsconAead128Tag};
286#[cfg(feature = "chacha20poly1305")]
287pub use aead::{ChaCha20Poly1305, ChaCha20Poly1305Key, ChaCha20Poly1305Tag};
288#[cfg(feature = "xchacha20poly1305")]
289pub use aead::{XChaCha20Poly1305, XChaCha20Poly1305Key, XChaCha20Poly1305Tag};
290#[cfg(feature = "hkdf")]
291pub use auth::HkdfOutputLengthError;
292#[cfg(feature = "kmac")]
293pub use auth::Kmac256;
294#[cfg(feature = "phc-strings")]
295pub use auth::PhcError;
296#[cfg(feature = "argon2")]
297pub use auth::{Argon2Error, Argon2Params, Argon2VerifyPolicy, Argon2Version, Argon2d, Argon2i, Argon2id};
298#[cfg(feature = "ed25519")]
299pub use auth::{Ed25519Keypair, Ed25519PublicKey, Ed25519SecretKey, Ed25519Signature};
300#[cfg(feature = "hkdf")]
301pub use auth::{HkdfSha256, HkdfSha384};
302#[cfg(feature = "hmac")]
303pub use auth::{HmacSha256, HmacSha384, HmacSha512};
304#[cfg(feature = "pbkdf2")]
305pub use auth::{Pbkdf2Error, Pbkdf2Sha256, Pbkdf2Sha512};
306#[cfg(feature = "scrypt")]
307pub use auth::{Scrypt, ScryptError, ScryptParams, ScryptVerifyPolicy};
308#[cfg(feature = "x25519")]
309pub use auth::{X25519Error, X25519PublicKey, X25519SecretKey, X25519SharedSecret};
310#[cfg(feature = "crc24")]
311pub use checksum::Crc24OpenPgp;
312#[cfg(feature = "crc16")]
313pub use checksum::{Crc16Ccitt, Crc16Ibm};
314#[cfg(feature = "crc32")]
315pub use checksum::{Crc32, Crc32C};
316#[cfg(feature = "crc64")]
317pub use checksum::{Crc64, Crc64Nvme};
318// Hash re-exports.
319#[cfg(feature = "ascon-hash")]
320pub use hashes::crypto::ascon::AsconCxofCustomizationError;
321#[cfg(feature = "ascon-hash")]
322pub use hashes::crypto::{AsconCxof128, AsconCxof128Reader, AsconHash256, AsconXof, AsconXofReader};
323#[cfg(feature = "blake2b")]
324pub use hashes::crypto::{Blake2b, Blake2b256, Blake2b512, Blake2bParams};
325#[cfg(feature = "blake2s")]
326pub use hashes::crypto::{Blake2s128, Blake2s256, Blake2sParams};
327#[cfg(feature = "blake3")]
328pub use hashes::crypto::{Blake3, Blake3XofReader};
329#[cfg(feature = "sha3")]
330pub use hashes::crypto::{
331  Cshake256, Cshake256XofReader, Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake128XofReader, Shake256,
332  Shake256XofReader,
333};
334#[cfg(feature = "sha2")]
335pub use hashes::crypto::{Sha224, Sha256, Sha384, Sha512, Sha512_256};
336#[cfg(all(feature = "rapidhash", feature = "alloc"))]
337pub use hashes::fast::{RapidBuildHasher, RapidHasher};
338#[cfg(feature = "rapidhash")]
339pub use hashes::fast::{RapidHash, RapidHash128, RapidHashFast64, RapidHashFast128};
340#[cfg(feature = "xxh3")]
341pub use hashes::fast::{Xxh3, Xxh3_128};
342#[cfg(all(feature = "xxh3", feature = "alloc"))]
343pub use hashes::fast::{Xxh3BuildHasher, Xxh3Hasher};
344// Hex re-exports.
345#[cfg(any(
346  feature = "aes-gcm",
347  feature = "aes-gcm-siv",
348  feature = "chacha20poly1305",
349  feature = "xchacha20poly1305",
350  feature = "aegis256",
351  feature = "ascon-aead",
352  feature = "ed25519",
353  feature = "x25519"
354))]
355pub use hex::{DisplaySecret, InvalidHexError};
356pub use secret::SecretBytes;
357// Trait re-exports.
358#[cfg(any(
359  feature = "aes-gcm",
360  feature = "aes-gcm-siv",
361  feature = "chacha20poly1305",
362  feature = "xchacha20poly1305",
363  feature = "aegis256",
364  feature = "ascon-aead"
365))]
366pub use traits::Aead;
367pub use traits::{Checksum, ChecksumCombine, ConstantTimeEq, Mac, VerificationError, ct};
368#[cfg(any(
369  feature = "sha2",
370  feature = "sha3",
371  feature = "blake2b",
372  feature = "blake2s",
373  feature = "blake3",
374  feature = "ascon-hash",
375  feature = "xxh3",
376  feature = "rapidhash"
377))]
378pub use traits::{Digest, FastHash, Xof};
379
380#[cfg(all(doctest, feature = "full", feature = "getrandom"))]
381#[doc = include_str!("../README.md")]
382pub struct ReadmeDoctests;
383
384#[cfg(all(doctest, feature = "full", feature = "diag"))]
385#[doc(hidden)]
386#[doc = r#"
387```compile_fail
388use rscrypto::Crc32Config;
389```
390
391```compile_fail
392use rscrypto::DispatchInfo;
393```
394
395```compile_fail
396use rscrypto::kernel_for;
397```
398
399```compile_fail
400use rscrypto::backend_for;
401```
402
403```compile_fail
404use rscrypto::backend;
405```
406
407```compile_fail
408use rscrypto::Crc32Ieee;
409```
410
411```compile_fail
412use rscrypto::Crc32Castagnoli;
413```
414
415```compile_fail
416use rscrypto::Crc64Xz;
417```
418
419```compile_fail
420use rscrypto::AsconXof128;
421```
422
423```compile_fail
424use rscrypto::AsconXof128Reader;
425```
426
427```compile_fail
428use rscrypto::BufferedCrc32C;
429```
430
431```compile_fail
432use rscrypto::Xxh3_64;
433```
434
435```compile_fail
436use rscrypto::RapidHash64;
437```
438
439```compile_fail
440use rscrypto::checksum::BufferedCrc32C;
441```
442
443```compile_fail
444use rscrypto::platform_describe;
445```
446
447```compile_fail
448use rscrypto::DigestReader;
449```
450
451```rust
452use rscrypto::checksum::config::Crc32Config;
453use rscrypto::checksum::buffered::BufferedCrc32C;
454use rscrypto::checksum::introspect::{DispatchInfo, kernel_for};
455use rscrypto::checksum::{Crc32Castagnoli, Crc32Ieee, Crc64Xz};
456use rscrypto::hashes::fast::{RapidHash64, RapidHashFast128, RapidHashFast64, Xxh3_64};
457use rscrypto::hashes::introspect::{KernelIntrospect, kernel_for as hash_kernel_for};
458use rscrypto::hashes::DigestReader;
459use rscrypto::{AsconXof, AsconXofReader, RapidHash, Xxh3};
460
461fn assert_hash_introspect<T: KernelIntrospect>() {}
462
463let _ = rscrypto::platform::describe();
464let _: Crc32Config = rscrypto::Crc32::config();
465let _ = kernel_for::<rscrypto::Crc32>(64);
466let _ = DispatchInfo::current();
467let _ = hash_kernel_for::<rscrypto::Sha256>(1024);
468assert_hash_introspect::<rscrypto::Sha256>();
469let _ = (core::any::TypeId::of::<Crc32Ieee>(), core::any::TypeId::of::<Crc32Castagnoli>(), core::any::TypeId::of::<Crc64Xz>());
470let _ = (core::any::TypeId::of::<AsconXof>(), core::any::TypeId::of::<AsconXofReader>());
471let _ = core::any::TypeId::of::<BufferedCrc32C>();
472let _ = (core::any::TypeId::of::<Xxh3>(), core::any::TypeId::of::<Xxh3_64>());
473let _ = (core::any::TypeId::of::<RapidHash>(), core::any::TypeId::of::<RapidHash64>());
474let _ = (core::any::TypeId::of::<RapidHashFast64>(), core::any::TypeId::of::<RapidHashFast128>());
475```
476"#]
477pub struct __RootSurfaceAudit;
478
479#[cfg(all(doctest, feature = "full"))]
480#[doc(hidden)]
481#[doc = r#"
482```rust
483use rscrypto::{
484  Blake3, Digest, Sha224, Sha256, Sha384, Sha512, Sha512_256, Sha3_224, Sha3_256, Sha3_384, Sha3_512,
485};
486
487fn assert_digest_api<D>()
488where
489  D: Digest,
490  D::Output: PartialEq + core::fmt::Debug,
491{
492  let mut h = D::new();
493  h.update(b"abc");
494  let expected = h.finalize();
495  h.reset();
496  h.update(b"abc");
497  assert_eq!(h.finalize(), expected);
498}
499
500assert_digest_api::<Sha224>();
501assert_digest_api::<Sha256>();
502assert_digest_api::<Sha384>();
503assert_digest_api::<Sha512>();
504assert_digest_api::<Sha512_256>();
505assert_digest_api::<Sha3_224>();
506assert_digest_api::<Sha3_256>();
507assert_digest_api::<Sha3_384>();
508assert_digest_api::<Sha3_512>();
509assert_digest_api::<Blake3>();
510```
511
512```rust
513use rscrypto::{AsconXof, Blake3, Digest, Shake128, Shake256, Xof};
514
515fn squeeze_32(mut reader: impl Xof) -> [u8; 32] {
516  let mut out = [0u8; 32];
517  reader.squeeze(&mut out);
518  out
519}
520
521macro_rules! assert_xof_api {
522  ($ty:ty) => {{
523    let data = b"abc";
524    let mut h = <$ty>::new();
525    h.update(data);
526    let streaming = squeeze_32(h.clone().finalize_xof());
527    h.reset();
528    let oneshot = squeeze_32(<$ty>::xof(data));
529    assert_eq!(streaming, oneshot);
530  }};
531}
532
533assert_xof_api!(Shake128);
534assert_xof_api!(Shake256);
535assert_xof_api!(Blake3);
536assert_xof_api!(AsconXof);
537```
538
539```rust
540use std::io::{Cursor, Read, Write};
541
542use rscrypto::{Checksum as _, Crc32C};
543
544let mut reader = Crc32C::reader(Cursor::new(b"abc".to_vec()));
545std::io::copy(&mut reader, &mut std::io::sink())?;
546assert_eq!(reader.checksum(), Crc32C::checksum(b"abc"));
547
548let mut writer = Crc32C::writer(Vec::new());
549writer.write_all(b"abc")?;
550assert_eq!(writer.checksum(), Crc32C::checksum(b"abc"));
551# Ok::<(), std::io::Error>(())
552```
553
554```compile_fail
555use std::io::Cursor;
556
557use rscrypto::{Checksum as _, Crc32C};
558
559let reader = Crc32C::reader(Cursor::new(b"abc".to_vec()));
560let _ = reader.crc();
561```
562
563```compile_fail
564use rscrypto::{Checksum as _, Crc32C};
565
566let writer = Crc32C::writer(Vec::<u8>::new());
567let _ = writer.crc();
568```
569"#]
570pub struct __ApiPatternAudit;
571
572// Compile-time trait assertions.
573//
574// Every public type must be Send + Sync + Debug.  Most must also be Clone.
575// These static assertions fail the build if any contract is broken.
576
577#[cfg(all(test, miri))]
578mod miri_shadow_tests;
579
580#[cfg(test)]
581mod length_framing_tests {
582  #[test]
583  fn bytes_to_bits_accepts_max_encodable_len() {
584    assert_eq!(super::bytes_to_bits((u64::MAX / 8) as usize), u64::MAX - 7);
585  }
586
587  #[test]
588  #[cfg(target_pointer_width = "64")]
589  #[should_panic(expected = "byte length bit count exceeds u64")]
590  fn bytes_to_bits_rejects_bit_count_overflow() {
591    let _ = super::bytes_to_bits((u64::MAX / 8).strict_add(1) as usize);
592  }
593}
594
595#[cfg(test)]
596mod send_sync_assertions {
597  #![allow(unused_imports)]
598  use super::*;
599
600  fn assert_send_sync<T: Send + Sync>() {}
601  fn assert_clone<T: Clone>() {}
602  fn assert_debug<T: core::fmt::Debug>() {}
603
604  #[test]
605  fn public_types_are_send_and_sync() {
606    // Traits. Object safety is separate; this checks the types.
607    assert_send_sync::<traits::error::VerificationError>();
608
609    // Platform.
610    assert_send_sync::<platform::Caps>();
611    assert_send_sync::<platform::Arch>();
612    assert_send_sync::<platform::Detected>();
613    assert_send_sync::<platform::OverrideError>();
614    assert_send_sync::<platform::Description>();
615  }
616
617  #[test]
618  #[cfg(feature = "checksums")]
619  fn checksum_types_are_send_and_sync() {
620    // CRC-16
621    assert_send_sync::<Crc16Ccitt>();
622    assert_send_sync::<Crc16Ibm>();
623    assert_send_sync::<checksum::config::Crc16Force>();
624    assert_send_sync::<checksum::config::Crc16Config>();
625
626    // CRC-24
627    assert_send_sync::<Crc24OpenPgp>();
628    assert_send_sync::<checksum::config::Crc24Force>();
629    assert_send_sync::<checksum::config::Crc24Config>();
630
631    // CRC-32
632    assert_send_sync::<Crc32>();
633    assert_send_sync::<Crc32C>();
634    assert_send_sync::<checksum::config::Crc32Force>();
635    assert_send_sync::<checksum::config::Crc32Config>();
636
637    // CRC-64
638    assert_send_sync::<Crc64>();
639    assert_send_sync::<Crc64Nvme>();
640    assert_send_sync::<checksum::config::Crc64Force>();
641    assert_send_sync::<checksum::config::Crc64Config>();
642
643    #[cfg(feature = "diag")]
644    {
645      assert_send_sync::<checksum::introspect::DispatchInfo>();
646      assert_send_sync::<checksum::diag::SelectionReason>();
647      assert_send_sync::<checksum::diag::Crc32Polynomial>();
648      assert_send_sync::<checksum::diag::Crc64Polynomial>();
649      assert_send_sync::<checksum::diag::Crc32SelectionDiag>();
650      assert_send_sync::<checksum::diag::Crc64SelectionDiag>();
651    }
652  }
653
654  #[test]
655  #[cfg(all(feature = "checksums", feature = "alloc"))]
656  fn buffered_checksum_types_are_send_and_sync() {
657    assert_send_sync::<checksum::buffered::BufferedCrc16Ccitt>();
658    assert_send_sync::<checksum::buffered::BufferedCrc16Ibm>();
659    assert_send_sync::<checksum::buffered::BufferedCrc24OpenPgp>();
660    assert_send_sync::<checksum::buffered::BufferedCrc32>();
661    assert_send_sync::<checksum::buffered::BufferedCrc32C>();
662    assert_send_sync::<checksum::buffered::BufferedCrc64>();
663    assert_send_sync::<checksum::buffered::BufferedCrc64Nvme>();
664  }
665
666  #[test]
667  #[cfg(feature = "hashes")]
668  fn hash_types_are_send_and_sync() {
669    // SHA-2
670    assert_send_sync::<Sha256>();
671    assert_send_sync::<Sha224>();
672    assert_send_sync::<Sha512>();
673    assert_send_sync::<Sha384>();
674    assert_send_sync::<Sha512_256>();
675
676    // SHA-3
677    assert_send_sync::<Sha3_256>();
678    assert_send_sync::<Sha3_224>();
679    assert_send_sync::<Sha3_512>();
680    assert_send_sync::<Sha3_384>();
681    assert_send_sync::<Shake128>();
682    assert_send_sync::<Shake256>();
683    assert_send_sync::<Shake128XofReader>();
684    assert_send_sync::<Shake256XofReader>();
685    assert_send_sync::<Cshake256>();
686    assert_send_sync::<Cshake256XofReader>();
687
688    // ASCON
689    assert_send_sync::<AsconHash256>();
690    assert_send_sync::<AsconXof>();
691    assert_send_sync::<AsconXofReader>();
692    assert_send_sync::<AsconCxof128>();
693    assert_send_sync::<AsconCxof128Reader>();
694
695    // BLAKE3
696    assert_send_sync::<Blake3>();
697    assert_send_sync::<Blake3XofReader>();
698
699    // Fast hashes
700    assert_send_sync::<Xxh3>();
701    assert_send_sync::<Xxh3_128>();
702    assert_send_sync::<RapidHash>();
703    assert_send_sync::<RapidHash128>();
704    assert_send_sync::<hashes::fast::RapidHashFast64>();
705    assert_send_sync::<hashes::fast::RapidHashFast128>();
706
707    // BuildHasher types
708    #[cfg(feature = "alloc")]
709    {
710      assert_send_sync::<Xxh3BuildHasher>();
711      assert_send_sync::<Xxh3Hasher>();
712      assert_send_sync::<RapidBuildHasher>();
713      assert_send_sync::<RapidHasher>();
714    }
715  }
716
717  #[test]
718  #[cfg(all(feature = "checksums", feature = "std"))]
719  fn io_adapter_types_are_send_and_sync() {
720    // ChecksumReader/Writer are Send+Sync when their inner types are
721    assert_send_sync::<traits::io::ChecksumReader<std::io::Cursor<Vec<u8>>, Crc32C>>();
722    assert_send_sync::<traits::io::ChecksumWriter<Vec<u8>, Crc32C>>();
723  }
724
725  #[test]
726  #[cfg(all(feature = "hashes", feature = "std"))]
727  fn digest_io_adapter_types_are_send_and_sync() {
728    assert_send_sync::<hashes::DigestReader<std::io::Cursor<Vec<u8>>, Sha256>>();
729    assert_send_sync::<hashes::DigestWriter<Vec<u8>, Sha256>>();
730  }
731
732  // Clone + Debug assertions.
733
734  #[test]
735  fn platform_types_are_clone_and_debug() {
736    assert_clone::<platform::Caps>();
737    assert_clone::<platform::Arch>();
738    assert_clone::<platform::Detected>();
739    assert_clone::<platform::OverrideError>();
740    assert_clone::<platform::Description>();
741    assert_clone::<traits::error::VerificationError>();
742
743    assert_debug::<platform::Caps>();
744    assert_debug::<platform::Arch>();
745    assert_debug::<platform::Detected>();
746    assert_debug::<platform::OverrideError>();
747    assert_debug::<platform::Description>();
748    assert_debug::<traits::error::VerificationError>();
749  }
750
751  #[test]
752  #[cfg(feature = "checksums")]
753  fn checksum_types_are_clone_and_debug() {
754    assert_clone::<Crc16Ccitt>();
755    assert_clone::<Crc16Ibm>();
756    assert_clone::<Crc24OpenPgp>();
757    assert_clone::<Crc32>();
758    assert_clone::<Crc32C>();
759    assert_clone::<Crc64>();
760    assert_clone::<Crc64Nvme>();
761    assert_clone::<checksum::config::Crc16Force>();
762    assert_clone::<checksum::config::Crc16Config>();
763    assert_clone::<checksum::config::Crc24Force>();
764    assert_clone::<checksum::config::Crc24Config>();
765    assert_clone::<checksum::config::Crc32Force>();
766    assert_clone::<checksum::config::Crc32Config>();
767    assert_clone::<checksum::config::Crc64Force>();
768    assert_clone::<checksum::config::Crc64Config>();
769    assert_debug::<Crc16Ccitt>();
770    assert_debug::<Crc16Ibm>();
771    assert_debug::<Crc24OpenPgp>();
772    assert_debug::<Crc32>();
773    assert_debug::<Crc32C>();
774    assert_debug::<Crc64>();
775    assert_debug::<Crc64Nvme>();
776    assert_debug::<checksum::config::Crc16Force>();
777    assert_debug::<checksum::config::Crc16Config>();
778    assert_debug::<checksum::config::Crc24Force>();
779    assert_debug::<checksum::config::Crc24Config>();
780    assert_debug::<checksum::config::Crc32Force>();
781    assert_debug::<checksum::config::Crc32Config>();
782    assert_debug::<checksum::config::Crc64Force>();
783    assert_debug::<checksum::config::Crc64Config>();
784    #[cfg(feature = "diag")]
785    {
786      assert_clone::<checksum::introspect::DispatchInfo>();
787      assert_debug::<checksum::introspect::DispatchInfo>();
788    }
789  }
790
791  #[test]
792  #[cfg(all(feature = "checksums", feature = "alloc"))]
793  fn buffered_checksum_types_are_clone_and_debug() {
794    assert_debug::<checksum::buffered::BufferedCrc16Ccitt>();
795    assert_debug::<checksum::buffered::BufferedCrc16Ibm>();
796    assert_debug::<checksum::buffered::BufferedCrc24OpenPgp>();
797    assert_debug::<checksum::buffered::BufferedCrc32>();
798    assert_debug::<checksum::buffered::BufferedCrc32C>();
799    assert_debug::<checksum::buffered::BufferedCrc64>();
800    assert_debug::<checksum::buffered::BufferedCrc64Nvme>();
801  }
802
803  #[test]
804  #[cfg(feature = "hashes")]
805  fn hash_types_are_clone_and_debug() {
806    assert_clone::<Sha256>();
807    assert_clone::<Sha224>();
808    assert_clone::<Sha512>();
809    assert_clone::<Sha384>();
810    assert_clone::<Sha512_256>();
811    assert_clone::<Sha3_256>();
812    assert_clone::<Sha3_224>();
813    assert_clone::<Sha3_512>();
814    assert_clone::<Sha3_384>();
815    assert_clone::<Shake128>();
816    assert_clone::<Shake256>();
817    assert_clone::<Shake128XofReader>();
818    assert_clone::<Shake256XofReader>();
819    assert_clone::<Cshake256>();
820    assert_clone::<Cshake256XofReader>();
821    assert_clone::<AsconHash256>();
822    assert_clone::<AsconXof>();
823    assert_clone::<AsconXofReader>();
824    assert_clone::<AsconCxof128>();
825    assert_clone::<AsconCxof128Reader>();
826    assert_clone::<Blake3>();
827    assert_clone::<Blake3XofReader>();
828    assert_clone::<Xxh3>();
829    assert_clone::<Xxh3_128>();
830    assert_clone::<RapidHash>();
831    assert_clone::<RapidHash128>();
832    assert_clone::<hashes::fast::RapidHashFast64>();
833    assert_clone::<hashes::fast::RapidHashFast128>();
834
835    assert_debug::<Sha256>();
836    assert_debug::<Sha224>();
837    assert_debug::<Sha512>();
838    assert_debug::<Sha384>();
839    assert_debug::<Sha512_256>();
840    assert_debug::<Sha3_256>();
841    assert_debug::<Sha3_224>();
842    assert_debug::<Sha3_512>();
843    assert_debug::<Sha3_384>();
844    assert_debug::<Shake128>();
845    assert_debug::<Shake256>();
846    assert_debug::<Shake128XofReader>();
847    assert_debug::<Shake256XofReader>();
848    assert_debug::<Cshake256>();
849    assert_debug::<Cshake256XofReader>();
850    assert_debug::<AsconHash256>();
851    assert_debug::<AsconXof>();
852    assert_debug::<AsconXofReader>();
853    assert_debug::<AsconCxof128>();
854    assert_debug::<AsconCxof128Reader>();
855    assert_debug::<Blake3>();
856    assert_debug::<Blake3XofReader>();
857    assert_debug::<Xxh3>();
858    assert_debug::<Xxh3_128>();
859    assert_debug::<RapidHash>();
860    assert_debug::<RapidHash128>();
861    assert_debug::<hashes::fast::RapidHashFast64>();
862    assert_debug::<hashes::fast::RapidHashFast128>();
863
864    // BuildHasher types
865    #[cfg(feature = "alloc")]
866    {
867      assert_clone::<Xxh3BuildHasher>();
868      assert_clone::<RapidBuildHasher>();
869      assert_debug::<Xxh3BuildHasher>();
870      assert_debug::<Xxh3Hasher>();
871      assert_debug::<RapidBuildHasher>();
872      assert_debug::<RapidHasher>();
873    }
874  }
875
876  #[test]
877  #[cfg(all(feature = "checksums", feature = "std"))]
878  fn io_adapter_types_are_debug() {
879    assert_debug::<traits::io::ChecksumReader<std::io::Cursor<Vec<u8>>, Crc32C>>();
880    assert_debug::<traits::io::ChecksumWriter<Vec<u8>, Crc32C>>();
881  }
882
883  #[test]
884  #[cfg(all(feature = "hashes", feature = "std"))]
885  fn digest_io_adapter_types_are_debug() {
886    assert_debug::<hashes::DigestReader<std::io::Cursor<Vec<u8>>, Sha256>>();
887    assert_debug::<hashes::DigestWriter<Vec<u8>, Sha256>>();
888  }
889}