#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![cfg_attr(not(feature = "std"), no_std)]
pub mod aead;
pub mod asym;
pub mod encoding;
pub mod errors;
pub mod hash;
pub mod kdf;
pub mod key_rotation;
pub mod kw;
pub mod mac;
pub mod rand;
pub mod secrets;
pub mod utils;
pub use aead::{AesGcm256, ChaCha20Poly1305, Ciphertext, CrabAead};
pub use asym::{Ed25519KeyPair, X25519KeyPair};
pub use errors::{CrabError, CrabResult};
pub use hash::{sha256, sha512};
#[cfg(feature = "extended-hashes")]
pub use hash::{blake2b_512, blake2s_256, blake3_hash, blake3_hex, sha3_256, sha3_512};
pub use kdf::{argon2_derive, hkdf_extract_expand, pbkdf2_derive};
pub use mac::{hmac_sha256, hmac_sha256_verify};
pub use secrets::{SecretArray, SecretVec};
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub mod prelude {
pub use crate::{
aead::{AesGcm128, AesGcm256, ChaCha20Poly1305, Ciphertext, CrabAead},
asym::{
Ed25519KeyPair, Ed25519PublicKey, Ed25519Signature, X25519KeyPair, X25519PublicKey,
X25519SharedSecret,
},
encoding::{base64_decode, base64_encode, hex_decode, hex_encode},
hash::{sha256, sha256_hex, sha512, sha512_hex},
kdf::{
argon2_derive, argon2_derive_with_params, hkdf_extract_expand, hkdf_sha256,
pbkdf2_derive, pbkdf2_derive_sha256, pbkdf2_derive_sha512, Argon2Params,
},
mac::{hmac_sha256, hmac_sha256_verify, hmac_sha512, hmac_sha512_verify},
rand::{generate_key_256, secure_bytes},
secrets::{SecretArray, SecretVec},
CrabError, CrabResult,
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_version() {
assert!(VERSION.starts_with("0."));
}
#[test]
fn test_full_workflow() {
let password = b"my_secret_password";
let salt = rand::secure_bytes(16).unwrap();
let key_material = kdf::pbkdf2_derive(password, &salt, 10_000, 32).unwrap();
let cipher = AesGcm256::new(key_material.as_slice()).unwrap();
let plaintext = b"Sensitive data";
let ciphertext = cipher.encrypt(plaintext, None).unwrap();
let decrypted = cipher.decrypt(&ciphertext, None).unwrap();
assert_eq!(decrypted, plaintext);
let keypair = Ed25519KeyPair::generate().unwrap();
let signature = keypair.sign(&ciphertext.to_bytes());
assert!(keypair.verify(&ciphertext.to_bytes(), &signature).unwrap());
}
#[test]
fn test_key_exchange_with_encryption() {
let alice = X25519KeyPair::generate().unwrap();
let bob = X25519KeyPair::generate().unwrap();
let alice_shared = alice.diffie_hellman(&bob.public_key()).unwrap();
let bob_shared = bob.diffie_hellman(&alice.public_key()).unwrap();
let alice_key = alice_shared.derive_key(b"chat_app_v1", 32).unwrap();
let bob_key = bob_shared.derive_key(b"chat_app_v1", 32).unwrap();
let alice_cipher = AesGcm256::new(alice_key.as_slice()).unwrap();
let message = b"Hello Bob!";
let ciphertext = alice_cipher.encrypt(message, None).unwrap();
let bob_cipher = AesGcm256::new(bob_key.as_slice()).unwrap();
let decrypted = bob_cipher.decrypt(&ciphertext, None).unwrap();
assert_eq!(decrypted, message);
}
}