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
43pub mod channel;
44#[cfg(feature = "async")]
45pub mod channel_async;
46mod error;
47mod exchange;
48mod group;
49mod identity;
50pub mod password;
51mod ratchet;
52mod rotation;
53mod shield;
54mod signatures;
55mod stream;
56mod totp;
57#[cfg(feature = "wasm")]
58mod wasm;
59
60pub use channel::{ChannelConfig, ShieldChannel, ShieldListener};
61#[cfg(feature = "async")]
62pub use channel_async::AsyncShieldChannel;
63pub use error::{Result, ShieldError};
64pub use exchange::{KeySplitter, PAKEExchange, QRExchange};
65pub use group::{BroadcastEncryption, EncryptedBroadcast, EncryptedGroupMessage, GroupEncryption};
66pub use identity::{Identity, IdentityProvider, SecureSession, Session};
67pub use ratchet::RatchetSession;
68pub use rotation::KeyRotationManager;
69pub use shield::Shield;
70pub use signatures::{LamportSignature, SymmetricSignature};
71pub use stream::StreamCipher;
72pub use totp::{RecoveryCodes, TOTP};
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}