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.6.4", 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 policy: <https://github.com/loadingalias/rscrypto/blob/main/SECURITY.md>
26//! - Threat model: <https://github.com/loadingalias/rscrypto/blob/main/THREAT_MODEL.md>
27//!
28//! # API Shape
29//!
30//! - Checksums: `Type::checksum(data)` or `new` / `update` / `finalize`.
31//! - Digests: `Type::digest(data)` or `new` / `update` / `finalize`.
32//! - XOFs: `Type::xof(data)` or `new` / `update` / `finalize_xof`.
33//! - MACs: `Type::mac(key, data)` and `Type::verify_tag(key, data, tag)`.
34//! - AEADs: typed keys and nonces, with combined, detached, and `alloc` Vec helpers.
35#![cfg_attr(
36  feature = "sha2",
37  doc = r#"
38# Quick Start
39
40```rust
41use rscrypto::{Digest, Sha256};
42
43let digest = Sha256::digest(b"hello world");
44
45let mut h = Sha256::new();
46h.update(b"hello ");
47h.update(b"world");
48assert_eq!(h.finalize(), digest);
49```
50"#
51)]
52#![cfg_attr(
53  feature = "chacha20poly1305",
54  doc = r#"
55# AEAD
56
57```rust
58# #[cfg(feature = "getrandom")]
59# {
60use rscrypto::{Aead, ChaCha20Poly1305, ChaCha20Poly1305Key};
61
62let key = ChaCha20Poly1305Key::from_bytes([0x11; 32]);
63let cipher = ChaCha20Poly1305::new(&key);
64
65let mut sealed = [0u8; 4 + ChaCha20Poly1305::TAG_SIZE];
66let nonce = cipher.seal_random(b"aad", b"data", &mut sealed)?;
67
68let mut opened = [0u8; 4];
69cipher.decrypt(&nonce, b"aad", &sealed, &mut opened)?;
70assert_eq!(&opened, b"data");
71# }
72# Ok::<(), Box<dyn std::error::Error>>(())
73```
74"#
75)]
76#![cfg_attr(
77  all(feature = "password-hashing", feature = "getrandom"),
78  doc = r#"
79# Password Hashing
80
81```rust
82use rscrypto::Argon2idPassword;
83
84let passwords = Argon2idPassword::default();
85let encoded = passwords.hash_password(b"correct horse battery staple")?;
86
87assert!(
88  passwords
89    .verify_password(b"correct horse battery staple", &encoded)
90    .is_ok()
91);
92# Ok::<(), Box<dyn std::error::Error>>(())
93```
94"#
95)]
96//! # Feature Groups
97//!
98//! - `checksums`: CRC families.
99//! - `hashes`: SHA-2, SHA-3, BLAKE2, BLAKE3, Ascon, XXH3, RapidHash.
100//! - `auth`: MACs, KDFs, password hashing, ECDSA signing/verification, Ed25519, RSA
101//!   signing/verification/OAEP, X25519.
102//! - `aead`: AES-GCM, AES-GCM-SIV, ChaCha20-Poly1305, XChaCha20-Poly1305, AEGIS-256, Ascon-AEAD128.
103//! - `full`: all public primitive families.
104//!
105//! Leaf features are available for size-conscious builds.
106//!
107//! # Security Posture
108//!
109//! Fixed-size secret-bearing owners expose comparison through an opaque
110//! [`ct::CtDecision`] and require explicit declassification. Public structural
111//! rejects such as malformed lengths, unsupported algorithms, or out-of-range
112//! RSA representatives may fail before the full primitive work. Opaque
113//! verification errors leak no failure detail. Generated-code constant-time
114//! claims remain compiler-, target-, feature-, and release-evidence-bound.
115//! Zeroize on drop for every secret-bearing type. `strict_*` arithmetic on
116//! counters and lengths; release builds keep `overflow-checks = true`.
117//! Continuous libFuzzer with corpus replay in CI; Miri on the portable backends.
118//!
119//! `rscrypto` is a primitives crate, not a FIPS 140-3 validated module. It
120//! exposes FIPS-aligned primitives (AES-256-GCM, SHA-2, SHA-3 / SHAKE, HMAC,
121//! KMAC, HKDF, PBKDF2) alongside non-FIPS ones. The `portable-only` feature
122//! makes runtime capability detection report no SIMD/ASM capabilities, so
123//! dispatchers that consult runtime caps fall through to portable backends.
124//! It is a deployment control, not a substitute for release constant-time
125//! evidence. See the security guidance for nonce lifecycle, PHC verification
126//! limits, and platform fallback notes.
127
128#![cfg_attr(not(test), deny(clippy::unwrap_used))]
129#![cfg_attr(not(test), deny(clippy::expect_used))]
130#![cfg_attr(not(test), deny(clippy::indexing_slicing))]
131// Exotic-architecture backends require nightly-only features (inline asm +
132// portable_simd + unstable target-feature flags). Primary targets (x86_64,
133// aarch64, wasm) compile on stable Rust 1.91.0.
134#![cfg_attr(
135  all(
136    target_arch = "powerpc64",
137    any(
138      feature = "crc16",
139      feature = "crc24",
140      feature = "crc32",
141      feature = "crc64",
142      feature = "aes-gcm",
143      feature = "aes-gcm-siv",
144      feature = "aegis256",
145      feature = "blake3",
146      feature = "xxh3",
147      feature = "chacha20poly1305",
148      feature = "xchacha20poly1305",
149      feature = "argon2"
150    )
151  ),
152  feature(portable_simd, powerpc_target_feature)
153)]
154// s390x VGFM/hash backends use vector asm; selected checksum/hash/AEAD/password
155// kernels also use portable SIMD.
156#![cfg_attr(target_arch = "s390x", feature(asm_experimental_reg))]
157#![cfg_attr(
158  all(
159    target_arch = "s390x",
160    any(
161      feature = "crc16",
162      feature = "crc24",
163      feature = "crc32",
164      feature = "crc64",
165      feature = "aes-gcm",
166      feature = "aes-gcm-siv",
167      feature = "aegis256",
168      feature = "blake3",
169      feature = "xxh3",
170      feature = "chacha20poly1305",
171      feature = "xchacha20poly1305",
172      feature = "ml-kem",
173      feature = "argon2"
174    )
175  ),
176  feature(portable_simd)
177)]
178// RISC-V CRC/vector/AES-style backends still need nightly target-feature names.
179// SHA-2's Zknh intrinsics are gated separately by `riscv_ext_intrinsics`.
180#![cfg_attr(
181  all(
182    target_arch = "riscv64",
183    any(
184      feature = "crc16",
185      feature = "crc24",
186      feature = "crc32",
187      feature = "crc64",
188      feature = "blake2b",
189      feature = "blake2s",
190      feature = "blake3",
191      feature = "aes-gcm",
192      feature = "aes-gcm-siv",
193      feature = "chacha20poly1305",
194      feature = "xchacha20poly1305",
195      feature = "aegis256",
196      feature = "argon2"
197    )
198  ),
199  feature(riscv_target_feature)
200)]
201#![cfg_attr(
202  all(
203    target_arch = "riscv64",
204    any(
205      feature = "crc16",
206      feature = "crc24",
207      feature = "crc32",
208      feature = "crc64",
209      feature = "aes-gcm",
210      feature = "aes-gcm-siv",
211      feature = "aegis256"
212    )
213  ),
214  feature(asm_experimental_reg)
215)]
216#![cfg_attr(
217  all(
218    target_arch = "riscv64",
219    any(feature = "sha2", feature = "aes-gcm", feature = "aes-gcm-siv", feature = "aegis256")
220  ),
221  feature(riscv_ext_intrinsics)
222)]
223#![cfg_attr(
224  all(
225    target_arch = "riscv64",
226    any(feature = "blake3", feature = "chacha20poly1305", feature = "xchacha20poly1305")
227  ),
228  feature(portable_simd)
229)]
230#![cfg_attr(
231  all(
232    target_arch = "riscv32",
233    any(feature = "sha2", feature = "aes-gcm", feature = "aes-gcm-siv", feature = "aegis256")
234  ),
235  feature(riscv_ext_intrinsics)
236)]
237#![cfg_attr(docsrs, feature(doc_cfg))]
238#![cfg_attr(not(feature = "std"), no_std)]
239
240#[cfg(feature = "alloc")]
241extern crate alloc;
242
243// Tests use alloc types (Vec, String) for constructing inputs regardless of feature flags.
244// The alloc crate is always in the sysroot; this brings the name into scope for test builds
245// when the `alloc` feature is off.
246#[cfg(all(test, not(feature = "alloc")))]
247extern crate alloc;
248
249// Tests use std-backed runtime feature detection and the test harness regardless
250// of whether the crate's `std` feature is enabled.
251#[cfg(any(feature = "std", test))]
252extern crate std;
253
254#[macro_use]
255mod macros;
256
257// Internal modules (not published as separate crates)
258// `hex` is an internal utility module for public byte newtypes that expose
259// hex formatting, parsing, or explicit secret display.
260// Public re-exports of `expert::DisplaySecret` / `InvalidHexError` stay gated
261// to the features that surface them in the public API.
262#[cfg(any(
263  feature = "aes-gcm",
264  feature = "aes-gcm-siv",
265  feature = "chacha20poly1305",
266  feature = "xchacha20poly1305",
267  feature = "aegis256",
268  feature = "ascon-aead",
269  feature = "ecdsa-p256",
270  feature = "ecdsa-p384",
271  feature = "ed25519",
272  feature = "x25519",
273  feature = "ml-kem",
274  feature = "blake3"
275))]
276#[macro_use]
277mod hex;
278
279#[cfg(any(
280  feature = "aes-gcm",
281  feature = "aes-gcm-siv",
282  feature = "chacha20poly1305",
283  feature = "xchacha20poly1305",
284  feature = "aegis256",
285  feature = "ascon-aead"
286))]
287pub mod aead;
288#[cfg(any(
289  feature = "hmac",
290  feature = "hmac-sha3",
291  feature = "hkdf",
292  feature = "kmac",
293  feature = "poly1305",
294  feature = "ecdsa-p256",
295  feature = "ecdsa-p384",
296  feature = "ed25519",
297  feature = "ml-kem",
298  feature = "rsa",
299  feature = "x25519",
300  feature = "phc-strings",
301  feature = "argon2",
302  feature = "scrypt"
303))]
304pub mod auth;
305#[doc(hidden)]
306mod backend;
307pub mod platform;
308pub mod traits;
309
310#[cfg(any(feature = "crc16", feature = "crc24", feature = "crc32", feature = "crc64"))]
311pub mod checksum;
312
313/// Implement [`std::io::Read`] for an [`Xof`](crate::traits::Xof) type by
314/// delegating to `squeeze`.
315#[cfg(any(feature = "sha3", feature = "blake3", feature = "ascon-hash"))]
316macro_rules! impl_xof_read {
317  ($type:ty) => {
318    #[cfg(feature = "std")]
319    impl std::io::Read for $type {
320      #[inline]
321      fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
322        self.squeeze(buf);
323        Ok(buf.len())
324      }
325    }
326  };
327}
328
329mod secret;
330
331#[cfg(any(
332  feature = "sha2",
333  feature = "sha3",
334  feature = "blake2b",
335  feature = "blake2s",
336  feature = "blake3",
337  feature = "ascon-hash",
338  feature = "xxh3",
339  feature = "rapidhash"
340))]
341pub mod hashes;
342
343#[cfg_attr(
344  not(any(feature = "kmac", feature = "ascon-hash", feature = "sha3")),
345  allow(dead_code)
346)]
347#[inline]
348#[track_caller]
349pub(crate) fn bytes_to_bits(len: usize) -> u64 {
350  let Ok(bytes) = u64::try_from(len) else {
351    panic!("byte length exceeds u64");
352  };
353  let Some(bits) = bytes.checked_mul(8) else {
354    panic!("byte length bit count exceeds u64");
355  };
356  bits
357}
358
359// Checksum re-exports.
360
361#[cfg(feature = "aead")]
362pub use aead::{AeadBufferError, OpenError};
363#[cfg(feature = "aegis256")]
364pub use aead::{Aegis256, Aegis256Key, Aegis256Tag};
365#[cfg(feature = "aes-gcm")]
366pub use aead::{Aes128Gcm, Aes128GcmKey, Aes128GcmTag};
367#[cfg(feature = "aes-gcm-siv")]
368pub use aead::{Aes128GcmSiv, Aes128GcmSivKey, Aes128GcmSivTag};
369#[cfg(feature = "aes-gcm")]
370pub use aead::{Aes256Gcm, Aes256GcmKey, Aes256GcmTag};
371#[cfg(feature = "aes-gcm-siv")]
372pub use aead::{Aes256GcmSiv, Aes256GcmSivKey, Aes256GcmSivTag};
373#[cfg(feature = "ascon-aead")]
374pub use aead::{AsconAead128, AsconAead128Key, AsconAead128Tag};
375#[cfg(feature = "chacha20poly1305")]
376pub use aead::{ChaCha20Poly1305, ChaCha20Poly1305Key, ChaCha20Poly1305Tag};
377#[cfg(feature = "xchacha20poly1305")]
378pub use aead::{XChaCha20Poly1305, XChaCha20Poly1305Key, XChaCha20Poly1305Tag};
379#[cfg(feature = "hkdf")]
380pub use auth::HkdfOutputLengthError;
381#[cfg(all(feature = "phc-strings", any(feature = "argon2", feature = "scrypt")))]
382pub use auth::PasswordStatus;
383#[cfg(feature = "argon2")]
384pub use auth::{Argon2Context, Argon2Error, Argon2Params, Argon2d, Argon2i, Argon2id};
385#[cfg(all(feature = "argon2", feature = "phc-strings"))]
386pub use auth::{Argon2VerificationLimits, Argon2idPassword};
387#[cfg(any(feature = "ecdsa-p256", feature = "ecdsa-p384"))]
388pub use auth::{EcdsaError, EcdsaKeyGenerationError};
389#[cfg(feature = "ecdsa-p256")]
390pub use auth::{EcdsaP256Keypair, EcdsaP256PublicKey, EcdsaP256SecretKey, EcdsaP256Signature};
391#[cfg(feature = "ecdsa-p384")]
392pub use auth::{EcdsaP384Keypair, EcdsaP384PublicKey, EcdsaP384SecretKey, EcdsaP384Signature};
393#[cfg(feature = "ed25519")]
394pub use auth::{Ed25519Keypair, Ed25519PublicKey, Ed25519SecretKey, Ed25519Signature};
395#[cfg(feature = "hkdf")]
396pub use auth::{HkdfSha256, HkdfSha384, HkdfSha512};
397#[cfg(feature = "hmac-sha3")]
398pub use auth::{
399  HmacSha3_224, HmacSha3_224Tag, HmacSha3_256, HmacSha3_256Tag, HmacSha3_384, HmacSha3_384Tag, HmacSha3_512,
400  HmacSha3_512Tag,
401};
402#[cfg(feature = "hmac")]
403pub use auth::{HmacSha256, HmacSha256Tag, HmacSha384, HmacSha384Tag, HmacSha512, HmacSha512Tag};
404#[cfg(feature = "kmac")]
405pub use auth::{Kmac128, Kmac256};
406#[cfg(feature = "ml-kem")]
407pub use auth::{
408  MlKem512, MlKem512Ciphertext, MlKem512DecapsulationKey, MlKem512EncapsulationKey, MlKem512PreparedDecapsulationKey,
409  MlKem512PreparedEncapsulationKey, MlKem512SharedSecret, MlKem768, MlKem768Ciphertext, MlKem768DecapsulationKey,
410  MlKem768EncapsulationKey, MlKem768PreparedDecapsulationKey, MlKem768PreparedEncapsulationKey, MlKem768SharedSecret,
411  MlKem1024, MlKem1024Ciphertext, MlKem1024DecapsulationKey, MlKem1024EncapsulationKey,
412  MlKem1024PreparedDecapsulationKey, MlKem1024PreparedEncapsulationKey, MlKem1024SharedSecret, MlKemError,
413};
414#[cfg(feature = "pbkdf2")]
415pub use auth::{Pbkdf2Error, Pbkdf2Params, Pbkdf2Sha256, Pbkdf2Sha512, Pbkdf2VerifyPolicy};
416#[cfg(feature = "poly1305")]
417pub use auth::{Poly1305, Poly1305OneTimeKey, Poly1305Tag};
418#[cfg(feature = "rsa")]
419pub use auth::{
420  RsaEncryptionError, RsaJwtAlgorithm, RsaJwtVerifier, RsaKeyError, RsaKeyGenerationContract, RsaKeyGenerationError,
421  RsaOaepProfile, RsaPkcs1v15Profile, RsaPrivateKey, RsaPrivateKeyParts, RsaPrivateOpError, RsaPrivateScratch,
422  RsaProtocolAlgorithmError, RsaPssProfile, RsaPublicExponent, RsaPublicExponentPolicy, RsaPublicKey,
423  RsaPublicKeyPolicy, RsaPublicOpError, RsaPublicScratch, RsaSignatureProfile, RsaSignatureSigner,
424  RsaSignatureVerifier, RsaTlsSignatureSchemes, RsaX509PublicKey, RsaX509PublicKeyAlgorithm,
425};
426#[cfg(feature = "scrypt")]
427pub use auth::{Scrypt, ScryptError, ScryptParams};
428#[cfg(all(feature = "scrypt", feature = "phc-strings"))]
429pub use auth::{ScryptPassword, ScryptVerificationLimits};
430#[cfg(feature = "x25519")]
431pub use auth::{X25519Error, X25519PublicKey, X25519SecretKey, X25519SharedSecret};
432#[cfg(feature = "crc24")]
433pub use checksum::Crc24OpenPgp;
434#[cfg(feature = "crc16")]
435pub use checksum::{Crc16Ccitt, Crc16Ibm};
436#[cfg(feature = "crc32")]
437pub use checksum::{Crc32, Crc32C};
438#[cfg(feature = "crc64")]
439pub use checksum::{Crc64, Crc64Nvme};
440#[cfg(any(feature = "blake2b", feature = "blake2s"))]
441pub use hashes::crypto::Blake2Error;
442// Hash re-exports.
443#[cfg(feature = "ascon-hash")]
444pub use hashes::crypto::ascon::AsconCxofCustomizationError;
445#[cfg(feature = "ascon-hash")]
446pub use hashes::crypto::{AsconCxof128, AsconCxof128Reader, AsconHash256, AsconXof, AsconXofReader};
447#[cfg(feature = "blake2b")]
448pub use hashes::crypto::{Blake2b, Blake2b256, Blake2b512, Blake2bKey, Blake2bParams};
449#[cfg(feature = "blake2s")]
450pub use hashes::crypto::{Blake2s128, Blake2s256, Blake2sKey, Blake2sParams};
451#[cfg(feature = "blake3")]
452pub use hashes::crypto::{Blake3, Blake3KeyedHash, Blake3XofReader};
453#[cfg(feature = "sha3")]
454pub use hashes::crypto::{
455  Cshake128, Cshake128XofReader, Cshake256, Cshake256XofReader, Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128,
456  Shake128XofReader, Shake256, Shake256XofReader,
457};
458#[cfg(feature = "sha2")]
459pub use hashes::crypto::{Sha224, Sha256, Sha384, Sha512, Sha512_256};
460#[cfg(feature = "rapidhash")]
461pub use hashes::fast::{RapidHash64, RapidHasher, RapidRandomState, RapidSeededState, RapidStreamHasher};
462#[cfg(feature = "xxh3")]
463pub use hashes::fast::{Xxh3, Xxh3_128};
464#[cfg(feature = "xxh3")]
465pub use hashes::fast::{Xxh3_128Hasher, Xxh3BuildHasher, Xxh3Hasher};
466// Hex re-exports.
467#[cfg(any(
468  feature = "aes-gcm",
469  feature = "aes-gcm-siv",
470  feature = "chacha20poly1305",
471  feature = "xchacha20poly1305",
472  feature = "aegis256",
473  feature = "ascon-aead",
474  feature = "ecdsa-p256",
475  feature = "ecdsa-p384",
476  feature = "ed25519",
477  feature = "ml-kem",
478  feature = "x25519"
479))]
480pub use hex::InvalidHexError;
481pub use secret::SecretBytes;
482#[cfg(feature = "alloc")]
483pub use secret::SecretVec;
484// Trait re-exports.
485#[cfg(any(
486  feature = "aes-gcm",
487  feature = "aes-gcm-siv",
488  feature = "chacha20poly1305",
489  feature = "xchacha20poly1305",
490  feature = "aegis256",
491  feature = "ascon-aead"
492))]
493pub use traits::Aead;
494pub use traits::{Checksum, ChecksumCombine, Kem, Mac, TrySigner, TrySignerInto, VerificationError, Verifier, ct};
495#[cfg(any(
496  feature = "sha2",
497  feature = "sha3",
498  feature = "blake2b",
499  feature = "blake2s",
500  feature = "blake3",
501  feature = "ascon-hash",
502  feature = "xxh3",
503  feature = "rapidhash"
504))]
505pub use traits::{Digest, FastHash, Xof};
506
507/// Explicitly dangerous capabilities that normal application code does not need.
508///
509/// Their placement is an intentional opt-in, not an additional runtime layer.
510pub mod expert {
511  #[cfg(any(
512    feature = "aes-gcm",
513    feature = "aes-gcm-siv",
514    feature = "chacha20poly1305",
515    feature = "xchacha20poly1305",
516    feature = "aegis256",
517    feature = "ascon-aead",
518    feature = "ecdsa-p256",
519    feature = "ecdsa-p384",
520    feature = "ed25519",
521    feature = "ml-kem",
522    feature = "x25519"
523  ))]
524  pub use crate::hex::DisplaySecret;
525}
526
527/// Trait-first imports for rscrypto user code.
528///
529/// This prelude intentionally re-exports traits and common verification
530/// errors, not algorithm types. Keep primitive choices visible:
531///
532/// ```rust
533/// # #[cfg(feature = "sha2")]
534/// # {
535/// use rscrypto::{Sha256, prelude::*};
536///
537/// let digest = Sha256::digest(b"message");
538/// assert_eq!(digest.len(), Sha256::OUTPUT_SIZE);
539/// # }
540/// ```
541pub mod prelude {
542  #[cfg(any(
543    feature = "aes-gcm",
544    feature = "aes-gcm-siv",
545    feature = "chacha20poly1305",
546    feature = "xchacha20poly1305",
547    feature = "aegis256",
548    feature = "ascon-aead"
549  ))]
550  pub use crate::traits::Aead;
551  pub use crate::traits::{
552    Checksum, ChecksumCombine, Digest, FastHash, Kem, Mac, TrySigner, TrySignerInto, VerificationError, Verifier, Xof,
553  };
554}
555
556#[cfg(all(doctest, feature = "full", feature = "getrandom"))]
557#[doc = include_str!("../README.md")]
558pub struct ReadmeDoctests;
559
560#[cfg(all(doctest, feature = "full", feature = "diag"))]
561#[doc(hidden)]
562#[doc = r#"
563```compile_fail
564use rscrypto::Crc32Config;
565```
566
567```compile_fail
568use rscrypto::DispatchInfo;
569```
570
571```compile_fail
572use rscrypto::kernel_for;
573```
574
575```compile_fail
576use rscrypto::backend_for;
577```
578
579```compile_fail
580use rscrypto::backend;
581```
582
583```compile_fail
584use rscrypto::Crc32Ieee;
585```
586
587```compile_fail
588use rscrypto::Crc32Castagnoli;
589```
590
591```compile_fail
592use rscrypto::Crc64Xz;
593```
594
595```compile_fail
596use rscrypto::AsconXof128;
597```
598
599```compile_fail
600use rscrypto::AsconXof128Reader;
601```
602
603```compile_fail
604use rscrypto::BufferedCrc32C;
605```
606
607```compile_fail
608use rscrypto::Xxh3_64;
609```
610
611```compile_fail
612use rscrypto::RapidHash;
613```
614
615```compile_fail
616use rscrypto::checksum::BufferedCrc32C;
617```
618
619```compile_fail
620use rscrypto::platform_describe;
621```
622
623```compile_fail
624use rscrypto::DigestReader;
625```
626
627```compile_fail
628use rscrypto::diag_hmac_sha256_verify_portable;
629```
630
631```rust
632use rscrypto::checksum::config::Crc32Config;
633use rscrypto::checksum::buffered::BufferedCrc32C;
634use rscrypto::checksum::introspect::{DispatchInfo, kernel_for};
635use rscrypto::checksum::{Crc32Castagnoli, Crc32Ieee, Crc64Xz};
636use rscrypto::hashes::fast::{RapidHash64, Xxh3_64};
637use rscrypto::hashes::introspect::{KernelIntrospect, kernel_for as hash_kernel_for};
638use rscrypto::hashes::DigestReader;
639use rscrypto::{AsconXof, AsconXofReader, Xxh3};
640
641fn assert_hash_introspect<T: KernelIntrospect>() {}
642
643let _ = rscrypto::platform::describe();
644let _: Crc32Config = rscrypto::Crc32::config();
645let _ = kernel_for::<rscrypto::Crc32>(64);
646let _ = DispatchInfo::current();
647let _ = hash_kernel_for::<rscrypto::Sha256>(1024);
648assert_hash_introspect::<rscrypto::Sha256>();
649let _ = (core::any::TypeId::of::<Crc32Ieee>(), core::any::TypeId::of::<Crc32Castagnoli>(), core::any::TypeId::of::<Crc64Xz>());
650let _ = (core::any::TypeId::of::<AsconXof>(), core::any::TypeId::of::<AsconXofReader>());
651let _ = core::any::TypeId::of::<BufferedCrc32C>();
652let _ = (core::any::TypeId::of::<Xxh3>(), core::any::TypeId::of::<Xxh3_64>());
653let _ = core::any::TypeId::of::<RapidHash64>();
654```
655"#]
656pub struct __RootSurfaceAudit;
657
658#[cfg(all(doctest, feature = "full", feature = "getrandom"))]
659#[doc(hidden)]
660#[doc = r#"
661```compile_fail
662use rscrypto::DisplaySecret;
663```
664
665```compile_fail
666use rscrypto::platform::OverrideError;
667```
668
669```compile_fail
670use rscrypto::platform::try_set_override;
671```
672
673```compile_fail
674use rscrypto::aead::{ChaCha20Poly1305Key, Nonce96};
675
676let _ = ChaCha20Poly1305Key::random();
677let _ = Nonce96::random();
678```
679
680```compile_fail
681use rscrypto::{Aead, ChaCha20Poly1305, ChaCha20Poly1305Key, aead::Nonce96};
682
683let cipher = ChaCha20Poly1305::new(&ChaCha20Poly1305Key::from_bytes([0u8; 32]));
684let nonce = Nonce96::from_bytes([0u8; 12]);
685let mut out = [0u8; 16];
686cipher.encrypt(&nonce, b"", b"", &mut out)?;
687```
688
689```compile_fail
690let _ = rscrypto::aead::__SealToken(());
691```
692
693```rust
694use rscrypto::{
695  Aead, ChaCha20Poly1305, ChaCha20Poly1305Key,
696  aead::{Nonce96, expert::AeadWithNonce},
697};
698
699let cipher = ChaCha20Poly1305::new(&ChaCha20Poly1305Key::from_bytes([0u8; 32]));
700let nonce = Nonce96::from_bytes([0u8; 12]);
701let mut out = [0u8; 16];
702cipher.encrypt(&nonce, b"", b"", &mut out)?;
703let display_key = ChaCha20Poly1305Key::from_bytes([0u8; 32]);
704let _: rscrypto::expert::DisplaySecret<'_> = display_key.display_secret();
705let _: Option<rscrypto::platform::expert::OverrideError> = None;
706# Ok::<(), rscrypto::aead::SealError>(())
707```
708"#]
709pub struct __MisuseResistantSurfaceAudit;
710
711#[cfg(all(doctest, feature = "full"))]
712#[doc(hidden)]
713#[doc = r#"
714```rust
715use rscrypto::{
716  Blake3, Digest, Sha224, Sha256, Sha384, Sha512, Sha512_256, Sha3_224, Sha3_256, Sha3_384, Sha3_512,
717};
718
719fn assert_digest_api<D>()
720where
721  D: Digest,
722  D::Output: PartialEq + core::fmt::Debug,
723{
724  let mut h = D::new();
725  h.update(b"abc");
726  let expected = h.finalize();
727  h.reset();
728  h.update(b"abc");
729  assert_eq!(h.finalize(), expected);
730}
731
732assert_digest_api::<Sha224>();
733assert_digest_api::<Sha256>();
734assert_digest_api::<Sha384>();
735assert_digest_api::<Sha512>();
736assert_digest_api::<Sha512_256>();
737assert_digest_api::<Sha3_224>();
738assert_digest_api::<Sha3_256>();
739assert_digest_api::<Sha3_384>();
740assert_digest_api::<Sha3_512>();
741assert_digest_api::<Blake3>();
742```
743
744```rust
745use rscrypto::{AsconXof, Blake3, Digest, Shake128, Shake256, Xof};
746
747fn squeeze_32(mut reader: impl Xof) -> [u8; 32] {
748  let mut out = [0u8; 32];
749  reader.squeeze(&mut out);
750  out
751}
752
753macro_rules! assert_xof_api {
754  ($ty:ty) => {{
755    let data = b"abc";
756    let mut h = <$ty>::new();
757    h.update(data);
758    let streaming = squeeze_32(h.clone().finalize_xof());
759    h.reset();
760    let oneshot = squeeze_32(<$ty>::xof(data));
761    assert_eq!(streaming, oneshot);
762  }};
763}
764
765assert_xof_api!(Shake128);
766assert_xof_api!(Shake256);
767assert_xof_api!(Blake3);
768assert_xof_api!(AsconXof);
769```
770
771```rust
772use std::io::{Cursor, Read, Write};
773
774use rscrypto::{Checksum as _, Crc32C};
775
776let mut reader = Crc32C::reader(Cursor::new(b"abc".to_vec()));
777std::io::copy(&mut reader, &mut std::io::sink())?;
778assert_eq!(reader.checksum(), Crc32C::checksum(b"abc"));
779
780let mut writer = Crc32C::writer(Vec::new());
781writer.write_all(b"abc")?;
782assert_eq!(writer.checksum(), Crc32C::checksum(b"abc"));
783# Ok::<(), std::io::Error>(())
784```
785
786```compile_fail
787use std::io::Cursor;
788
789use rscrypto::{Checksum as _, Crc32C};
790
791let reader = Crc32C::reader(Cursor::new(b"abc".to_vec()));
792let _ = reader.crc();
793```
794
795```compile_fail
796use rscrypto::{Checksum as _, Crc32C};
797
798let writer = Crc32C::writer(Vec::<u8>::new());
799let _ = writer.crc();
800```
801"#]
802pub struct __ApiPatternAudit;
803
804#[cfg(all(doctest, feature = "full"))]
805#[doc(hidden)]
806#[doc = r#"
807```compile_fail
808use rscrypto::ConstantTimeEq;
809```
810
811```compile_fail
812let left = [0u8; 32];
813let right = [0u8; 32];
814let _ = left.ct_eq(&right);
815```
816
817```compile_fail
818let left = [0u8; 32];
819let right = [0u8; 32];
820let _ = rscrypto::ct::constant_time_eq(&left, &right);
821```
822
823```compile_fail
824use rscrypto::SecretBytes;
825
826let left = SecretBytes::new([0u8; 32]);
827let right = SecretBytes::new([0u8; 32]);
828let _ = left == right;
829```
830
831```compile_fail
832use rscrypto::SecretVec;
833
834fn compare(left: &SecretVec, right: &SecretVec) -> bool {
835  left == right
836}
837```
838
839```compile_fail
840use rscrypto::HmacSha256Tag;
841
842let tag = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
843let _ = tag == [0u8; HmacSha256Tag::LENGTH];
844```
845
846```compile_fail
847use rscrypto::HmacSha256Tag;
848
849let left = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
850let right = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
851let _ = left == right;
852```
853
854```compile_fail
855use rscrypto::HmacSha256Tag;
856
857let left = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
858let right = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
859let _: bool = left.ct_eq(&right);
860```
861
862```compile_fail
863use rscrypto::HmacSha256Tag;
864
865let left = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
866let right = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
867let _: bool = left.ct_eq(&right).into();
868```
869
870```compile_fail
871use rscrypto::HmacSha256Tag;
872
873let left = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
874let right = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
875if left.ct_eq(&right) {}
876```
877
878```compile_fail
879let _ = rscrypto::ct::CtDecision { mask: u8::MAX };
880```
881
882```compile_fail
883use rscrypto::HmacSha256Tag;
884
885let left = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
886let right = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
887let decision = left.ct_eq(&right);
888let _ = decision.declassify();
889let _ = decision.declassify();
890```
891
892```compile_fail
893use rscrypto::HmacSha256Tag;
894
895let first = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
896let second = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
897let third = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
898let _ = first.ct_eq(&second) == second.ct_eq(&third);
899```
900
901```compile_fail
902use rscrypto::HmacSha256Tag;
903
904let left = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
905let right = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
906let _ = format!("{:?}", left.ct_eq(&right));
907```
908
909```rust
910use rscrypto::HmacSha256Tag;
911
912let left = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
913let right = HmacSha256Tag::from_bytes([0u8; HmacSha256Tag::LENGTH]);
914assert!(left.ct_eq(&right).declassify());
915```
916"#]
917pub struct __OwnerEqualityBoundaryAudit;
918
919#[cfg(all(doctest, feature = "full"))]
920#[doc(hidden)]
921#[doc = r#"
922The secret-bearing owners below must not acquire a generic `Clone` capability.
923
924```compile_fail,E0277
925use rscrypto::HmacSha256;
926
927fn require_clone<T: Clone>() {}
928require_clone::<HmacSha256>();
929```
930
931```compile_fail,E0277
932use rscrypto::HmacSha384;
933
934fn require_clone<T: Clone>() {}
935require_clone::<HmacSha384>();
936```
937
938```compile_fail,E0277
939use rscrypto::HmacSha512;
940
941fn require_clone<T: Clone>() {}
942require_clone::<HmacSha512>();
943```
944
945```compile_fail,E0277
946use rscrypto::HmacSha3_224;
947
948fn require_clone<T: Clone>() {}
949require_clone::<HmacSha3_224>();
950```
951
952```compile_fail,E0277
953use rscrypto::HmacSha3_256;
954
955fn require_clone<T: Clone>() {}
956require_clone::<HmacSha3_256>();
957```
958
959```compile_fail,E0277
960use rscrypto::HmacSha3_384;
961
962fn require_clone<T: Clone>() {}
963require_clone::<HmacSha3_384>();
964```
965
966```compile_fail,E0277
967use rscrypto::HmacSha3_512;
968
969fn require_clone<T: Clone>() {}
970require_clone::<HmacSha3_512>();
971```
972
973```compile_fail,E0277
974use rscrypto::HkdfSha256;
975
976fn require_clone<T: Clone>() {}
977require_clone::<HkdfSha256>();
978```
979
980```compile_fail,E0277
981use rscrypto::HkdfSha384;
982
983fn require_clone<T: Clone>() {}
984require_clone::<HkdfSha384>();
985```
986
987```compile_fail,E0277
988use rscrypto::HkdfSha512;
989
990fn require_clone<T: Clone>() {}
991require_clone::<HkdfSha512>();
992```
993
994```compile_fail,E0277
995use rscrypto::Kmac128;
996
997fn require_clone<T: Clone>() {}
998require_clone::<Kmac128>();
999```
1000
1001```compile_fail,E0277
1002use rscrypto::Kmac256;
1003
1004fn require_clone<T: Clone>() {}
1005require_clone::<Kmac256>();
1006```
1007
1008```compile_fail,E0277
1009use rscrypto::Pbkdf2Sha256;
1010
1011fn require_clone<T: Clone>() {}
1012require_clone::<Pbkdf2Sha256>();
1013```
1014
1015```compile_fail,E0277
1016use rscrypto::Pbkdf2Sha512;
1017
1018fn require_clone<T: Clone>() {}
1019require_clone::<Pbkdf2Sha512>();
1020```
1021
1022```compile_fail,E0277
1023use rscrypto::Blake2bParams;
1024
1025fn require_clone<T: Clone>() {}
1026require_clone::<Blake2bParams>();
1027```
1028
1029```compile_fail,E0277
1030use rscrypto::Blake2sParams;
1031
1032fn require_clone<T: Clone>() {}
1033require_clone::<Blake2sParams>();
1034```
1035
1036```compile_fail,E0277
1037use rscrypto::Blake2b;
1038
1039fn require_clone<T: Clone>() {}
1040require_clone::<Blake2b>();
1041```
1042
1043```compile_fail,E0277
1044use rscrypto::Poly1305OneTimeKey;
1045
1046fn require_clone<T: Clone>() {}
1047require_clone::<Poly1305OneTimeKey>();
1048```
1049
1050```compile_fail,E0277
1051use rscrypto::Poly1305;
1052
1053fn require_clone<T: Clone>() {}
1054require_clone::<Poly1305>();
1055```
1056
1057```compile_fail,E0277
1058use rscrypto::EcdsaP256SecretKey;
1059
1060fn require_clone<T: Clone>() {}
1061require_clone::<EcdsaP256SecretKey>();
1062```
1063
1064```compile_fail,E0277
1065use rscrypto::EcdsaP256Keypair;
1066
1067fn require_clone<T: Clone>() {}
1068require_clone::<EcdsaP256Keypair>();
1069```
1070
1071```compile_fail,E0277
1072use rscrypto::EcdsaP384SecretKey;
1073
1074fn require_clone<T: Clone>() {}
1075require_clone::<EcdsaP384SecretKey>();
1076```
1077
1078```compile_fail,E0277
1079use rscrypto::EcdsaP384Keypair;
1080
1081fn require_clone<T: Clone>() {}
1082require_clone::<EcdsaP384Keypair>();
1083```
1084
1085```compile_fail,E0277
1086use rscrypto::Ed25519SecretKey;
1087
1088fn require_clone<T: Clone>() {}
1089require_clone::<Ed25519SecretKey>();
1090```
1091
1092```compile_fail,E0277
1093use rscrypto::Ed25519Keypair;
1094
1095fn require_clone<T: Clone>() {}
1096require_clone::<Ed25519Keypair>();
1097```
1098
1099```compile_fail,E0277
1100use rscrypto::X25519SecretKey;
1101
1102fn require_clone<T: Clone>() {}
1103require_clone::<X25519SecretKey>();
1104```
1105
1106```compile_fail,E0277
1107use rscrypto::MlKem512DecapsulationKey;
1108
1109fn require_clone<T: Clone>() {}
1110require_clone::<MlKem512DecapsulationKey>();
1111```
1112
1113```compile_fail,E0277
1114use rscrypto::MlKem768DecapsulationKey;
1115
1116fn require_clone<T: Clone>() {}
1117require_clone::<MlKem768DecapsulationKey>();
1118```
1119
1120```compile_fail,E0277
1121use rscrypto::MlKem1024DecapsulationKey;
1122
1123fn require_clone<T: Clone>() {}
1124require_clone::<MlKem1024DecapsulationKey>();
1125```
1126
1127```compile_fail,E0277
1128use rscrypto::MlKem512PreparedDecapsulationKey;
1129
1130fn require_clone<T: Clone>() {}
1131require_clone::<MlKem512PreparedDecapsulationKey>();
1132```
1133
1134```compile_fail,E0277
1135use rscrypto::MlKem768PreparedDecapsulationKey;
1136
1137fn require_clone<T: Clone>() {}
1138require_clone::<MlKem768PreparedDecapsulationKey>();
1139```
1140
1141```compile_fail,E0277
1142use rscrypto::MlKem1024PreparedDecapsulationKey;
1143
1144fn require_clone<T: Clone>() {}
1145require_clone::<MlKem1024PreparedDecapsulationKey>();
1146```
1147
1148```compile_fail,E0277
1149use rscrypto::RsaPrivateKey;
1150
1151fn require_clone<T: Clone>() {}
1152require_clone::<RsaPrivateKey>();
1153```
1154
1155```compile_fail,E0277
1156use rscrypto::RsaPrivateScratch;
1157
1158fn require_clone<T: Clone>() {}
1159require_clone::<RsaPrivateScratch>();
1160```
1161"#]
1162pub struct __SecretCloneBoundaryAudit;
1163
1164// Positive compile-time trait assertions for public capability contracts.
1165// Secret-bearing non-Clone contracts are compile-fail doctests above.
1166
1167#[cfg(all(test, miri))]
1168mod miri_shadow_tests;
1169
1170#[cfg(test)]
1171mod length_framing_tests {
1172  #[test]
1173  fn bytes_to_bits_accepts_max_encodable_len() {
1174    assert_eq!(super::bytes_to_bits((u64::MAX / 8) as usize), u64::MAX - 7);
1175  }
1176
1177  #[test]
1178  #[cfg(target_pointer_width = "64")]
1179  #[should_panic(expected = "byte length bit count exceeds u64")]
1180  fn bytes_to_bits_rejects_bit_count_overflow() {
1181    let _ = super::bytes_to_bits((u64::MAX / 8).strict_add(1) as usize);
1182  }
1183}
1184
1185#[cfg(all(test, feature = "std", feature = "sha2", feature = "crc32"))]
1186mod direct_io_write_tests {
1187  use std::io::{IoSlice, Write};
1188
1189  use super::{Crc32C, Sha256};
1190  use crate::traits::Checksum as _;
1191
1192  #[test]
1193  fn digest_state_accepts_direct_io_write() {
1194    let mut digest = Sha256::new();
1195    digest.write_all(b"hello ").unwrap();
1196    digest.write_all(b"world").unwrap();
1197
1198    assert_eq!(digest.finalize(), Sha256::digest(b"hello world"));
1199  }
1200
1201  #[test]
1202  fn checksum_state_accepts_direct_io_write() {
1203    let mut checksum = Crc32C::new();
1204    checksum.write_all(b"hello ").unwrap();
1205    checksum.write_all(b"world").unwrap();
1206
1207    assert_eq!(checksum.finalize(), Crc32C::checksum(b"hello world"));
1208  }
1209
1210  #[test]
1211  fn digest_vectored_write_consumes_all_buffers() {
1212    let mut digest = Sha256::new();
1213    let bufs = [IoSlice::new(b"hello "), IoSlice::new(b"world")];
1214
1215    let written = digest.write_vectored(&bufs).unwrap();
1216
1217    assert_eq!(written, b"hello world".len());
1218    assert_eq!(digest.finalize(), Sha256::digest(b"hello world"));
1219  }
1220}
1221
1222#[cfg(test)]
1223mod send_sync_assertions {
1224  #![allow(unused_imports)]
1225  use super::*;
1226
1227  fn assert_send_sync<T: Send + Sync>() {}
1228  fn assert_clone<T: Clone>() {}
1229  fn assert_debug<T: core::fmt::Debug>() {}
1230
1231  #[test]
1232  fn public_types_are_send_and_sync() {
1233    // Traits. Object safety is separate; this checks the types.
1234    assert_send_sync::<traits::error::VerificationError>();
1235
1236    // Platform.
1237    assert_send_sync::<platform::Caps>();
1238    assert_send_sync::<platform::Arch>();
1239    assert_send_sync::<platform::Detected>();
1240    assert_send_sync::<platform::expert::OverrideError>();
1241    assert_send_sync::<platform::Description>();
1242  }
1243
1244  #[test]
1245  #[cfg(feature = "checksums")]
1246  fn checksum_types_are_send_and_sync() {
1247    // CRC-16
1248    assert_send_sync::<Crc16Ccitt>();
1249    assert_send_sync::<Crc16Ibm>();
1250    assert_send_sync::<checksum::config::Crc16Force>();
1251    assert_send_sync::<checksum::config::Crc16Config>();
1252
1253    // CRC-24
1254    assert_send_sync::<Crc24OpenPgp>();
1255    assert_send_sync::<checksum::config::Crc24Force>();
1256    assert_send_sync::<checksum::config::Crc24Config>();
1257
1258    // CRC-32
1259    assert_send_sync::<Crc32>();
1260    assert_send_sync::<Crc32C>();
1261    assert_send_sync::<checksum::config::Crc32Force>();
1262    assert_send_sync::<checksum::config::Crc32Config>();
1263
1264    // CRC-64
1265    assert_send_sync::<Crc64>();
1266    assert_send_sync::<Crc64Nvme>();
1267    assert_send_sync::<checksum::config::Crc64Force>();
1268    assert_send_sync::<checksum::config::Crc64Config>();
1269
1270    #[cfg(feature = "diag")]
1271    {
1272      assert_send_sync::<checksum::introspect::DispatchInfo>();
1273      assert_send_sync::<checksum::diag::SelectionReason>();
1274      assert_send_sync::<checksum::diag::Crc32Polynomial>();
1275      assert_send_sync::<checksum::diag::Crc64Polynomial>();
1276      assert_send_sync::<checksum::diag::Crc32SelectionDiag>();
1277      assert_send_sync::<checksum::diag::Crc64SelectionDiag>();
1278    }
1279  }
1280
1281  #[test]
1282  #[cfg(all(feature = "checksums", feature = "alloc"))]
1283  fn buffered_checksum_types_are_send_and_sync() {
1284    assert_send_sync::<checksum::buffered::BufferedCrc16Ccitt>();
1285    assert_send_sync::<checksum::buffered::BufferedCrc16Ibm>();
1286    assert_send_sync::<checksum::buffered::BufferedCrc24OpenPgp>();
1287    assert_send_sync::<checksum::buffered::BufferedCrc32>();
1288    assert_send_sync::<checksum::buffered::BufferedCrc32C>();
1289    assert_send_sync::<checksum::buffered::BufferedCrc64>();
1290    assert_send_sync::<checksum::buffered::BufferedCrc64Nvme>();
1291  }
1292
1293  #[test]
1294  #[cfg(feature = "hashes")]
1295  fn hash_types_are_send_and_sync() {
1296    // SHA-2
1297    assert_send_sync::<Sha256>();
1298    assert_send_sync::<Sha224>();
1299    assert_send_sync::<Sha512>();
1300    assert_send_sync::<Sha384>();
1301    assert_send_sync::<Sha512_256>();
1302
1303    // SHA-3
1304    assert_send_sync::<Sha3_256>();
1305    assert_send_sync::<Sha3_224>();
1306    assert_send_sync::<Sha3_512>();
1307    assert_send_sync::<Sha3_384>();
1308    assert_send_sync::<Shake128>();
1309    assert_send_sync::<Shake256>();
1310    assert_send_sync::<Shake128XofReader>();
1311    assert_send_sync::<Shake256XofReader>();
1312    assert_send_sync::<Cshake128>();
1313    assert_send_sync::<Cshake256>();
1314    assert_send_sync::<Cshake128XofReader>();
1315    assert_send_sync::<Cshake256XofReader>();
1316
1317    // ASCON
1318    assert_send_sync::<AsconHash256>();
1319    assert_send_sync::<AsconXof>();
1320    assert_send_sync::<AsconXofReader>();
1321    assert_send_sync::<AsconCxof128>();
1322    assert_send_sync::<AsconCxof128Reader>();
1323
1324    // BLAKE3
1325    assert_send_sync::<Blake3>();
1326    assert_send_sync::<Blake3XofReader>();
1327
1328    // Fast hashes
1329    assert_send_sync::<Xxh3>();
1330    assert_send_sync::<Xxh3_128>();
1331    assert_send_sync::<RapidHash64>();
1332
1333    assert_send_sync::<Xxh3BuildHasher>();
1334    assert_send_sync::<Xxh3Hasher>();
1335    assert_send_sync::<Xxh3_128Hasher>();
1336    assert_send_sync::<RapidSeededState>();
1337    assert_send_sync::<RapidRandomState>();
1338    assert_send_sync::<RapidHasher>();
1339    assert_send_sync::<RapidStreamHasher>();
1340  }
1341
1342  #[test]
1343  #[cfg(all(feature = "checksums", feature = "std"))]
1344  fn io_adapter_types_are_send_and_sync() {
1345    // ChecksumReader/Writer are Send+Sync when their inner types are
1346    assert_send_sync::<traits::io::ChecksumReader<std::io::Cursor<Vec<u8>>, Crc32C>>();
1347    assert_send_sync::<traits::io::ChecksumWriter<Vec<u8>, Crc32C>>();
1348  }
1349
1350  #[test]
1351  #[cfg(all(feature = "hashes", feature = "std"))]
1352  fn digest_io_adapter_types_are_send_and_sync() {
1353    assert_send_sync::<hashes::DigestReader<std::io::Cursor<Vec<u8>>, Sha256>>();
1354    assert_send_sync::<hashes::DigestWriter<Vec<u8>, Sha256>>();
1355  }
1356
1357  // Clone + Debug assertions.
1358
1359  #[test]
1360  fn platform_types_are_clone_and_debug() {
1361    assert_clone::<platform::Caps>();
1362    assert_clone::<platform::Arch>();
1363    assert_clone::<platform::Detected>();
1364    assert_clone::<platform::expert::OverrideError>();
1365    assert_clone::<platform::Description>();
1366    assert_clone::<traits::error::VerificationError>();
1367
1368    assert_debug::<platform::Caps>();
1369    assert_debug::<platform::Arch>();
1370    assert_debug::<platform::Detected>();
1371    assert_debug::<platform::expert::OverrideError>();
1372    assert_debug::<platform::Description>();
1373    assert_debug::<traits::error::VerificationError>();
1374  }
1375
1376  #[test]
1377  #[cfg(feature = "checksums")]
1378  fn checksum_types_are_clone_and_debug() {
1379    assert_clone::<Crc16Ccitt>();
1380    assert_clone::<Crc16Ibm>();
1381    assert_clone::<Crc24OpenPgp>();
1382    assert_clone::<Crc32>();
1383    assert_clone::<Crc32C>();
1384    assert_clone::<Crc64>();
1385    assert_clone::<Crc64Nvme>();
1386    assert_clone::<checksum::config::Crc16Force>();
1387    assert_clone::<checksum::config::Crc16Config>();
1388    assert_clone::<checksum::config::Crc24Force>();
1389    assert_clone::<checksum::config::Crc24Config>();
1390    assert_clone::<checksum::config::Crc32Force>();
1391    assert_clone::<checksum::config::Crc32Config>();
1392    assert_clone::<checksum::config::Crc64Force>();
1393    assert_clone::<checksum::config::Crc64Config>();
1394    assert_debug::<Crc16Ccitt>();
1395    assert_debug::<Crc16Ibm>();
1396    assert_debug::<Crc24OpenPgp>();
1397    assert_debug::<Crc32>();
1398    assert_debug::<Crc32C>();
1399    assert_debug::<Crc64>();
1400    assert_debug::<Crc64Nvme>();
1401    assert_debug::<checksum::config::Crc16Force>();
1402    assert_debug::<checksum::config::Crc16Config>();
1403    assert_debug::<checksum::config::Crc24Force>();
1404    assert_debug::<checksum::config::Crc24Config>();
1405    assert_debug::<checksum::config::Crc32Force>();
1406    assert_debug::<checksum::config::Crc32Config>();
1407    assert_debug::<checksum::config::Crc64Force>();
1408    assert_debug::<checksum::config::Crc64Config>();
1409    #[cfg(feature = "diag")]
1410    {
1411      assert_clone::<checksum::introspect::DispatchInfo>();
1412      assert_debug::<checksum::introspect::DispatchInfo>();
1413    }
1414  }
1415
1416  #[test]
1417  #[cfg(all(feature = "checksums", feature = "alloc"))]
1418  fn buffered_checksum_types_are_clone_and_debug() {
1419    assert_debug::<checksum::buffered::BufferedCrc16Ccitt>();
1420    assert_debug::<checksum::buffered::BufferedCrc16Ibm>();
1421    assert_debug::<checksum::buffered::BufferedCrc24OpenPgp>();
1422    assert_debug::<checksum::buffered::BufferedCrc32>();
1423    assert_debug::<checksum::buffered::BufferedCrc32C>();
1424    assert_debug::<checksum::buffered::BufferedCrc64>();
1425    assert_debug::<checksum::buffered::BufferedCrc64Nvme>();
1426  }
1427
1428  #[test]
1429  #[cfg(feature = "hashes")]
1430  fn hash_types_are_clone_and_debug() {
1431    assert_clone::<Sha256>();
1432    assert_clone::<Sha224>();
1433    assert_clone::<Sha512>();
1434    assert_clone::<Sha384>();
1435    assert_clone::<Sha512_256>();
1436    assert_clone::<Sha3_256>();
1437    assert_clone::<Sha3_224>();
1438    assert_clone::<Sha3_512>();
1439    assert_clone::<Sha3_384>();
1440    assert_clone::<Shake128>();
1441    assert_clone::<Shake256>();
1442    assert_clone::<Shake128XofReader>();
1443    assert_clone::<Shake256XofReader>();
1444    assert_clone::<Cshake128>();
1445    assert_clone::<Cshake256>();
1446    assert_clone::<Cshake128XofReader>();
1447    assert_clone::<Cshake256XofReader>();
1448    assert_clone::<AsconHash256>();
1449    assert_clone::<AsconXof>();
1450    assert_clone::<AsconXofReader>();
1451    assert_clone::<AsconCxof128>();
1452    assert_clone::<AsconCxof128Reader>();
1453    assert_clone::<Blake3>();
1454    assert_clone::<Blake3XofReader>();
1455    assert_clone::<Xxh3>();
1456    assert_clone::<Xxh3_128>();
1457    assert_clone::<RapidHash64>();
1458
1459    assert_debug::<Sha256>();
1460    assert_debug::<Sha224>();
1461    assert_debug::<Sha512>();
1462    assert_debug::<Sha384>();
1463    assert_debug::<Sha512_256>();
1464    assert_debug::<Sha3_256>();
1465    assert_debug::<Sha3_224>();
1466    assert_debug::<Sha3_512>();
1467    assert_debug::<Sha3_384>();
1468    assert_debug::<Shake128>();
1469    assert_debug::<Shake256>();
1470    assert_debug::<Shake128XofReader>();
1471    assert_debug::<Shake256XofReader>();
1472    assert_debug::<Cshake128>();
1473    assert_debug::<Cshake256>();
1474    assert_debug::<Cshake128XofReader>();
1475    assert_debug::<Cshake256XofReader>();
1476    assert_debug::<AsconHash256>();
1477    assert_debug::<AsconXof>();
1478    assert_debug::<AsconXofReader>();
1479    assert_debug::<AsconCxof128>();
1480    assert_debug::<AsconCxof128Reader>();
1481    assert_debug::<Blake3>();
1482    assert_debug::<Blake3XofReader>();
1483    assert_debug::<Xxh3>();
1484    assert_debug::<Xxh3_128>();
1485    assert_debug::<RapidHash64>();
1486
1487    assert_clone::<Xxh3BuildHasher>();
1488    assert_clone::<RapidSeededState>();
1489    assert_clone::<RapidRandomState>();
1490    assert_clone::<RapidStreamHasher>();
1491    assert_debug::<Xxh3BuildHasher>();
1492    assert_debug::<Xxh3Hasher>();
1493    assert_debug::<Xxh3_128Hasher>();
1494    assert_debug::<RapidSeededState>();
1495    assert_debug::<RapidRandomState>();
1496    assert_debug::<RapidHasher>();
1497    assert_debug::<RapidStreamHasher>();
1498  }
1499
1500  #[test]
1501  #[cfg(all(feature = "checksums", feature = "std"))]
1502  fn io_adapter_types_are_debug() {
1503    assert_debug::<traits::io::ChecksumReader<std::io::Cursor<Vec<u8>>, Crc32C>>();
1504    assert_debug::<traits::io::ChecksumWriter<Vec<u8>, Crc32C>>();
1505  }
1506
1507  #[test]
1508  #[cfg(all(feature = "hashes", feature = "std"))]
1509  fn digest_io_adapter_types_are_debug() {
1510    assert_debug::<hashes::DigestReader<std::io::Cursor<Vec<u8>>, Sha256>>();
1511    assert_debug::<hashes::DigestWriter<Vec<u8>, Sha256>>();
1512  }
1513}