【C#】共通鍵暗号方式の暗号化キーと初期化ベクトル(IV)を生成する方法

目次

概要

AESなどの共通鍵暗号方式(Symmetric Algorithm)で安全な通信を行うには、暗号化と復号で同じ「キー(Key)」と「初期化ベクトル(IV: Initialization Vector)」を共有する必要があります。 .NETの System.Security.Cryptography 名前空間に含まれるクラスを使用することで、暗号学的に安全な乱数を用いたKeyとIVを簡単に生成できます。

仕様(入出力)

  • 入力: なし(ランダム生成のため)。
  • 出力: 生成されたKeyとIV(バイト配列)。
  • 前提: .NET標準ライブラリを使用。アルゴリズムはAES(Advanced Encryption Standard)を推奨。

基本の使い方

Aes.Create() でインスタンスを作成した時点で、プロパティには既にランダムなKeyとIVがセットされていますが、GenerateKey()GenerateIV() メソッドを呼び出すことで、明示的に新しいランダムな値を再生成できます。

using var aes = Aes.Create();

// 明示的に再生成する場合(インスタンス作成直後は自動生成されているため必須ではない)
aes.GenerateKey();
aes.GenerateIV();

byte[] key = aes.Key;
byte[] iv = aes.IV;

コード全文

ここでは、最も標準的なアルゴリズムであるAESを使用してKeyとIVを生成し、その内容を保存・共有しやすいBase64形式で表示するコードです。 入力コードにあった AesManaged は古い実装であるため、現在はプラットフォームに最適な実装を自動選択する Aes.Create() の使用が推奨されます。

using System;
using System.Security.Cryptography;

class Program
{
    static void Main()
    {
        Console.WriteLine("AES用キーとIVの生成を開始します...");

        // キーとIVの生成
        var (key, iv) = GenerateKeyAndIv();

        // 結果の表示
        // バイナリデータ(byte[])は、そのままでは文字化けするためBase64文字列に変換して扱うのが一般的です
        Console.WriteLine($"Key (サイズ: {key.Length} bytes / {key.Length * 8} bits)");
        Console.WriteLine(Convert.ToBase64String(key));
        
        Console.WriteLine();

        Console.WriteLine($"IV  (サイズ: {iv.Length} bytes / {iv.Length * 8} bits)");
        Console.WriteLine(Convert.ToBase64String(iv));
    }

    /// <summary>
    /// AESアルゴリズム用のKeyとIVを生成して返します
    /// </summary>
    static (byte[] Key, byte[] IV) GenerateKeyAndIv()
    {
        // Aes.Create()を使用するのがベストプラクティス
        // usingを使うことで、使用後に機密情報を含むリソースを破棄する
        using var aes = Aes.Create();

        // 鍵のサイズを指定(通常は128, 192, 256のいずれか。デフォルトは256が多い)
        aes.KeySize = 256;

        // ブロックサイズはAESの場合128ビット固定
        aes.BlockSize = 128;

        // GenerateKey(), GenerateIV() を呼ぶと、既存のプロパティを強力な乱数で上書きします
        aes.GenerateKey();
        aes.GenerateIV();

        // プロパティから値を取得してコピーを返す
        // (aesインスタンスがDisposeされても、返却したbyte[]は残ります)
        return (aes.Key, aes.IV);
    }
}

カスタムポイント

  • KeySizeの変更: aes.KeySize = 128; のように設定することで、鍵の長さを変更できます。長いほど強固ですが、処理速度とのトレードオフや、輸出管理規制・互換性の制約を受ける場合があります。
  • パスワードからの生成: ユーザーが入力したパスワードからKeyを生成したい場合は、単純な乱数生成(GenerateKey)ではなく、Rfc2898DeriveBytes (PBKDF2) などの鍵導出関数を使用する必要があります。

注意点

  1. 文字列として扱わない: 暗号キーやIVは任意のバイト列であり、UTF-8などのテキストではありません。保存や転送を行う際は、必ず Convert.ToBase64String を使用するか、バイナリとして扱ってください。Encoding.UTF8.GetString(key) などを行うとデータが破損します。
  2. Keyの管理: 生成したKeyは外部に漏れないよう厳重に管理する必要があります。ソースコードへのハードコーディングは厳禁です。
  3. IVの役割: IVは「秘密」である必要はありませんが、同じKeyで暗号化するたびに「毎回異なる値」である必要があります。IVを固定して使い回すと、暗号文のパターンから解読の手がかりを与えてしまう脆弱性につながります。

まとめ

共通鍵暗号方式において、Aes.Create() メソッドを使用することで、暗号学的に安全な乱数に基づいたKeyとIVを容易に生成することができます。生成されたデータはバイナリ形式であるため、可読性が必要な場面ではBase64形式に変換して取り扱い、実際の運用ではIVをメッセージごとに変更し、Keyをセキュアなストレージで管理する設計が不可欠です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次