【C#】CspParametersを用いたRSAキーコンテナへの秘密鍵格納と再利用

目次

概要

Windows環境において、CryptoAPI(CAPI)のキーコンテナ機能を利用し、RSA鍵ペアをOSレベルで永続化する実装です。 ファイルとして鍵を保存・管理するのではなく、OSのユーザープロファイルまたはマシンストアに関連付けられた「コンテナ名」を指定することで、アプリケーションの再起動後も同じ秘密鍵を呼び出すことが可能になります。

仕様(入出力)

  • 入力: キーコンテナ名(一意の識別子)
  • 出力:
    • コンテナ内に保存されたRSA鍵ペアのXML文字列表現
    • OSのキーストアへの永続的な保存(副作用)
  • 動作: 指定されたコンテナ名に鍵が存在しない場合は新規生成し、存在する場合はその鍵をロードします。

基本の使い方

using System.Security.Cryptography;

// コンテナ名を指定してパラメータを作成
var cspParams = new CspParameters
{
    KeyContainerName = "MyUniqueAppName_KeyContainer"
};

// コンストラクタに渡すと、自動的に「生成」または「読み込み」が行われる
using var rsa = new RSACryptoServiceProvider(cspParams);

// 秘密鍵を含むXMLを取得(バックアップ等)
string xmlKey = rsa.ToXmlString(includePrivateParameters: true);

コード全文

このコードはWindows環境での実行を前提としています。

using System;
using System.Security.Cryptography;
using System.Runtime.Versioning;

[SupportedOSPlatform("windows")]
class Program
{
    static void Main()
    {
        // 1. コンテナ名の定義
        // システム内で一意になるような名前を付けます
        const string ContainerName = "LocalAppIdentity_v1";

        try
        {
            Console.WriteLine($"Accessing Key Container: {ContainerName}");

            // 2. CSPパラメータの設定
            // KeyContainerNameを指定することで、この名前のキーストアにアクセスします
            var parameters = new CspParameters
            {
                KeyContainerName = ContainerName,
                // マシン全体で共有する場合は以下を有効化(要管理者権限)
                // Flags = CspProviderFlags.UseMachineKeyStore 
            };

            // 3. インスタンス生成(鍵のロードまたは新規作成)
            // 指定したコンテナに鍵があればロード、なければ新規生成して自動保存されます
            using var rsa = new RSACryptoServiceProvider(2048, parameters);

            // 4. 鍵情報の確認
            // 永続化されていることを確認するため、鍵の指紋(KeySize等)を表示
            Console.WriteLine($"Key Loaded. Size: {rsa.KeySize} bits");

            // 5. 秘密鍵のエクスポート(XML形式)
            // ToXmlString(true) で秘密鍵パラメータを含みます
            string privateKeyXml = rsa.ToXmlString(includePrivateParameters: true);
            
            Console.WriteLine("\n--- Private Key (XML Format) ---");
            Console.WriteLine(privateKeyXml);

            // 6. 公開鍵のエクスポート(XML形式)
            // 配布用には includePrivateParameters: false を指定します
            string publicKeyXml = rsa.ToXmlString(includePrivateParameters: false);

            Console.WriteLine("\n--- Public Key (XML Format) ---");
            Console.WriteLine(publicKeyXml);
        }
        catch (PlatformNotSupportedException)
        {
            Console.WriteLine("Error: Key Containers are supported only on Windows.");
        }
        catch (CryptographicException ex)
        {
            Console.WriteLine($"Crypto Error: {ex.Message}");
        }
    }
}

カスタムポイント

  • KeyContainerName: アプリケーション名やユーザーIDを含むユニークな文字列に変更してください。競合すると他のアプリの鍵を上書きする恐れがあります。
  • CspProviderFlags: Webサーバーやサービスで使用する場合は、CspProviderFlags.UseMachineKeyStore を指定して、特定のユーザープロファイルに依存しない「マシンキーストア」を利用するのが一般的です(実行には管理者権限が必要です)。
  • キーサイズ: コンストラクタの第1引数(例: 2048)を変更することで強度を調整できます。

注意点

  1. Windows限定機能: CspParameters とキーコンテナを利用するこの手法は Windows API (CAPI) に依存しています。Linux や macOS では動作しないため、クロスプラットフォームが必要な場合はPEMファイル保存などを検討してください。
  2. 秘密鍵の取り扱い: ToXmlString(true) で出力された文字列には生の秘密鍵が含まれます。ログ出力や画面表示はデバッグ目的に留め、本番環境では慎重に扱ってください。
  3. 明示的な削除: キーコンテナに保存された鍵は、OSを再起動しても残り続けます。不要になった場合は rsa.PersistKeyInCsp = false; を設定した上で rsa.Clear(); を呼び出し、明示的に削除する必要があります。

応用

コンテナからの鍵削除

使用しなくなった鍵をクリーンアップする処理です。

using System.Security.Cryptography;

// 削除対象のコンテナを指定
var deleteParams = new CspParameters { KeyContainerName = "LocalAppIdentity_v1" };

using var rsaToDelete = new RSACryptoServiceProvider(deleteParams);

// このプロパティをfalseにしてから破棄すると、コンテナから鍵が削除される
rsaToDelete.PersistKeyInCsp = false;
rsaToDelete.Clear();

Console.WriteLine("Key container deleted.");

まとめ

RSACryptoServiceProviderCspParameters を組み合わせることで、Windowsのキーストア機能を利用した鍵管理が実現できます。ファイルパスの管理が不要になる利点がありますが、OS依存の機能である点と、永続化されたデータが意図せず残り続けるリスクを考慮して設計する必要があります。

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

この記事を書いた人

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

目次