1mod algorithm;
7mod error;
8mod provider;
9mod secret;
10mod traits;
11
12#[cfg(any(feature = "crypto-ring", feature = "crypto-aws-lc-rs"))]
13mod common;
14pub mod providers;
15
16#[cfg(feature = "test-support")]
17pub mod conformance;
18
19pub use algorithm::*;
20pub use error::CryptoError;
21pub use provider::default_provider;
22pub use secret::SecretVec;
23pub use traits::*;
24
25#[must_use]
27pub fn constant_time_eq(left: &[u8], right: &[u8]) -> bool {
28 use subtle::ConstantTimeEq;
29
30 left.len() == right.len() && bool::from(left.ct_eq(right))
31}
32
33const _: () = {
34 #[allow(dead_code)]
35 #[allow(clippy::too_many_arguments)]
36 fn assert_dyn_compatible(
37 _provider: &dyn RTCCryptoProvider,
38 _crypto: &dyn RTCCrypto,
39 _random: &dyn RTCRandom,
40 _mac: &dyn Mac,
41 _stream: &dyn StreamCipher,
42 _aead: &dyn AeadCipher,
43 _cbc: &dyn CbcCipher,
44 _exchange: &dyn ActiveKeyExchange,
45 _signing_key: &dyn SigningKey,
46 ) {
47 }
48};
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn secret_debug_is_redacted() {
56 let secret = SecretVec::new(vec![1, 2, 3, 4]);
57 let debug = format!("{secret:?}");
58 assert!(debug.contains("REDACTED"));
59 assert!(debug.contains("len: 4"));
60 assert!(!debug.contains("1, 2, 3, 4"));
61 }
62
63 #[test]
64 fn secret_into_bytes_is_explicit() {
65 let secret = SecretVec::new(vec![1, 2, 3]);
66 assert_eq!(secret.into_bytes(), vec![1, 2, 3]);
67 }
68
69 #[test]
70 fn errors_have_provider_neutral_text() {
71 assert_eq!(
72 CryptoError::AuthenticationFailed.to_string(),
73 "authentication failed"
74 );
75 assert_eq!(
76 CryptoError::InvalidSignature.to_string(),
77 "signature verification failed"
78 );
79 }
80
81 #[test]
82 fn constant_time_equality_checks_length_and_content() {
83 assert!(constant_time_eq(b"same", b"same"));
84 assert!(!constant_time_eq(b"same", b"diff"));
85 assert!(!constant_time_eq(b"same", b"same-longer"));
86 }
87}