libsodiumでファイル暗号化を試してみました。
Introduction
何故ファイル暗号化に libsodium が必要なのかというと
- C++で使いたい
- OpenSSLはビルドが面倒
- ライセンスが緩い
という3点です。
そんなlibsodiumはこちら
Networking and Cryptography library (NaCL) の構成コンポーネントのフォークです。
- クロスプラットフォーム
- ISCライセンス
- 2条項BSDライセンスと同等
- 開発が活発
- PHP 7.2から暗号化のコアとして採用
という特徴があります。
そんなlibsodiumを使って暗号化処理を試してみました。
How to do?
ソースは下記です。
公式提供のサンプルコードをベースにしているのですが、
- C++化
- iostreamを使っているためfopenとか除去
- 引数チェックなど追加
- libsodiumをCMakeから利用
- libsodiumは静的リンク
と改良してあります。
暗号方式は、ChaCha20-Poly1305 になります。
詳細はググっていただければと思いますが
- Googleが推奨
- TLS 1.3で提案されている
- RFC7539として標準化済み
- ローパフォーマンスなマシンで高速に動作
- ハードウェアで高速化できるAESとは違いCPUのSIMDを効率的に使えるため、モバイルでも高速
- 参考 Adiantum : 低廉な端末でも効率的に使える暗号化技術
とモダンな感じがするアルゴリズムです。
そして、libsodiumにはChaCha20-Poly1305の実装として下記が提供されています。
- ChaCha20-Poly1305 (オリジナル実装)
- IETF ChaCha20-Poly1305
- XChaCha20-Poly1305 (今回使ったのはこれ)
実装の際は、Nonceの長さやメッセージの最大長が違ったりするといった感じに見えます。
(今回使った)XChaCha20-Poly1305での暗号/復号化に必要なのはKEYのみ。
どうも、Nonceは暗号化ファイルのヘッダーに埋め込まれる感じに見えます。
ただ、ヘッダー自体がKEYを使って生成されているので、Nonceが生で入っているような感じでは無いです (未確認)
1 | typedef struct crypto_secretstream_xchacha20poly1305_state { |
1 | static int encrypt(std::string & target_file, std::string & source_file, |
ヘッダーにnonceフィールドがあるのできっとそうなのでしょう。
また、暗号化は
- ヘッダー挿入
- チャンクサイズ(4096)毎に暗号化
するだけです。
復号化も
- ヘッダー解析
- チャンクサイズ(4096)毎に復号化
というシンプルさなのも実装が容易で好ましいです。
Source Code
https://github.com/takuya-takeuchi/Demo/tree/master/Security/Cryptography/libsodium/libsodium1