crabgraph/lib.rs
1//! CrabGraph: A safe, ergonomic cryptographic library for Rust.
2//!
3//! # ⚠️ Security Warning
4//!
5//! **This library has NOT been audited by third-party cryptographic experts.**
6//! While it uses audited primitives (RustCrypto, dalek-cryptography), mistakes
7//! in composition can still lead to vulnerabilities.
8//!
9//! **DO NOT use in production without a professional security audit.**
10//!
11//! # Overview
12//!
13//! CrabGraph provides high-level, safe-by-default cryptographic operations:
14//!
15//! - **Authenticated Encryption (AEAD)**: [`aead::AesGcm256`], [`aead::ChaCha20Poly1305`]
16//! - **Key Derivation**: [`kdf::argon2_derive`], [`kdf::pbkdf2_derive`], [`kdf::hkdf_extract_expand`]
17//! - **Digital Signatures**: [`asym::Ed25519KeyPair`], [`asym::RsaKeyPair`] (with `rsa-support` feature)
18//! - **Key Exchange**: [`asym::X25519KeyPair`]
19//! - **Message Authentication**: [`mac::hmac_sha256`]
20//! - **Hashing**: [`hash::sha256`], [`hash::sha512`]
21//! - **Secure Random**: [`rand::secure_bytes`]
22//!
23//! # ⚠️ RSA Security Warning (rsa-support feature)
24//!
25//! The RSA implementation has a known vulnerability (RUSTSEC-2023-0071 - Marvin timing attack).
26//! **Use Ed25519 for signatures and X25519+AEAD for encryption** unless RSA is specifically
27//! required for compatibility with legacy systems.
28//!
29//! # Quick Start
30//!
31//! ## Authenticated Encryption
32//!
33//! ```
34//! use crabgraph::{aead::{AesGcm256, CrabAead}, CrabResult};
35//!
36//! fn encrypt_example() -> CrabResult<()> {
37//! // Generate a key
38//! let key = AesGcm256::generate_key()?;
39//! let cipher = AesGcm256::new(&key)?;
40//!
41//! // Encrypt
42//! let plaintext = b"Secret message";
43//! let ciphertext = cipher.encrypt(plaintext, None)?;
44//!
45//! // Decrypt
46//! let decrypted = cipher.decrypt(&ciphertext, None)?;
47//! assert_eq!(decrypted, plaintext);
48//!
49//! Ok(())
50//! }
51//! ```
52//!
53//! ## Password Hashing
54//!
55//! ```
56//! use crabgraph::{kdf::argon2_derive, CrabResult};
57//!
58//! fn hash_password() -> CrabResult<()> {
59//! let password = b"user_password";
60//! let salt = crabgraph::rand::secure_bytes(16)?;
61//!
62//! let hash = argon2_derive(password, &salt, 32)?;
63//! // Store hash and salt in database
64//!
65//! Ok(())
66//! }
67//! ```
68//!
69//! ## Digital Signatures
70//!
71//! ```
72//! use crabgraph::{asym::Ed25519KeyPair, CrabResult};
73//!
74//! fn sign_example() -> CrabResult<()> {
75//! let keypair = Ed25519KeyPair::generate()?;
76//! let message = b"Important document";
77//!
78//! let signature = keypair.sign(message);
79//! assert!(keypair.verify(message, &signature)?);
80//!
81//! Ok(())
82//! }
83//! ```
84//!
85//! # Design Principles
86//!
87//! 1. **Safe by Default**: AEAD modes, automatic nonce generation, memory zeroing
88//! 2. **Audited Primitives**: Built on RustCrypto and dalek-cryptography
89//! 3. **Ergonomic API**: Clear function names, comprehensive docs, helpful errors
90//! 4. **Performance**: Zero-copy operations, hardware acceleration support
91//! 5. **Interoperable**: Helpers for compatibility with CryptoJS and OpenSSL
92//!
93//! # Feature Flags
94//!
95//! - `default`: Enables `std` support
96//! - `std`: Standard library support
97//! - `alloc`: Allocation without full std
98//! - `no_std`: Embedded/bare-metal support
99//! - `extended-hashes`: SHA-3 and BLAKE2
100//! - `rsa-support`: RSA encryption/signatures
101//! - `serde-support`: Serialization support
102//! - `zero-copy`: High-performance `bytes` integration
103//! - `wasm`: WebAssembly support
104
105#![warn(missing_docs)]
106#![warn(rust_2018_idioms)]
107#![cfg_attr(not(feature = "std"), no_std)]
108
109pub mod aead;
110pub mod asym;
111pub mod encoding;
112pub mod errors;
113pub mod hash;
114pub mod kdf;
115pub mod key_rotation;
116pub mod kw;
117pub mod mac;
118pub mod rand;
119pub mod secrets;
120pub mod utils;
121
122// Re-export commonly used types
123pub use aead::{AesGcm256, ChaCha20Poly1305, Ciphertext, CrabAead};
124pub use asym::{Ed25519KeyPair, X25519KeyPair};
125pub use errors::{CrabError, CrabResult};
126pub use hash::{sha256, sha512};
127
128// Re-export extended hash functions (when feature is enabled)
129#[cfg(feature = "extended-hashes")]
130pub use hash::{blake2b_512, blake2s_256, blake3_hash, blake3_hex, sha3_256, sha3_512};
131
132pub use kdf::{argon2_derive, hkdf_extract_expand, pbkdf2_derive};
133pub use mac::{hmac_sha256, hmac_sha256_verify};
134pub use secrets::{SecretArray, SecretVec};
135
136/// Library version.
137pub const VERSION: &str = env!("CARGO_PKG_VERSION");
138
139/// Prelude module for convenient imports.
140///
141/// # Example
142///
143/// ```
144/// use crabgraph::prelude::*;
145///
146/// let key = AesGcm256::generate_key()?;
147/// let cipher = AesGcm256::new(&key)?;
148/// # Ok::<(), crabgraph::CrabError>(())
149/// ```
150pub mod prelude {
151 pub use crate::{
152 aead::{AesGcm128, AesGcm256, ChaCha20Poly1305, Ciphertext, CrabAead},
153 asym::{
154 Ed25519KeyPair, Ed25519PublicKey, Ed25519Signature, X25519KeyPair, X25519PublicKey,
155 X25519SharedSecret,
156 },
157 encoding::{base64_decode, base64_encode, hex_decode, hex_encode},
158 hash::{sha256, sha256_hex, sha512, sha512_hex},
159 kdf::{
160 argon2_derive, argon2_derive_with_params, hkdf_extract_expand, hkdf_sha256,
161 pbkdf2_derive, pbkdf2_derive_sha256, pbkdf2_derive_sha512, Argon2Params,
162 },
163 mac::{hmac_sha256, hmac_sha256_verify, hmac_sha512, hmac_sha512_verify},
164 rand::{generate_key_256, secure_bytes},
165 secrets::{SecretArray, SecretVec},
166 CrabError, CrabResult,
167 };
168}
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173
174 #[test]
175 fn test_version() {
176 // Just verify the version string exists and has expected format
177 assert!(VERSION.starts_with("0."));
178 }
179
180 #[test]
181 fn test_full_workflow() {
182 // Test a complete workflow: key derivation -> encryption -> signing
183
184 // 1. Derive a key from password
185 let password = b"my_secret_password";
186 let salt = rand::secure_bytes(16).unwrap();
187 let key_material = kdf::pbkdf2_derive(password, &salt, 10_000, 32).unwrap();
188
189 // 2. Encrypt data
190 let cipher = AesGcm256::new(key_material.as_slice()).unwrap();
191 let plaintext = b"Sensitive data";
192 let ciphertext = cipher.encrypt(plaintext, None).unwrap();
193
194 // 3. Decrypt
195 let decrypted = cipher.decrypt(&ciphertext, None).unwrap();
196 assert_eq!(decrypted, plaintext);
197
198 // 4. Sign the ciphertext
199 let keypair = Ed25519KeyPair::generate().unwrap();
200 let signature = keypair.sign(&ciphertext.to_bytes());
201
202 // 5. Verify signature
203 assert!(keypair.verify(&ciphertext.to_bytes(), &signature).unwrap());
204 }
205
206 #[test]
207 fn test_key_exchange_with_encryption() {
208 // Simulate Alice and Bob doing key exchange and encrypting messages
209
210 // Key exchange
211 let alice = X25519KeyPair::generate().unwrap();
212 let bob = X25519KeyPair::generate().unwrap();
213
214 let alice_shared = alice.diffie_hellman(&bob.public_key()).unwrap();
215 let bob_shared = bob.diffie_hellman(&alice.public_key()).unwrap();
216
217 // Derive encryption key
218 let alice_key = alice_shared.derive_key(b"chat_app_v1", 32).unwrap();
219 let bob_key = bob_shared.derive_key(b"chat_app_v1", 32).unwrap();
220
221 // Alice encrypts
222 let alice_cipher = AesGcm256::new(alice_key.as_slice()).unwrap();
223 let message = b"Hello Bob!";
224 let ciphertext = alice_cipher.encrypt(message, None).unwrap();
225
226 // Bob decrypts
227 let bob_cipher = AesGcm256::new(bob_key.as_slice()).unwrap();
228 let decrypted = bob_cipher.decrypt(&ciphertext, None).unwrap();
229
230 assert_eq!(decrypted, message);
231 }
232}