-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkey_wrapping_example.rs
More file actions
288 lines (233 loc) · 11.2 KB
/
Copy pathkey_wrapping_example.rs
File metadata and controls
288 lines (233 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
//! AES Key Wrap (RFC 3394) Example
//!
//! Demonstrates how to use CrabGraph's key wrapping functionality to securely
//! encrypt key material with Key Encryption Keys (KEKs).
//!
//! Run this example with:
//! ```bash
//! cargo run --example key_wrapping_example
//! ```
use crabgraph::{
kw::{Kw128, Kw192, Kw256},
CrabResult,
};
/// Demo 1: Basic Key Wrapping with AES-256
///
/// Shows the fundamental wrap/unwrap operation with a 256-bit KEK.
/// This is the recommended key size for most applications.
fn demo_basic_wrapping() -> CrabResult<()> {
println!("=== Demo 1: Basic Key Wrapping ===\n");
// Generate a random 256-bit KEK (Key Encryption Key)
let kek = Kw256::generate_kek()?;
println!("Generated 256-bit KEK: {} bytes", kek.len());
// Create wrapper instance
let wrapper = Kw256::new(&kek)?;
// Simulate a session key that needs to be stored/transmitted securely
let session_key = [0x42u8; 32]; // 256-bit AES key
println!("Session key to wrap: {:02x?}...", &session_key[..8]);
// Wrap the key (deterministic encryption + integrity protection)
let wrapped = wrapper.wrap_key(&session_key)?;
println!("Wrapped key: {} bytes", wrapped.len());
println!("Wrapped data: {:02x?}...\n", &wrapped[..16]);
// Later, unwrap to use the key
let unwrapped = wrapper.unwrap_key(&wrapped)?;
assert_eq!(unwrapped, session_key);
println!("✓ Successfully unwrapped key");
println!("✓ Integrity verified (IV check passed)\n");
Ok(())
}
/// Demo 2: HSM-Style Key Export/Import Workflow
///
/// Demonstrates a realistic scenario where keys are exported from one system
/// and imported into another using key wrapping.
fn demo_hsm_workflow() -> CrabResult<()> {
println!("=== Demo 2: HSM Key Export/Import ===\n");
// System A: Master KEK (would be stored in HSM)
let master_kek = Kw256::generate_kek()?;
let exporter = Kw256::new(&master_kek)?;
println!("System A: Master KEK initialized");
// System A: Generate and wrap a database encryption key
let db_key = [0x11u8; 32];
println!("System A: Database key generated");
let wrapped_db_key = exporter.wrap_key(&db_key)?;
println!("System A: Key wrapped for export ({} bytes)", wrapped_db_key.len());
println!("System A: Wrapped data: {:02x?}...", &wrapped_db_key[..16]);
// Transmit wrapped_db_key over insecure channel...
println!("\n[Transmitting wrapped key over network...]");
// System B: Import the key using shared KEK
let importer = Kw256::new(&master_kek)?;
println!("\nSystem B: Master KEK configured");
let imported_key = importer.unwrap_key(&wrapped_db_key)?;
println!("System B: Key imported successfully");
// Verify integrity
assert_eq!(imported_key, db_key);
println!("✓ Key matches original");
println!("✓ No tampering detected\n");
Ok(())
}
/// Demo 3: Multiple Key Sizes
///
/// Shows usage of different KEK sizes (128, 192, 256 bits).
/// AES-256 is recommended, but other sizes are available for compatibility.
fn demo_multiple_sizes() -> CrabResult<()> {
println!("=== Demo 3: Multiple Key Sizes ===\n");
let test_key = [0x33u8; 24]; // 192-bit key to wrap
// AES-128 Key Wrap
let kek128 = Kw128::generate_kek()?;
let wrapper128 = Kw128::new(&kek128)?;
let wrapped128 = wrapper128.wrap_key(&test_key)?;
println!("Kw128: Wrapped {} bytes → {} bytes", test_key.len(), wrapped128.len());
// AES-192 Key Wrap
let kek192 = Kw192::generate_kek()?;
let wrapper192 = Kw192::new(&kek192)?;
let wrapped192 = wrapper192.wrap_key(&test_key)?;
println!("Kw192: Wrapped {} bytes → {} bytes", test_key.len(), wrapped192.len());
// AES-256 Key Wrap (Recommended)
let kek256 = Kw256::generate_kek()?;
let wrapper256 = Kw256::new(&kek256)?;
let wrapped256 = wrapper256.wrap_key(&test_key)?;
println!("Kw256: Wrapped {} bytes → {} bytes (RECOMMENDED)", test_key.len(), wrapped256.len());
// Verify all unwrap correctly
assert_eq!(wrapper128.unwrap_key(&wrapped128)?, test_key);
assert_eq!(wrapper192.unwrap_key(&wrapped192)?, test_key);
assert_eq!(wrapper256.unwrap_key(&wrapped256)?, test_key);
println!("\n✓ All sizes work correctly");
println!("✓ Use Kw256 for maximum security\n");
Ok(())
}
/// Demo 4: Error Handling
///
/// Shows how key wrapping detects tampering, wrong KEKs, and invalid inputs.
fn demo_error_handling() -> CrabResult<()> {
println!("=== Demo 4: Error Handling ===\n");
let kek = Kw256::generate_kek()?;
let wrapper = Kw256::new(&kek)?;
let key = [0x55u8; 32];
let wrapped = wrapper.wrap_key(&key)?;
// Test 1: Wrong KEK detection
println!("Test 1: Wrong KEK detection");
let wrong_kek = Kw256::generate_kek()?;
let wrong_wrapper = Kw256::new(&wrong_kek)?;
match wrong_wrapper.unwrap_key(&wrapped) {
Ok(_) => println!(" ✗ Should have failed!"),
Err(e) => println!(" ✓ Correctly detected wrong KEK: {}", e),
}
// Test 2: Tampered data detection
println!("\nTest 2: Tampered data detection");
let mut tampered = wrapped.clone();
tampered[5] ^= 0xFF; // Flip bits
match wrapper.unwrap_key(&tampered) {
Ok(_) => println!(" ✗ Should have detected tampering!"),
Err(e) => println!(" ✓ Correctly detected tampering: {}", e),
}
// Test 3: Invalid input lengths
println!("\nTest 3: Invalid input lengths");
// Key too small
let tiny_key = [0u8; 8];
match wrapper.wrap_key(&tiny_key) {
Ok(_) => println!(" ✗ Should reject small key!"),
Err(e) => println!(" ✓ Rejected key < 16 bytes: {}", e),
}
// Key not multiple of 8
let odd_key = [0u8; 19];
match wrapper.wrap_key(&odd_key) {
Ok(_) => println!(" ✗ Should reject non-8-byte-multiple!"),
Err(e) => println!(" ✓ Rejected non-aligned key: {}", e),
}
// Wrong KEK size
println!("\nTest 4: Invalid KEK size");
let bad_kek = [0u8; 31]; // Should be 32
match Kw256::new(&bad_kek) {
Ok(_) => println!(" ✗ Should reject wrong KEK size!"),
Err(e) => println!(" ✓ Rejected invalid KEK: {}", e),
}
println!("\n✓ All error cases handled correctly\n");
Ok(())
}
/// Demo 5: Deterministic Encryption Property
///
/// Shows that key wrapping is deterministic (same input = same output).
/// This is by design for key wrapping but differs from AEAD ciphers.
fn demo_deterministic() -> CrabResult<()> {
println!("=== Demo 5: Deterministic Encryption ===\n");
let kek = Kw256::generate_kek()?;
let wrapper = Kw256::new(&kek)?;
let key = [0x77u8; 32];
// Wrap the same key twice
let wrapped1 = wrapper.wrap_key(&key)?;
let wrapped2 = wrapper.wrap_key(&key)?;
println!("Wrapped #1: {:02x?}...", &wrapped1[..16]);
println!("Wrapped #2: {:02x?}...", &wrapped2[..16]);
if wrapped1 == wrapped2 {
println!("\n✓ Deterministic: Same input → Same output");
println!(" This is EXPECTED for key wrapping");
println!(" (Unlike AEAD which uses random nonces)");
} else {
println!("\n✗ Unexpected: Outputs differ!");
}
println!("\n⚠️ Security Note:");
println!(" Key wrapping is deterministic by design (RFC 3394)");
println!(" Only use for wrapping key material, not arbitrary data");
println!(" For general encryption, use AEAD ciphers (AES-GCM, ChaCha20-Poly1305)\n");
Ok(())
}
/// Demo 6: Practical Key Storage
///
/// Shows how to use key wrapping for secure key storage at rest.
fn demo_key_storage() -> CrabResult<()> {
println!("=== Demo 6: Practical Key Storage ===\n");
// Master KEK (would be derived from user password or stored in HSM)
let master_kek = Kw256::generate_kek()?;
let wrapper = Kw256::new(&master_kek)?;
println!("Master KEK initialized (32 bytes)");
// Application generates multiple keys for different purposes
let encryption_key = [0xAAu8; 32];
let signing_key = [0xBBu8; 32];
let backup_key = [0xCCu8; 32];
// Wrap all keys with the master KEK
let wrapped_encryption = wrapper.wrap_key(&encryption_key)?;
let wrapped_signing = wrapper.wrap_key(&signing_key)?;
let wrapped_backup = wrapper.wrap_key(&backup_key)?;
println!("Wrapped encryption key: {} bytes", wrapped_encryption.len());
println!("Wrapped signing key: {} bytes", wrapped_signing.len());
println!("Wrapped backup key: {} bytes", wrapped_backup.len());
// Store wrapped keys in database/config file
println!("\n[Storing wrapped keys in database...]");
println!(" - Only wrapped forms are stored");
println!(" - Master KEK is never stored with wrapped keys");
println!(" - Master KEK may be derived from password or in HSM");
// Later, load and unwrap when needed
println!("\n[Loading wrapped keys from storage...]");
let loaded_encryption = wrapper.unwrap_key(&wrapped_encryption)?;
let loaded_signing = wrapper.unwrap_key(&wrapped_signing)?;
let loaded_backup = wrapper.unwrap_key(&wrapped_backup)?;
assert_eq!(loaded_encryption, encryption_key);
assert_eq!(loaded_signing, signing_key);
assert_eq!(loaded_backup, backup_key);
println!("✓ All keys loaded successfully");
println!("✓ Integrity verified for all keys");
println!("\n✓ Ready to use unwrapped keys for operations\n");
Ok(())
}
fn main() -> CrabResult<()> {
println!("\n╔══════════════════════════════════════════════════════════════╗");
println!("║ CrabGraph AES Key Wrap (RFC 3394) Examples ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
demo_basic_wrapping()?;
demo_hsm_workflow()?;
demo_multiple_sizes()?;
demo_error_handling()?;
demo_deterministic()?;
demo_key_storage()?;
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ Key Takeaways ║");
println!("╠══════════════════════════════════════════════════════════════╣");
println!("║ • Use Kw256 (32-byte KEK) for maximum security ║");
println!("║ • Key wrapping is deterministic (by design) ║");
println!("║ • Built-in integrity protection detects tampering ║");
println!("║ • Only for keys - use AEAD for general data ║");
println!("║ • RFC 3394 compliant implementation ║");
println!("║ • Automatic validation of sizes and alignment ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
Ok(())
}