Skip to the content.

目次

ファイルの暗号化・圧縮の流れ

実際のソースコードはこちらから確認できます。

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を作成します。
なお、AesCngCipher 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を通してファイルの内容を変換しながらコピーします。