概要
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) などの鍵導出関数を使用する必要があります。
注意点
- 文字列として扱わない: 暗号キーやIVは任意のバイト列であり、UTF-8などのテキストではありません。保存や転送を行う際は、必ず
Convert.ToBase64Stringを使用するか、バイナリとして扱ってください。Encoding.UTF8.GetString(key)などを行うとデータが破損します。 - Keyの管理: 生成したKeyは外部に漏れないよう厳重に管理する必要があります。ソースコードへのハードコーディングは厳禁です。
- IVの役割: IVは「秘密」である必要はありませんが、同じKeyで暗号化するたびに「毎回異なる値」である必要があります。IVを固定して使い回すと、暗号文のパターンから解読の手がかりを与えてしまう脆弱性につながります。
まとめ
共通鍵暗号方式において、Aes.Create() メソッドを使用することで、暗号学的に安全な乱数に基づいたKeyとIVを容易に生成することができます。生成されたデータはバイナリ形式であるため、可読性が必要な場面ではBase64形式に変換して取り扱い、実際の運用ではIVをメッセージごとに変更し、Keyをセキュアなストレージで管理する設計が不可欠です。
