Skip to main content

a2f_el/
lib.rs

1//! # A2F-EL (Essential Lite) - Analysis to Fake Protocol Essential Lite
2//!
3//! 必要不可欠な要素に厳選した、軽量で実用的な暗号プロトコル
4//! - ChaCha20-Poly1305 単層暗号化
5//! - X25519鍵交換(内蔵)
6//! - スライディングウィンドウによるリプレイ対策
7//! - 非同期・順不同・高遅延耐性
8
9mod 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
27/// 現在のタイムスタンプをミリ秒単位で取得
28pub 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}