1mod error;
10mod crypto;
11mod protocol;
12mod shuffle;
13mod config;
14mod replay;
15
16pub use error::{A2FError, A2FResult};
17pub use crypto::{SimpleCrypto, KeyExchange};
18pub use protocol::{Packet, PayloadType, TimestampBuffer};
19pub use shuffle::ShuffleScheduler;
20pub use config::A2FConfig;
21pub use replay::SlidingWindow;
22
23use std::time::{SystemTime, UNIX_EPOCH};
24use std::collections::HashMap;
25use std::sync::atomic::{AtomicU64, Ordering};
26
27pub fn current_timestamp() -> u64 {
29 SystemTime::now()
30 .duration_since(UNIX_EPOCH)
31 .unwrap()
32 .as_millis() as u64
33}
34
35static GLOBAL_SEQ: AtomicU64 = AtomicU64::new(1);
36
37pub fn next_sequence() -> u64 {
38 GLOBAL_SEQ.fetch_add(1, Ordering::SeqCst)
39}
40
41pub struct A2FELSender {
42 crypto: SimpleCrypto,
43 key_exchange: KeyExchange,
44 shuffler: ShuffleScheduler,
45 session_key: Option<[u8; 32]>,
46 peer_public_key: Option<[u8; 32]>,
47 next_seq: u64,
48}
49
50impl A2FELSender {
51 pub fn new() -> Self {
52 Self {
53 crypto: SimpleCrypto::new(),
54 key_exchange: KeyExchange::new(),
55 shuffler: ShuffleScheduler::new(),
56 session_key: None,
57 peer_public_key: None,
58 next_seq: next_sequence(),
59 }
60 }
61
62 pub fn start_key_exchange(&mut self) -> [u8; 32] {
63 self.key_exchange.generate_keypair()
64 }
65
66 pub fn complete_key_exchange(&mut self, peer_public: &[u8; 32]) -> A2FResult<()> {
67 let shared = self.key_exchange.compute_shared_secret(peer_public)?;
68 let session_key = self.derive_session_key(&shared);
69 self.session_key = Some(session_key);
70 self.crypto.set_key(session_key);
71 self.peer_public_key = Some(*peer_public);
72 Ok(())
73 }
74
75 fn derive_session_key(&self, shared: &[u8; 32]) -> [u8; 32] {
76 use sha2::Sha256;
77 use hkdf::Hkdf;
78
79 let hkdf = Hkdf::<Sha256>::new(None, shared);
80 let mut okm = [0u8; 32];
81 hkdf.expand(b"a2f-el-session", &mut okm).unwrap();
82 okm
83 }
84
85 pub fn encrypt_data(&mut self, data: &[u8], timestamp: u64) -> A2FResult<Packet> {
86 if self.session_key.is_none() {
87 return Err(A2FError::ConfigError("鍵交換が完了していません".into()));
88 }
89
90 let encrypted = self.crypto.encrypt(data)?;
91 let seq = self.next_seq;
92 self.next_seq += 1;
93
94 Ok(Packet::new(seq, timestamp, PayloadType::EncryptedData, encrypted))
95 }
96
97 pub fn make_key_packet(&mut self, timestamp: u64) -> A2FResult<Packet> {
98 let public_key = self.start_key_exchange();
99 let seq = self.next_seq;
100 self.next_seq += 1;
101
102 Ok(Packet::new(seq, timestamp, PayloadType::WrappedKey, public_key.to_vec()))
103 }
104
105 pub fn send_multiple(&mut self, chunks: &[&[u8]]) -> A2FResult<Vec<Packet>> {
106 if chunks.is_empty() {
107 return Ok(vec![]);
108 }
109
110 let ts = current_timestamp();
111 let mut packets = Vec::new();
112
113 for (i, chunk) in chunks.iter().enumerate() {
114 let chunk_ts = ts + i as u64;
115 let data_packet = self.encrypt_data(chunk, chunk_ts)?;
116 packets.push(data_packet);
117 }
118
119 packets = self.shuffler.shuffle_packets(packets);
120 Ok(packets)
121 }
122
123 pub fn shuffle_packets<T>(&mut self, packets: Vec<T>) -> Vec<T> {
124 self.shuffler.shuffle_packets(packets)
125 }
126}
127
128impl Default for A2FELSender {
129 fn default() -> Self {
130 Self::new()
131 }
132}
133
134pub struct A2FELReceiver {
135 crypto: SimpleCrypto,
136 key_exchange: KeyExchange,
137 buffer: TimestampBuffer,
138 pending_keys: HashMap<u64, [u8; 32]>,
139 sliding_window: SlidingWindow,
140 session_key: Option<[u8; 32]>,
141 peer_public_key: Option<[u8; 32]>,
142}
143
144impl A2FELReceiver {
145 pub fn new(config: &A2FConfig) -> Self {
146 Self {
147 crypto: SimpleCrypto::new(),
148 key_exchange: KeyExchange::new(),
149 buffer: TimestampBuffer::new(config.buffer_timeout_secs, config.buffer_max_size),
150 pending_keys: HashMap::new(),
151 sliding_window: SlidingWindow::new(config.replay_window_size),
152 session_key: None,
153 peer_public_key: None,
154 }
155 }
156
157 pub fn get_public_key(&mut self) -> [u8; 32] {
158 self.key_exchange.generate_keypair()
159 }
160
161 pub fn complete_key_exchange(&mut self, peer_public: &[u8; 32]) -> A2FResult<()> {
162 let shared = self.key_exchange.compute_shared_secret(peer_public)?;
163 let session_key = self.derive_session_key(&shared);
164 self.session_key = Some(session_key);
165 self.crypto.set_key(session_key);
166 self.peer_public_key = Some(*peer_public);
167 Ok(())
168 }
169
170 fn derive_session_key(&self, shared: &[u8; 32]) -> [u8; 32] {
171 use sha2::Sha256;
172 use hkdf::Hkdf;
173
174 let hkdf = Hkdf::<Sha256>::new(None, shared);
175 let mut okm = [0u8; 32];
176 hkdf.expand(b"a2f-el-session", &mut okm).unwrap();
177 okm
178 }
179
180 pub fn receive_packet(&mut self, packet: Packet) -> A2FResult<Option<Vec<u8>>> {
181 if !self.sliding_window.check_and_record(packet.seq) {
182 return Err(A2FError::ExpiredSequence(packet.seq));
183 }
184
185 match packet.payload_type {
186 PayloadType::WrappedKey => {
187 if packet.payload.len() != 32 {
188 return Err(A2FError::DecryptionError("公開鍵の長さが不正".into()));
189 }
190 let mut peer_public = [0u8; 32];
191 peer_public.copy_from_slice(&packet.payload);
192 self.complete_key_exchange(&peer_public)?;
193 Ok(None)
194 }
195 PayloadType::EncryptedData => {
196 if self.session_key.is_none() {
197 return Err(A2FError::ConfigError("鍵交換が完了していません".into()));
198 }
199 let decrypted = self.crypto.decrypt(&packet.payload)?;
200 Ok(Some(decrypted))
201 }
202 }
203 }
204
205 pub fn pending_count(&self) -> usize {
206 self.buffer.pending_count()
207 }
208
209 pub fn clear_expired(&mut self) -> usize {
210 self.buffer.clear_expired()
211 }
212}