目次
ファイルの暗号化・圧縮の流れ
実際のソースコードはこちらから確認できます。
1.ソルトの作成
RNGCryptoServiceProvider(.NET 6では非推奨になったので対応予定)を利用して暗号強度の高いランダム値を作成し、ソルトとします。
Salt = GenerateSalt(8);
2.暗号化キーと初期化ベクトルの生成
ユーザが入力したパスワードと、1.で生成したソルトをもとに、Rfc2898DeriveBytesを利用して暗号化キーと初期化ベクトルを生成します。
現在はOpenSSLのデフォルト値と合わせるため、繰り返し回数は10000、ハッシュアルゴリズムはSHA256に固定しています。
(key, Iv) = GetKeyAndIV(GenerateKIV(Salt, password, HashAlgorithm, 10000, keySize / 8 + blockSize));
なお、このクラスではRFC 2898で定義されたPBKDF2のアルゴリズムを使用しています。
これは、オープンソースのパスワードマネージャとして有名なBitwardenでも使われている(参照)、一般的かつ強力なアルゴリズムです。
3.ソルトの書き込み
暗号化ファイルの先頭にプレフィックスSalted__
とソルトを書き込みます。
プレフィックスを書き込んでいるのはOpenSSLのものと合わせるためです。
output.Write(Encoding.UTF8.GetBytes(prefix));
output.Write(Salt);
4.ICryptoTransform・CryptoStreamの作成
暗号化キーと初期化ベクトルを使用してAesCngから対称AES暗号化オブジェクト(ICryptoTransform)を作成し、それをもとにCryptoStreamを作成します。
なお、AesCngはCipher Block Chaining (CBC)モードで予め生成しています。
ICryptoTransform cryptoTransform = aes.CreateEncryptor(key, Iv);
using var cryptoStream = new CryptoStream(output, cryptoTransform, CryptoStreamMode.Write);
5.DeflateStream/GZipStreamの作成
圧縮するように設定されている場合、この時点で圧縮用のDeflateStream又はGZipStreamを作成します。
using var deflateStream = new DeflateStream(cryptoStream, CompressionLevel);
6.コピー
作成したStreamを通してファイルの内容を変換しながらコピーします。