use peat_btle::observer::{PeatEvent, PeatObserver, SecurityViolationKind};
use peat_btle::{NodeId, PeatMesh, PeatMeshConfig};
use std::sync::Arc;
struct SecurityObserver {
name: &'static str,
}
impl SecurityObserver {
fn new(name: &'static str) -> Self {
Self { name }
}
}
impl PeatObserver for SecurityObserver {
fn on_event(&self, event: PeatEvent) {
match event {
PeatEvent::EmergencyReceived { from_node } => {
println!(
"[{}] Received EMERGENCY from {:08X}",
self.name,
from_node.as_u32()
);
}
PeatEvent::SecurityViolation { kind, source } => {
let kind_str = match kind {
SecurityViolationKind::DecryptionFailed => "Decryption failed (wrong key?)",
SecurityViolationKind::UnencryptedInStrictMode => "Unencrypted in strict mode",
SecurityViolationKind::ReplayDetected => "Replay attack detected",
SecurityViolationKind::UnauthorizedNode => "Unauthorized node",
};
println!(
"[{}] SECURITY VIOLATION: {} (source: {:?})",
self.name, kind_str, source
);
}
PeatEvent::DocumentSynced { from_node, .. } => {
println!(
"[{}] Successfully synced with {:08X}",
self.name,
from_node.as_u32()
);
}
_ => {}
}
}
}
fn main() {
println!("=== PEAT-BTLE Mesh-Wide Encryption Example ===\n");
let mesh_secret: [u8; 32] = [
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
0x1f, 0x20,
];
let wrong_secret: [u8; 32] = [0xFFu8; 32];
println!("--- Creating Encrypted Mesh Nodes ---");
let config_alpha = PeatMeshConfig::new(NodeId::new(0x11111111), "ALPHA-1", "SECURE")
.with_encryption(mesh_secret);
let config_bravo = PeatMeshConfig::new(NodeId::new(0x22222222), "BRAVO-1", "SECURE")
.with_encryption(mesh_secret);
let mesh_alpha = PeatMesh::new(config_alpha);
let mesh_bravo = PeatMesh::new(config_bravo);
mesh_alpha.add_observer(Arc::new(SecurityObserver::new("ALPHA")));
mesh_bravo.add_observer(Arc::new(SecurityObserver::new("BRAVO")));
println!(
"Alpha encryption enabled: {}",
mesh_alpha.is_encryption_enabled()
);
println!(
"Bravo encryption enabled: {}",
mesh_bravo.is_encryption_enabled()
);
println!();
let config_eve = PeatMeshConfig::new(NodeId::new(0xEEEEEEEE), "EVE-1", "SECURE")
.with_encryption(wrong_secret);
let mesh_eve = PeatMesh::new(config_eve);
mesh_eve.add_observer(Arc::new(SecurityObserver::new("EVE")));
let config_plain = PeatMeshConfig::new(NodeId::new(0xAAAAAAAA), "PLAIN-1", "SECURE");
let mesh_plain = PeatMesh::new(config_plain);
mesh_plain.add_observer(Arc::new(SecurityObserver::new("PLAIN")));
println!("--- Scenario 1: Encrypted Communication ---");
let now_ms = 1000u64;
let encrypted_doc = mesh_alpha.send_emergency(now_ms);
println!(
"Alpha sent encrypted document: {} bytes",
encrypted_doc.len()
);
println!("First byte (marker): 0x{:02X}", encrypted_doc[0]);
let result = mesh_bravo.on_ble_data_received_from_node(
NodeId::new(0x11111111),
&encrypted_doc,
now_ms + 100,
);
println!("Bravo can decrypt: {}", result.is_some());
println!();
println!("--- Scenario 2: Wrong Key Rejection ---");
let result = mesh_eve.on_ble_data_received_from_node(
NodeId::new(0x11111111),
&encrypted_doc,
now_ms + 200,
);
println!("Eve can decrypt: {}", result.is_some());
println!();
println!("--- Scenario 3: Unencrypted Node ---");
let plain_doc = mesh_plain.build_document();
println!("Plain node document: {} bytes", plain_doc.len());
println!("First byte: 0x{:02X} (not encrypted marker)", plain_doc[0]);
let result = mesh_bravo.on_ble_data_received_from_node(
NodeId::new(0xAAAAAAAA),
&plain_doc,
now_ms + 300,
);
println!(
"Bravo (non-strict) accepts unencrypted: {}",
result.is_some()
);
println!();
println!("--- Scenario 4: Strict Encryption Mode ---");
let config_strict = PeatMeshConfig::new(NodeId::new(0x33333333), "STRICT-1", "SECURE")
.with_encryption(mesh_secret)
.with_strict_encryption();
let mesh_strict = PeatMesh::new(config_strict);
mesh_strict.add_observer(Arc::new(SecurityObserver::new("STRICT")));
println!(
"Strict mode enabled: {}",
mesh_strict.is_strict_encryption_enabled()
);
let result = mesh_strict.on_ble_data_received_from_node(
NodeId::new(0xAAAAAAAA),
&plain_doc,
now_ms + 400,
);
println!("Strict node accepts unencrypted: {}", result.is_some());
println!();
println!("--- Encryption Overhead ---");
let mesh_alpha_unencrypted = PeatMesh::new(PeatMeshConfig::new(
NodeId::new(0x11111111),
"ALPHA-1",
"SECURE",
));
mesh_alpha_unencrypted.send_emergency(now_ms + 500); let unencrypted_doc = mesh_alpha_unencrypted.build_document();
let encrypted_doc_sample = mesh_alpha.build_document();
let overhead = encrypted_doc_sample.len() - unencrypted_doc.len();
println!("Same content unencrypted: {} bytes", unencrypted_doc.len());
println!(
"Same content encrypted: {} bytes",
encrypted_doc_sample.len()
);
println!("Encryption overhead: {} bytes", overhead);
println!(" (2 bytes marker + 12 bytes nonce + 16 bytes auth tag = 30 bytes)");
println!("\n=== Example Complete ===");
}