ブログネタは腐るほど有りますが,めんどくさくて書いてませんでした.
2月くらいから作ってましたが,一時期放置して,またこの休みに完成させました.
mipsparc / SimpleTrans — Bitbucket
今回作ったのは,8文字の受信側のマシンに表示されたコードを入力するだけで,探索・分割・圧縮・暗号化・転送を自動で行うものです.IPアドレスの入力は不要です.
隣のコンピュータにデータを移すときにUSBメモリを取り出すのが面倒で,せっかくネットワークにつながってるのに馬鹿らしいので,そういう用途を想定して作りました.気が向いたらGUIもつけます.当分気は向かないと思います.
データの転送にはSimpleHTTPServerのdo_GET()をいろいろ変えたものを利用しています.偽のIPアドレスでアクセスすれば暗号化されたファイルは取得できますが,復号化はできないのでいいと思いました.どうせSocketでやっても通信内容は見れるし.あと一度しかダウンロードできないのでいろいろエラー出ると思います.
外部モジュールとして,Diffie-Hellman.pyというどこかの方が書かれたものを私がPython3で動くようにしたDiffie-Hellman3.pyを,別途Gistから落として同じディレクトリに放り込む必要が有ります.そのライブラリがGPLなので,The MIT Licenseなこのコード的に同梱できないので,こういう形になりました.
すごく適当な計測で,1Gbpsネットワークでメイン機→ノートが300Mbpsくらい出ました.復号化とかに時間が取られてます.純粋な転送は…測ってないのでわかりません
だいたいの動作
起動するときのオプションで送信側と受信側を選択します.めんどくさいので送信側だけ書きますけど,まあ雰囲気は伝わるでしょう.受信側は今のところは並列化しないで順番に落としてますけど,並列化してもあんまり高速化する気はしないのでたぶんしません
送信側
- 受信側に表示されたランダムキーを入力する.同じコードを信頼できない他人が見られるときは,オプションで両方に事前共有鍵を入力できる
- ハードコートされたSALTと混ぜながら10000回SHA-256でハッシュする
- それをもう一度ハッシュしてdiffie_key,2の先頭16進6文字(3bytes)をsearch_idにする.そこからtmp_filenameを作る
- 8095ポート宛にsearch_idをUDP broadcastで飛ばして,TCP8095でlisten,タイムアウトするのを繰り返す
- 返答が帰ってきたらsearch_idが同じことを確認
- Diffie-Hellman鍵交換をTCP8095で実行.通信内容はAES256でdiffie-keyで暗号化.これでencryptkeyを生成する
- グローバルメタデータ(ファイル名,ファイルサイズ,セグメント数,圧縮方式など)(JSON)を生成してAES256で暗号化
- データキューとメタデータキューを作る
- 圧縮・暗号化をセグメント単位で行うプロセスsegprocessを作成
- HTTPサーバプロセスを立ち上げる
- 共有メモリの送信済み数が全体セグメント数以上なら終了
segprocess
- ファイルを開いてseg_size(100MiBがハードコート)を読み込む
- キューのサイズが既定値max_seg(デフォルト3(300MiB))を超えていないことを確認.それ以上になっていたら待機
- SHA-256ハッシュをとる
- 既定の圧縮方式で圧縮(デフォルトは無効.JPEGなどのすでに圧縮されたファイルの転送が多い気がするから.選択肢はzlib(gzip),bz2)
- AES256でencryptkeyで暗号化
- メタデータ(今のところハッシュ値だけ)を作成してAES256で暗号化
- キューに突っ込む
- 暗号化されたデータをキューに突っ込む
HTTPサーバ
- 接続元IPアドレスが鍵交換したIPアドレスと同一を確認
- ヘッダ送出
- 接続先URIのリソースを見て,’-‘で分割して前半がtmp_filenameであることを確認.その末尾に_dataとついていたらメタデータ要求
- 後半の番号を確認して(今のところはキューに突っ込まれた順番に出す実装になってるけど,まあ特に問題はなさそうな気も…),キューから取り出してデータ/メタデータ送出.キューが空ならこのまま待機.受信側のurllibにはデフォルトでタイムアウトがないのでこれでいける.
- 共有メモリの送信済み数を追加