Skip to main content

rscrypto/
lib.rs

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