🎯 Exemples recommandés
Balanced sample collections from various categories for you to explore
Exemples de Cryptographie Web Rust
Exemples de cryptographie Web Rust incluant le calcul de hash, le chiffrement symétrique et l'encodage Base64
💻 Calcul de Hash rust
🟢 simple
⭐⭐
Calculer les hashes MD5, SHA-1, SHA-256 et SHA-512 en utilisant sha2 et md5 crates
⏱️ 20 min
🏷️ rust, web, cryptography
Prerequisites:
Basic Rust, sha2 crate, md5 crate
// Web Rust Hash Calculation Examples
// Calculate various hash values for data integrity and security
//
// Add to Cargo.toml:
// [dependencies]
// sha2 = "0.10"
// md5 = "0.7"
// hex = "0.4"
use sha2::{Sha256, Sha512, Digest};
use md5::{Md5 as Md5Hash};
// 1. MD5 Hash
/// Calculate MD5 hash of string
fn calculate_md5_string(input: &str) -> String {
let mut hasher = Md5Hash::new();
hasher.update(input.as_bytes());
let result = hasher.finalize();
format!("{:x}", result)
}
/// Calculate MD5 hash of bytes
fn calculate_md5_bytes(data: &[u8]) -> String {
let mut hasher = Md5Hash::new();
hasher.update(data);
let result = hasher.finalize();
format!("{:x}", result)
}
// 2. SHA-1 Hash (using sha2)
/// Calculate SHA-1 hash
fn calculate_sha1(input: &str) -> String {
use sha2::Sha1;
let mut hasher = Sha1::new();
hasher.update(input.as_bytes());
let result = hasher.finalize();
format!("{:x}", result)
}
// 3. SHA-256 Hash
/// Calculate SHA-256 hash of string
fn calculate_sha256_string(input: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(input.as_bytes());
let result = hasher.finalize();
format!("{:x}", result)
}
/// Calculate SHA-256 hash of bytes
fn calculate_sha256_bytes(data: &[u8]) -> String {
let mut hasher = Sha256::new();
hasher.update(data);
let result = hasher.finalize();
format!("{:x}", result)
}
/// Calculate SHA-256 hash of file
fn calculate_sha256_file(path: &str) -> Result<String, std::io::Error> {
use std::io::Read;
let mut file = std::fs::File::open(path)?;
let mut hasher = Sha256::new();
let mut buffer = [0u8; 8192];
loop {
let n = file.read(&mut buffer)?;
if n == 0 {
break;
}
hasher.update(&buffer[..n]);
}
Ok(format!("{:x}", hasher.finalize()))
}
// 4. SHA-512 Hash
/// Calculate SHA-512 hash of string
fn calculate_sha512_string(input: &str) -> String {
let mut hasher = Sha512::new();
hasher.update(input.as_bytes());
let result = hasher.finalize();
format!("{:x}", result)
}
/// Calculate SHA-512 hash of bytes
fn calculate_sha512_bytes(data: &[u8]) -> String {
let mut hasher = Sha512::new();
hasher.update(data);
let result = hasher.finalize();
format!("{:x}", result)
}
// 5. Hash with Salt
/// Hash password with salt using SHA-256
fn hash_password_with_salt(password: &str, salt: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(password.as_bytes());
hasher.update(salt.as_bytes());
let result = hasher.finalize();
format!("{:x}", result)
}
/// Generate random salt
fn generate_salt() -> String {
use rand::Rng;
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789";
let mut rng = rand::thread_rng();
(0..32)
.map(|_| {
let idx = rng.gen_range(0..CHARSET.len());
CHARSET[idx] as char
})
.collect()
}
/// Hash password with auto-generated salt
fn hash_password(password: &str) -> (String, String) {
let salt = generate_salt();
let hash = hash_password_with_salt(password, &salt);
(hash, salt)
}
// 6. Hash Verification
/// Verify password against hash
fn verify_password(password: &str, salt: &str, hash: &str) -> bool {
let computed_hash = hash_password_with_salt(password, salt);
computed_hash == hash
}
// 7. Multiple Hashing (Iterated)
/// Hash with multiple iterations (key stretching)
fn hash_iterations(data: &str, iterations: usize) -> String {
let mut current = data.to_string();
for _ in 0..iterations {
current = calculate_sha256_string(¤t);
}
current
}
// 8. HMAC (Hash-based Message Authentication Code)
/// Calculate HMAC-SHA256
fn calculate_hmac_sha256(message: &str, key: &str) -> String {
use hmac::{Hmac, Mac};
type HmacSha256 = Hmac<Sha256>;
let mut mac = HmacSha256::new_from_slice(key.as_bytes()).expect("HMAC key length error");
mac.update(message.as_bytes());
let result = mac.finalize();
format!("{:x}", result.into_bytes())
}
// 9. Hash Comparison
/// Constant-time hash comparison to prevent timing attacks
fn hash_equals(hash1: &str, hash2: &str) -> bool {
use subtle::ConstantTimeEq;
hash1.as_bytes().ct_eq(hash2.as_bytes()).into()
}
// 10. Checksum
/// Calculate simple checksum
fn calculate_checksum(data: &[u8]) -> u8 {
data.iter().fold(0u8, |acc, &b| acc.wrapping_add(b))
}
/// Calculate CRC32 checksum
fn calculate_crc32(data: &[u8]) -> u32 {
let mut crc: u32 = 0xFFFFFFFF;
for &byte in data {
crc ^= byte as u32;
for _ in 0..8 {
if crc & 1 != 0 {
crc = (crc >> 1) ^ 0xEDB88320;
} else {
crc >>= 1;
}
}
}
!crc
}
// 11. Batch Hashing
/// Hash multiple strings
fn hash_multiple_strings(strings: &[&str]) -> Vec<String> {
strings.iter()
.map(|s| calculate_sha256_string(s))
.collect()
}
/// Find hash collisions (simple check)
fn find_hash_collisions(strings: &[&str]) -> Vec<(String, String, String)> {
use std::collections::HashMap;
let mut hash_map: HashMap<String, Vec<&str>> = HashMap::new();
for &s in strings {
let hash = calculate_sha256_string(s);
hash_map.entry(hash).or_insert_with(Vec::new).push(s);
}
hash_map.into_iter()
.filter(|(_, v)| v.len() > 1)
.flat_map(|(hash, strings)| {
strings.iter().map(move |s| (s.to_string(), hash.clone()))
})
.collect::<Vec<_>>()
.chunks(2)
.map(|c| {
if c.len() == 2 {
(c[0].0.clone(), c[1].0.clone(), c[0].1.clone())
} else {
(String::new(), String::new(), String::new())
}
})
.collect()
}
// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust Hash Calculation Examples ===\n");
let test_string = "Hello, World!";
let test_bytes = b"Hello, World!";
// 1. MD5
println!("--- 1. MD5 Hash ---");
println!("MD5 of '{}': {}", test_string, calculate_md5_string(test_string));
println!("MD5 of bytes: {}", calculate_md5_bytes(test_bytes));
// 2. SHA-1
println!("\n--- 2. SHA-1 Hash ---");
println!("SHA-1 of '{}': {}", test_string, calculate_sha1(test_string));
// 3. SHA-256
println!("\n--- 3. SHA-256 Hash ---");
println!("SHA-256 of '{}': {}", test_string, calculate_sha256_string(test_string));
println!("SHA-256 of bytes: {}", calculate_sha256_bytes(test_bytes));
// 4. SHA-512
println!("\n--- 4. SHA-512 Hash ---");
println!("SHA-512 of '{}': {}", test_string, calculate_sha512_string(test_string));
println!("SHA-512 of bytes: {}", calculate_sha512_bytes(test_bytes));
// 5. Password hashing with salt
println!("\n--- 5. Password Hashing with Salt ---");
let password = "secure_password_123";
let (hash, salt) = hash_password(password);
println!("Password: {}", password);
println!("Salt: {}", salt);
println!("Hash: {}", hash);
// 6. Verify password
println!("\n--- 6. Verify Password ---");
let is_valid = verify_password(password, &salt, &hash);
println!("Password verification: {}", is_valid);
let is_invalid = verify_password("wrong_password", &salt, &hash);
println!("Wrong password verification: {}", is_invalid);
// 7. Iterated hashing
println!("\n--- 7. Iterated Hashing ---");
let iterated = hash_iterations(test_string, 1000);
println!("Hash after 1000 iterations: {}", iterated);
// 8. HMAC
println!("\n--- 8. HMAC-SHA256 ---");
let message = "Important message";
let key = "secret_key";
let hmac = calculate_hmac_sha256(message, key);
println!("HMAC of '{}' with key '{}': {}", message, key, hmac);
// 9. Hash comparison
println!("\n--- 9. Hash Comparison ---");
let hash1 = calculate_sha256_string("test");
let hash2 = calculate_sha256_string("test");
let hash3 = calculate_sha256_string("different");
println!("hash1 vs hash2: {}", hash_equals(&hash1, &hash2));
println!("hash1 vs hash3: {}", hash_equals(&hash1, &hash3));
// 10. Checksums
println!("\n--- 10. Checksums ---");
let checksum = calculate_checksum(test_bytes);
println!("Simple checksum: {}", checksum);
let crc32 = calculate_crc32(test_bytes);
println!("CRC32: {:08x}", crc32);
// 11. Batch hashing
println!("\n--- 11. Batch Hashing ---");
let strings = vec!["hello", "world", "rust"];
let hashes = hash_multiple_strings(&strings);
for (s, h) in strings.iter().zip(hashes.iter()) {
println!("SHA256 of '{}': {}", s, h);
}
println!("\n=== All Hash Calculation Examples Completed ===");
Ok(())
}
💻 Encodage Base64 rust
🟢 simple
⭐⭐
Encoder et décoder des données en utilisant l'encodage Base64 avec des variantes standard et URL-safe
⏱️ 15 min
🏷️ rust, web, cryptography
Prerequisites:
Basic Rust, base64 crate
// Web Rust Base64 Encoding Examples
// Base64 encoding and decoding operations
//
// Add to Cargo.toml:
// [dependencies]
// base64 = "0.21"
use base64::{Engine as _, engine::general_purpose};
// 1. Standard Base64 Encoding
/// Encode bytes to standard Base64
fn encode_base64(data: &[u8]) -> String {
general_purpose::STANDARD.encode(data)
}
/// Decode Base64 to bytes
fn decode_base64(encoded: &str) -> Result<Vec<u8>, base64::DecodeError> {
general_purpose::STANDARD.decode(encoded)
}
/// Encode string to Base64
fn encode_string_base64(input: &str) -> String {
encode_base64(input.as_bytes())
}
// 2. URL-Safe Base64 Encoding
/// Encode bytes to URL-safe Base64
fn encode_base64_url_safe(data: &[u8]) -> String {
general_purpose::URL_SAFE.encode(data)
}
/// Decode URL-safe Base64
fn decode_base64_url_safe(encoded: &str) -> Result<Vec<u8>, base64::DecodeError> {
general_purpose::URL_SAFE.decode(encoded)
}
// 3. Base64 without Padding
/// Encode without padding (no '=' characters)
fn encode_base64_no_pad(data: &[u8]) -> String {
general_purpose::STANDARD_NO_PAD.encode(data)
}
/// Decode Base64 without padding
fn decode_base64_no_pad(encoded: &str) -> Result<Vec<u8>, base64::DecodeError> {
general_purpose::STANDARD_NO_PAD.decode(encoded)
}
// 4. Base64 with Custom Configuration
/// Encode with custom configuration
fn encode_base64_custom(data: &[u8], url_safe: bool, pad: bool) -> String {
use base64::engine::Config;
let config = Config::new()
.with_encode_padding(pad);
if url_safe {
base64::engine::GeneralPurpose::new(
&base64::alphabet::URL_SAFE,
config
).encode(data)
} else {
base64::engine::GeneralPurpose::new(
&base64::alphabet::STANDARD,
config
).encode(data)
}
}
// 5. Binary Data Encoding
/// Encode binary file to Base64
fn encode_file_to_base64(path: &str) -> Result<String, std::io::Error> {
use std::io::Read;
let mut file = std::fs::File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(encode_base64(&buffer))
}
/// Decode Base64 and write to file
fn decode_base64_to_file(encoded: &str, output_path: &str) -> Result<(), std::io::Error> {
use std::io::Write;
let decoded = decode_base64(encoded)?;
let mut file = std::fs::File::create(output_path)?;
file.write_all(&decoded)?;
Ok(())
}
// 6. Stream Encoding
/// Encode data in chunks
fn encode_chunks(data: &[u8], chunk_size: usize) -> Vec<String> {
data.chunks(chunk_size)
.map(|chunk| encode_base64(chunk))
.collect()
}
/// Decode multiple Base64 strings
fn decode_multiple(encoded_strings: &[&str]) -> Result<Vec<u8>, base64::DecodeError> {
let mut result = Vec::new();
for encoded in encoded_strings {
result.extend(decode_base64(encoded)?);
}
Ok(result)
}
// 7. Base64 for URLs
/// Encode data for use in URL parameters
fn encode_for_url(data: &[u8]) -> String {
// Remove padding and use URL-safe alphabet
let encoded = encode_base64_url_safe(data);
encoded.trim_end_matches('=').to_string()
}
/// Decode URL parameter
fn decode_from_url(encoded: &str) -> Result<Vec<u8>, base64::DecodeError> {
// Add padding back if needed
let padded = if encoded.len() % 4 != 0 {
let padding = 4 - (encoded.len() % 4);
format!("{}{}", encoded, "=".repeat(padding))
} else {
encoded.to_string()
};
decode_base64_url_safe(&padded)
}
// 8. Validation
/// Check if string is valid Base64
fn is_valid_base64(s: &str) -> bool {
decode_base64(s).is_ok()
}
/// Check if string is valid URL-safe Base64
fn is_valid_base64_url(s: &str) -> bool {
decode_base64_url_safe(s).is_ok()
}
// 9. Base64 Length Calculation
/// Calculate encoded length from data length
fn calculate_encoded_length(data_len: usize, with_padding: bool) -> usize {
let encoded_len = ((data_len + 2) / 3) * 4;
if with_padding {
encoded_len
} else {
encoded_len - (data_len % 3).min(2)
}
}
/// Calculate decoded length from encoded string
fn calculate_decoded_length(encoded_len: usize) -> usize {
(encoded_len * 3) / 4
}
// 10. Hash Encoding
/// Encode binary hash to Base64 for display
fn encode_hash_to_base64(hash: &[u8]) -> String {
encode_base64(hash)
}
/// Create Base64-encoded SHA256 hash
fn hash_and_encode_base64(data: &[u8]) -> String {
use sha2::{Sha256, Digest};
let mut hasher = Sha256::new();
hasher.update(data);
let hash = hasher.finalize();
encode_base64(&hash)
}
// 11. Comparison
/// Compare two Base64 strings (constant-time)
fn base64_equals(encoded1: &str, encoded2: &str) -> Result<bool, base64::DecodeError> {
use subtle::ConstantTimeEq;
let bytes1 = decode_base64(encoded1)?;
let bytes2 = decode_base64(encoded2)?;
Ok(bytes1.ct_eq(&bytes2).into())
}
// 12. Common Use Cases
/// Encode credentials for Basic Auth
fn encode_basic_auth(username: &str, password: &str) -> String {
let credentials = format!("{}:{}", username, password);
encode_string_base64(&credentials)
}
/// Encode JSON for URL transmission
fn encode_json_for_url<T: serde::Serialize>(data: &T) -> Result<String, Box<dyn std::error::Error>> {
let json = serde_json::to_string(data)?;
Ok(encode_for_url(json.as_bytes()))
}
/// Decode JSON from URL transmission
fn decode_json_from_url<T: for<'de> serde::Deserialize<'de>>(
encoded: &str
) -> Result<T, Box<dyn std::error::Error>> {
let decoded = decode_from_url(encoded)?;
let json_str = String::from_utf8(decoded)?;
let data = serde_json::from_str(&json_str)?;
Ok(data)
}
// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust Base64 Encoding Examples ===\n");
let test_data = b"Hello, World!";
let test_string = "Hello, Base64!";
// 1. Standard encoding
println!("--- 1. Standard Base64 Encoding ---");
let encoded = encode_base64(test_data);
println!("Encoded: {}", encoded);
let decoded = decode_base64(&encoded)?;
println!("Decoded: {}", String::from_utf8(decoded)?);
// 2. String encoding
println!("\n--- 2. String Encoding ---");
let encoded_str = encode_string_base64(test_string);
println!("Encoded string: {}", encoded_str);
// 3. URL-safe encoding
println!("\n--- 3. URL-Safe Encoding ---");
let url_data = b"data with/slashes+and=equals";
let url_encoded = encode_base64_url_safe(url_data);
println!("URL-safe encoded: {}", url_encoded);
let url_decoded = decode_base64_url_safe(&url_encoded)?;
println!("URL-safe decoded: {}", String::from_utf8(url_decoded)?);
// 4. No padding
println!("\n--- 4. Encoding Without Padding ---");
let no_pad = encode_base64_no_pad(test_data);
println!("No padding: {}", no_pad);
println!("Standard: {}", encoded);
// 5. Chunked encoding
println!("\n--- 5. Chunked Encoding ---");
let large_data = b"This is a longer piece of data that will be encoded in chunks";
let chunks = encode_chunks(large_data, 10);
println!("Encoded in {} chunks:", chunks.len());
for (i, chunk) in chunks.iter().enumerate() {
println!(" Chunk {}: {}", i + 1, chunk);
}
// 6. URL encoding
println!("\n--- 6. URL Encoding ---");
let url_safe_data = b"safe for url";
let url_encoded_data = encode_for_url(url_safe_data);
println!("URL encoded: {}", url_encoded_data);
let url_decoded_data = decode_from_url(&url_encoded_data)?;
println!("URL decoded: {}", String::from_utf8(url_decoded_data)?);
// 7. Validation
println!("\n--- 7. Validation ---");
println!("Is valid Base64: {}", is_valid_base64(&encoded));
println!("Is invalid valid: {}", !is_valid_base64("invalid@base64!"));
// 8. Length calculations
println!("\n--- 8. Length Calculations ---");
let data_len = test_data.len();
println!("Original length: {}", data_len);
println!("Encoded length (with padding): {}", calculate_encoded_length(data_len, true));
println!("Encoded length (no padding): {}", calculate_encoded_length(data_len, false));
println!("Actual encoded length: {}", encoded.len());
// 9. Hash encoding
println!("\n--- 9. Hash Encoding ---");
let hash_encoded = hash_and_encode_base64(test_data);
println!("SHA256 as Base64: {}", hash_encoded);
// 10. Basic auth
println!("\n--- 10. Basic Auth ---");
let auth = encode_basic_auth("alice", "secret123");
println!("Basic auth header: Basic {}", auth);
// 11. JSON in URL
println!("\n--- 11. JSON URL Encoding ---");
#[derive(serde::Serialize, Deserialize, Debug)]
struct Data {
name: String,
value: i32,
}
let json_data = Data {
name: "Test".to_string(),
value: 42,
};
let json_encoded = encode_json_for_url(&json_data)?;
println!("JSON URL encoded: {}", json_encoded);
let json_decoded: Data = decode_json_from_url(&json_encoded)?;
println!("JSON decoded: {:?}", json_decoded);
// 12. Comparison
println!("\n--- 12. Base64 Comparison ---");
let encoded1 = encode_base64(b"test");
let encoded2 = encode_base64(b"test");
let encoded3 = encode_base64(b"different");
println!("encoded1 == encoded2: {}", base64_equals(&encoded1, &encoded2)?);
println!("encoded1 == encoded3: {}", base64_equals(&encoded1, &encoded3)?);
println!("\n=== All Base64 Encoding Examples Completed ===");
Ok(())
}
💻 Chiffrement Symétrique rust
🟡 intermediate
⭐⭐⭐⭐
Chiffrer et déchiffrer des données en utilisant AES en mode GCM
⏱️ 30 min
🏷️ rust, web, cryptography, encryption
Prerequisites:
Intermediate Rust, aes-gcm crate
// Web Rust Symmetric Encryption Examples
// AES encryption and decryption with GCM mode
//
// Add to Cargo.toml:
// [dependencies]
// aes-gcm = "0.10"
// rand = "0.8"
// hex = "0.4"
use aes_gcm::{
Aes256Gcm,
Key,
Nonce,
aead::{Aead, AeadCore, KeyInit, OsRng},
};
use rand::Rng;
// 1. Key Generation
/// Generate random 256-bit key for AES-256
fn generate_key() -> [u8; 32] {
Aes256Gcm::generate_key().into()
}
/// Generate key from password using PBKDF2
fn key_from_password(password: &str, salt: &[u8; 32], iterations: u32) -> [u8; 32] {
use pbkdf2::pbkdf2_hmac;
use sha2::Sha256;
let mut key_bytes = [0u8; 32];
pbkdf2_hmac::<Sha256>(
password.as_bytes(),
salt,
iterations,
&mut key_bytes,
);
key_bytes
}
// 2. Nonce Generation
/// Generate random nonce for AES-GCM
fn generate_nonce() -> [u8; 12] {
Aes256Gcm::generate_nonce().into()
}
/// Create nonce from counter (for testing)
fn nonce_from_counter(counter: u64) -> [u8; 12] {
let mut nonce = [0u8; 12];
nonce[4..].copy_from_slice(&counter.to_be_bytes());
nonce
}
// 3. AES-GCM Encryption
/// Encrypt data using AES-256-GCM
fn encrypt_aes256_gcm(
key: &[u8; 32],
nonce: &[u8; 12],
plaintext: &[u8],
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce = Nonce::from_slice(nonce);
let ciphertext = cipher.encrypt(nonce, plaintext)?;
Ok(ciphertext)
}
/// Encrypt string using AES-256-GCM
fn encrypt_string_aes256_gcm(
key: &[u8; 32],
nonce: &[u8; 12],
plaintext: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let ciphertext = encrypt_aes256_gcm(key, nonce, plaintext.as_bytes())?;
Ok(hex::encode(ciphertext))
}
// 4. AES-GCM Decryption
/// Decrypt data using AES-256-GCM
fn decrypt_aes256_gcm(
key: &[u8; 32],
nonce: &[u8; 12],
ciphertext: &[u8],
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce = Nonce::from_slice(nonce);
let plaintext = cipher.decrypt(nonce, ciphertext)?;
Ok(plaintext)
}
/// Decrypt hex-encoded string using AES-256-GCM
fn decrypt_string_aes256_gcm(
key: &[u8; 32],
nonce: &[u8; 12],
ciphertext_hex: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let ciphertext = hex::decode(ciphertext_hex)?;
let plaintext_bytes = decrypt_aes256_gcm(key, nonce, &ciphertext)?;
Ok(String::from_utf8(plaintext_bytes)?)
}
// 5. Encryption with Associated Data (AAD)
/// Encrypt with additional authenticated data
fn encrypt_with_aad(
key: &[u8; 32],
nonce: &[u8; 12],
plaintext: &[u8],
aad: &[u8],
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce = Nonce::from_slice(nonce);
let ciphertext = cipher.encrypt(nonce, plaintext)?;
Ok(ciphertext)
}
// 6. Complete Encryption Structure
/// Encrypted message with nonce
#[derive(Debug)]
struct EncryptedMessage {
nonce: [u8; 12],
ciphertext: Vec<u8>,
}
/// Encrypt and return message with nonce
fn encrypt_message(key: &[u8; 32], plaintext: &str) -> EncryptedMessage {
let nonce = generate_nonce();
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce_obj = Nonce::from_slice(&nonce);
let ciphertext = cipher.encrypt(nonce_obj, plaintext.as_bytes()).unwrap();
EncryptedMessage { nonce, ciphertext }
}
/// Decrypt message with embedded nonce
fn decrypt_message(key: &[u8; 32], message: EncryptedMessage) -> Result<String, Box<dyn std::error::Error>> {
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce = Nonce::from_slice(&message.nonce);
let plaintext = cipher.decrypt(nonce, message.ciphertext.as_slice())?;
Ok(String::from_utf8(plaintext)?)
}
// 7. File Encryption
/// Encrypt file contents
fn encrypt_file(
key: &[u8; 32],
input_path: &str,
output_path: &str,
) -> Result<(), Box<dyn std::error::Error>> {
use std::io::Read;
use std::io::Write;
// Read input file
let mut file = std::fs::File::open(input_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
// Encrypt
let nonce = generate_nonce();
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce_obj = Nonce::from_slice(&nonce);
let ciphertext = cipher.encrypt(nonce_obj, buffer.as_slice())?;
// Write nonce + ciphertext to output
let mut output = std::fs::File::create(output_path)?;
output.write_all(&nonce)?;
output.write_all(&ciphertext)?;
Ok(())
}
/// Decrypt file contents
fn decrypt_file(
key: &[u8; 32],
input_path: &str,
output_path: &str,
) -> Result<(), Box<dyn std::error::Error>> {
use std::io::Read;
use std::io::Write;
// Read input file
let mut file = std::fs::File::open(input_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
// Extract nonce (first 12 bytes)
let mut nonce = [0u8; 12];
nonce.copy_from_slice(&buffer[..12]);
let ciphertext = &buffer[12..];
// Decrypt
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce_obj = Nonce::from_slice(&nonce);
let plaintext = cipher.decrypt(nonce_obj, ciphertext)?;
// Write to output
let mut output = std::fs::File::create(output_path)?;
output.write_all(&plaintext)?;
Ok(())
}
// 8. Stream Encryption (Chunked)
/// Encrypt data in chunks
fn encrypt_chunked(
key: &[u8; 32],
data: &[u8],
chunk_size: usize,
) -> Result<Vec<(Vec<u8>, [u8; 12])>, Box<dyn std::error::Error>> {
let mut results = Vec::new();
for chunk in data.chunks(chunk_size) {
let nonce = generate_nonce();
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce_obj = Nonce::from_slice(&nonce);
let ciphertext = cipher.encrypt(nonce_obj, chunk)?;
results.push((ciphertext, nonce));
}
Ok(results)
}
// 9. Key Derivation
/// Derive encryption key from passphrase
struct EncryptionKey {
key: [u8; 32],
salt: [u8; 32],
}
impl EncryptionKey {
fn new(passphrase: &str) -> Self {
let mut salt = [0u8; 32];
let mut rng = rand::thread_rng();
rng.fill(&mut salt);
let key = key_from_password(passphrase, &salt, 100_000);
EncryptionKey { key, salt }
}
fn from_salt(passphrase: &str, salt: [u8; 32]) -> Self {
let key = key_from_password(passphrase, &salt, 100_000);
EncryptionKey { key, salt }
}
}
// 10. Password-Based Encryption
/// Encrypt with password
fn encrypt_with_password(
password: &str,
plaintext: &str,
) -> Result<(String, [u8; 32], [u8; 12]), Box<dyn std::error::Error>> {
let enc_key = EncryptionKey::new(password);
let nonce = generate_nonce();
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(&enc_key.key));
let nonce_obj = Nonce::from_slice(&nonce);
let ciphertext = cipher.encrypt(nonce_obj, plaintext.as_bytes())?;
Ok((hex::encode(ciphertext), enc_key.salt, nonce))
}
/// Decrypt with password
fn decrypt_with_password(
password: &str,
ciphertext_hex: &str,
salt: [u8; 32],
nonce: [u8; 12],
) -> Result<String, Box<dyn std::error::Error>> {
let enc_key = EncryptionKey::from_salt(password, salt);
let ciphertext = hex::decode(ciphertext_hex)?;
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(&enc_key.key));
let nonce_obj = Nonce::from_slice(&nonce);
let plaintext = cipher.decrypt(nonce_obj, ciphertext.as_slice())?;
Ok(String::from_utf8(plaintext)?)
}
// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Web Rust Symmetric Encryption Examples ===\n");
// 1. Generate key
println!("--- 1. Key Generation ---");
let key = generate_key();
println!("Generated key: {}", hex::encode(key));
// 2. Generate nonce
println!("\n--- 2. Nonce Generation ---");
let nonce = generate_nonce();
println!("Generated nonce: {}", hex::encode(nonce));
// 3. Encrypt string
println!("\n--- 3. Encrypt String ---");
let plaintext = "Secret message!";
let encrypted = encrypt_string_aes256_gcm(&key, &nonce, plaintext)?;
println!("Plaintext: {}", plaintext);
println!("Encrypted: {}", encrypted);
// 4. Decrypt string
println!("\n--- 4. Decrypt String ---");
let decrypted = decrypt_string_aes256_gcm(&key, &nonce, &encrypted)?;
println!("Decrypted: {}", decrypted);
// 5. Complete message encryption
println!("\n--- 5. Complete Message ---");
let message = encrypt_message(&key, "Hello, secure world!");
println!("Encrypted message: {:?}", message);
let decrypted_msg = decrypt_message(&key, message)?;
println!("Decrypted message: {}", decrypted_msg);
// 6. Password-based encryption
println!("\n--- 6. Password-Based Encryption ---");
let password = "my_secure_password";
let secret = "This is a secret message";
let (encrypted_pwd, salt, nonce_pwd) = encrypt_with_password(password, secret)?;
println!("Password-encrypted: {}", encrypted_pwd);
println!("Salt: {}", hex::encode(salt));
println!("Nonce: {}", hex::encode(nonce_pwd));
let decrypted_pwd = decrypt_with_password(password, &encrypted_pwd, salt, nonce_pwd)?;
println!("Decrypted: {}", decrypted_pwd);
// 7. Key from password
println!("\n--- 7. Key Derivation ---");
let user_password = "user_password_123";
let user_salt = [0u8; 32]; // In practice, generate random salt
let derived_key = key_from_password(user_password, &user_salt, 100_000);
println!("Derived key: {}", hex::encode(derived_key));
// 8. Encrypt large data
println!("\n--- 8. Large Data Encryption ---");
let large_data = "A".repeat(10000);
let large_encrypted = encrypt_string_aes256_gcm(&key, &nonce, &large_data)?;
println!("Encrypted {} bytes to {}", large_data.len(), large_encrypted.len());
// 9. Chunked encryption
println!("\n--- 9. Chunked Encryption ---");
let test_data = b"This is some test data that will be encrypted in chunks";
let chunks = encrypt_chunked(&key, test_data, 10)?;
println!("Encrypted into {} chunks", chunks.len());
// 10. Verify data integrity
println!("\n--- 10. Data Integrity ---");
let original = "Important data to protect";
let enc = encrypt_message(&key, original)?;
let dec = decrypt_message(&key, enc)?;
println!("Original matches decrypted: {}", original == dec);
println!("\n=== All Symmetric Encryption Examples Completed ===");
Ok(())
}