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}