1#![forbid(unsafe_code)]
38#![warn(clippy::all, clippy::pedantic)]
39#![allow(clippy::module_name_repetitions)]
40#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)]
42
43mod error;
44mod shield;
45mod stream;
46mod ratchet;
47mod totp;
48mod signatures;
49mod exchange;
50mod rotation;
51mod group;
52mod identity;
53pub mod password;
54pub mod channel;
55#[cfg(feature = "async")]
56pub mod channel_async;
57#[cfg(feature = "wasm")]
58mod wasm;
59
60pub use error::{ShieldError, Result};
61pub use shield::Shield;
62pub use stream::StreamCipher;
63pub use ratchet::RatchetSession;
64pub use totp::{TOTP, RecoveryCodes};
65pub use signatures::{SymmetricSignature, LamportSignature};
66pub use exchange::{PAKEExchange, QRExchange, KeySplitter};
67pub use rotation::KeyRotationManager;
68pub use group::{GroupEncryption, BroadcastEncryption, EncryptedGroupMessage, EncryptedBroadcast};
69pub use identity::{IdentityProvider, Identity, Session, SecureSession};
70pub use channel::{ShieldChannel, ChannelConfig, ShieldListener};
71#[cfg(feature = "async")]
72pub use channel_async::AsyncShieldChannel;
73
74#[cfg(feature = "wasm")]
75pub use wasm::*;
76
77pub fn quick_encrypt(key: &[u8; 32], data: &[u8]) -> Result<Vec<u8>> {
79 Shield::encrypt_with_key(key, data)
80}
81
82pub fn quick_decrypt(key: &[u8; 32], encrypted: &[u8]) -> Result<Vec<u8>> {
84 Shield::decrypt_with_key(key, encrypted)
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_roundtrip() {
93 let shield = Shield::new("test_password", "test.service");
94 let plaintext = b"Hello, EXPTIME-secure world!";
95
96 let encrypted = shield.encrypt(plaintext).unwrap();
97 let decrypted = shield.decrypt(&encrypted).unwrap();
98
99 assert_eq!(plaintext.as_slice(), decrypted.as_slice());
100 }
101
102 #[test]
103 fn test_quick_functions() {
104 let key = [0x42u8; 32];
105 let data = b"Quick test message";
106
107 let encrypted = quick_encrypt(&key, data).unwrap();
108 let decrypted = quick_decrypt(&key, &encrypted).unwrap();
109
110 assert_eq!(data.as_slice(), decrypted.as_slice());
111 }
112
113 #[test]
114 fn test_tamper_detection() {
115 let shield = Shield::new("password", "service");
116 let mut encrypted = shield.encrypt(b"data").unwrap();
117
118 encrypted[20] ^= 0xFF;
120
121 assert!(shield.decrypt(&encrypted).is_err());
122 }
123
124 #[test]
125 fn test_wrong_password() {
126 let shield1 = Shield::new("password1", "service");
127 let shield2 = Shield::new("password2", "service");
128
129 let encrypted = shield1.encrypt(b"secret").unwrap();
130
131 assert!(shield2.decrypt(&encrypted).is_err());
132 }
133
134 #[test]
135 fn test_different_services() {
136 let shield1 = Shield::new("password", "service1");
137 let shield2 = Shield::new("password", "service2");
138
139 let encrypted = shield1.encrypt(b"secret").unwrap();
140
141 assert!(shield2.decrypt(&encrypted).is_err());
142 }
143}