C#: AES-256を使った暗号化・復号化サンプル

概要

AES-256の概要

暗号化・復号化サンプル

  • ここでは「ストリームを使ったサンプル」(CryptoStreamクラスを使用)と、「バイト列を使ったサンプル」(TransformFinalBlockを使用)のサンプルを紹介します。基本的には、少ないメモリ使用量で大きなファイルを暗号化・復号化できるストリームを使った方法をお薦めします。
  • RFC2828の考えに沿って、暗号化処理の入力となる平文をcleartext、暗号化処理の出力となる暗号文をciphertextと表記します。平文・暗号文はバイナリデータを意味しており、文字列(文章)の他に画像や音声などを暗号化する場合にも使用されます。
  • 完全なソースコードはこちらで公開しています。

ストリームを使ったサンプル

  • 暗号化・復号化のメイン処理のサンプルです。
    • AES関連の操作は、AesクラスやAesクラスから取得したEncryptor/Decryptor(ICryptoTransform)等のオブジェクトで実現できます。
    • キーやIVは独自に生成も可能ですが、AesのGenerateKey(), GenerateIV()で簡単に生成できます。
  • 前述のメイン処理から呼び出している暗号化・復号化処理メソッドです。
    このサンプルでは、平文はバイト列(byte[]型)、暗号文はストリーム(Stream型)を想定しています。暗号化の主要処理はCryptoStreamクラスで行っています。
    • 暗号化・復号化にCryptoStreamを使用します。ストリームに対して書込みや読み込みを行うことで自動的に暗号化・復号化が行われます。
    • FileStream, NetworkStream等の他のストリームクラスと併せて使用することができます。
    • CSVファイル等の文字列を前提としたデータの暗号化・復号化を行う場合、CryptStreamをStreamReader/StreamWriter等で開くことで、ReadLine(), ReadToEnd(), WriteLine()等の柔軟なテキスト操作が可能になります。
    • 複数のストリームをネストして開いており、処理終了時にこれらのストリームを解放する必要があります。マイクロソフト等のサンプルでは、usingステートメントをネストして使用していますが、ここではusing宣言を使用してフラットな構造にしています。(using宣言の仕様では、"The using locals will then be disposed in the reverse order in which they are declared."とあり、宣言の逆順で解放される旨が記載されています。)
    • なお、ストリーム(リソース)の有効範囲を狭めて積極的に開放したい場合は、従来のusingステートメントの使用をお薦めします。

バイト列を使ったサンプル

  • 暗号化・復号化のメイン処理のサンプルです。
    • キーや初期ベクトルの生成方法は、前述の「ストリームを使ったサンプル」と同様です。
  • 前述のメイン処理から呼び出している暗号化・復号化処理メソッドです。
    このサンプルでは、平文も暗号文もバイト列(byte[]型)を想定しています。暗号化の主要処理はEncryptor/Decryptor(ICryptoTransform)のTransformFinalBlock()メソッドで行っています。
    • AESは平文・暗号文を所定の長さのデータ(ブロック)に分けて、暗号化・復号化します。ICryptoTransformには、TransformBlock()TransformFinalBlock()メソッドが用意されており、途中ブロックはTransformBlock()、最後のブロックはTransformFinalBlock()を使用するように思えます。しかしながら、TransformFinalBlock()だけで全てのブロックを暗号化・復号化できるようです。