A2F: 高遅延・不安定ネットワークでも動く新しい暗号プロトコルを作った
はじめに
「Starlinkみたいな衛星インターネット、速いけど通信が不安定でイライラする...」
「災害時、LINEの既読すらつかない...」
「コミケの会場、全然通信できない...」
「格安SIM、速度制限で実質使い物にならない...」
これらの問題の原因は、TCPの特性にあります。パケットロスを「混雑」と誤認識して速度を落としたり、順序が入れ替わると再送要求を出したり。高遅延・不安定なネットワークでは、TCPは本領を発揮できません。
そこで作りました。
A2F (Analysis to Fake Protocol) です。
A2Fとは
A2Fは、タイムスタンプを使って鍵とデータを結合するという発想の暗号プロトコルです。
特徴はたった1つ:
「順序は関係ない。タイムスタンプだけが全てを結びつける。」
従来のプロトコルとの違い
| 特徴 | TCP+TLS | A2F |
|---|---|---|
| 順序 | 保証する | 保証しない(シャッフル可) |
| 鍵とデータの到着順 | 鍵が先 | どっちが先でもOK |
| パケットロス | 再送 | 諦める or 再送はRaknetに任せる |
| 高遅延 | タイムアウト | 遅延は許容 |
| トラフィック解析 | 可能 | ダミー+シャッフルで困難 |
どうやって動くのか
基本アイデア
送信側:
- セッション鍵K_tを生成(tはタイムスタンプ)
- K_tをAES-256 + ChaCha20-Poly1305で多重ラップ
- データをK_tで暗号化
- 両方にタイムスタンプtを付ける
- 順序をシャッフルして送信
ネットワーク:
- 順序バラバラで届く
- パケットロスする
- 遅延する
受信側:
- タイムスタンプtでバッファリング
- K_tとデータが揃ったら復号
- 古いものはタイムアウト
鍵の多重ラップ
セッション鍵をAES-256で暗号化し、さらにChaCha20-Poly1305で暗号化します。2つの異なる暗号を重ねることで、万一どちらかに弱点が見つかっても、もう片方が守ります。
実装(Rust)
A2FはRustで実装されています。Cargo.tomlに以下を追加します。
[dependencies]
a2f = { git = "https://github.com/kcjsa/a2f" }
使用例
use a2f::{A2FConfig, A2FSender, A2FReceiver, current_timestamp};
fn main() -> anyhow::Result<()> {
let master_key = [0x42; 32];
let config = A2FConfig::default();
let mut sender = A2FSender::new(master_key, &config);
let mut receiver = A2FReceiver::new(master_key, &config);
let ts = current_timestamp();
let key_packet = sender.generate_key_packet(ts)?;
let data_packet = sender.encrypt_data(b"Hello, A2F!", ts)?;
let packets = sender.shuffle_packets(vec![key_packet, data_packet]);
for packet in packets {
if let Some(decrypted) = receiver.receive_packet(packet)? {
println!("Decrypted: {}", String::from_utf8_lossy(&decrypted));
}
}
Ok(())
}
たったこれだけ。順序バラバラでも、データが先でも、ちゃんと復号できます。
実験結果
- 実験1(順序シャッフル): 鍵とデータをランダム順で送信。どちらが先でも復号成功。
- 実験2(データが先): データだけ先に届いてもバッファリングされ、後から鍵が届くと復号成功。
- 実験3(複数メッセージ混在): 5メッセージ10パケットをランダム順で送信。全て復号成功。
- 実験4(ダミーパケット + パケットロス): ダミー30個混ぜ、30%ロス。鍵とデータ両方届けば復号成功。
- 実験5(UDP通信): 実際のUDPソケットで通信。全て復号成功。
使い道
Starlink / 衛星通信: 遅延変動やハンドオーバーでTCPが苦手。A2FはUDPベースで順序も気にしない。
災害時通信: 回線が混雑・不安定でも、「不完全でも届く」が「全く届かない」より価値がある。
コミケ: 数万人が集まる輻輳地獄。TCPはほぼ死ぬが、A2Fならとりあえず届く。
速度制限されたモバイル回線: TCPはパケットロスを混雑と誤認してさらに減速。A2Fは制限いっぱいまで使える。
拠点間VPN: A2F + Raknet + UDPの上にVPNを乗せれば、不安定な回線でも安定した通信が可能。
さらに強力な組み合わせ
A2Fは単体でも強いですが、他の技術と組み合わせるとさらに化けます。
アプリ(SSH/HTTP/ゲームなど)
↑
VPN(トンネリング)
↑
A2F(暗号化 + タイムスタンプ)
↑
Raknet(再送 + 匿名)
↑
UDP
- VPN: どんなプロトコルも包める。TCPも動く。
- A2F: 中身を二重暗号化。順序バラバラでも平気。
- Raknet: パケットロスを再送でカバー。匿名性も。
この積み重ねで、「どんなネットワークでも、どんなアプリでも、安全に動く」を実現できます。
トレードオフ
良いところ:
- 高遅延・不安定に強い
- 順序バラバラOK
- 実装がシンプル
- トラフィック解析耐性
悪いところ:
- 事前共有鍵が必要
- 公開鍵認証はなし(別途実装可)
- 標準プロトコルではない
- オーバーヘッドがある
公開鍵暗号がないのは欠点ではなくトレードオフです。閉鎖環境や事前共有が可能な環境では、ハンドシェイクがない分、高速で安定します。
まとめ
A2Fは、「TCPが苦手な環境でも暗号通信を諦めない」ためのプロトコルです。
- 順序バラバラでも動く
- データが先でも動く
- パケットロスに強い
- 高遅延に強い
- ダミーパケットで解析困難
- 多重暗号化(AES + ChaCha20)
- Rustで実装、クロスプラットフォーム
Qiitaでこの記事を読んだあなた。もし「高遅延・不安定ネットワーク」に悩んだことがあるなら、ぜひA2Fを試してみてください。
GitHub: https://github.com/kcjsa/a2f
crates.io: cargo add a2f
A2F - Analysis to Fake Protocol
Send in chaos. Receive in order. Timestamps bind everything.