【C#】RSA鍵ペアの生成とPEM形式による秘密鍵・公開鍵のテキスト化

目次

概要

最新の.NET環境において、標準ライブラリのみを使用してRSA暗号化方式のキーペア(秘密鍵と公開鍵)を新規生成し、取り回しのしやすいPEM形式(Base64文字列)としてエクスポートする実装です。 従来のXML形式(ToXmlString)に代わり、OpenSSLや他のプラットフォームとも互換性が高い標準的なテキスト形式を採用しています。

仕様(入出力)

  • 入力: キーサイズ(ビット長、例: 2048, 4096)
  • 出力:
    • 秘密鍵のPEM形式文字列(-----BEGIN PRIVATE KEY----- …)
    • 公開鍵のPEM形式文字列(-----BEGIN PUBLIC KEY----- …)
  • 動作: メモリ上でキーを生成し、標準出力へ表示した後、文字列からキー情報を復元できることを検証します。

基本の使い方

using System.Security.Cryptography;

// 2048ビットでキーを生成
using var algorithm = RSA.Create(2048);

// 秘密鍵(PKCS#8)を文字列として取得
var privateKeyPem = algorithm.ExportRSAPrivateKeyPem();

// 公開鍵(SPKI)を文字列として取得
var publicKeyPem = algorithm.ExportSubjectPublicKeyPem();

コード全文

このコードは .NET 7 以降の環境で動作するコンソールアプリケーションです。

using System;
using System.Security.Cryptography;

class Program
{
    static void Main()
    {
        // 1. RSAアルゴリズムのインスタンス生成(キーサイズ指定)
        // 従来のRSACryptoServiceProviderではなく、クロスプラットフォーム対応のCreateを使用
        using var secureIdentity = RSA.Create(2048);
        
        Console.WriteLine($"[Key Generated] KeySize: {secureIdentity.KeySize} bits");

        // 2. 秘密鍵のエクスポート(PEM形式: PKCS#8)
        // サーバー側で保存・管理するための機密情報
        string secretToken = secureIdentity.ExportRSAPrivateKeyPem();
        Console.WriteLine("\n--- Exported Private Key (Keep Secret) ---");
        Console.WriteLine(secretToken);

        // 3. 公開鍵のエクスポート(PEM形式: SubjectPublicKeyInfo)
        // クライアント等に配布して暗号化に使ってもらう情報
        string publicToken = secureIdentity.ExportSubjectPublicKeyPem();
        Console.WriteLine("\n--- Exported Public Key (Distribute) ---");
        Console.WriteLine(publicToken);

        // 4. 文字列からの復元検証(インポート)
        VerifyKeyImport(secretToken, publicToken);
    }

    /// <summary>
    /// エクスポートされたPEM文字列からRSAインスタンスが復元できるか検証します
    /// </summary>
    static void VerifyKeyImport(string privatePem, string publicPem)
    {
        Console.WriteLine("\n[Validation] Testing key import...");

        // 復元用の新しいインスタンス
        using var validationRsa = RSA.Create();

        try
        {
            // 秘密鍵を含めてインポート(署名や復号が可能になる)
            validationRsa.ImportFromPem(privatePem);
            Console.WriteLine("- Private key import: Success");

            // 念のため公開鍵だけで別インスタンスを初期化できるかも確認
            using var publicOnlyRsa = RSA.Create();
            publicOnlyRsa.ImportFromPem(publicPem);
            Console.WriteLine("- Public key import: Success");
        }
        catch (CryptographicException ex)
        {
            Console.WriteLine($"- Import Error: {ex.Message}");
        }
    }
}

カスタムポイント

  • キーサイズの変更: RSA.Create(2048) の数値を 4096 に変更することで、強度は上がりますが処理速度は低下します。用途に合わせて調整してください。
  • 保存先の変更: 現在は Console.WriteLine で出力していますが、実運用では System.IO.File.WriteAllText 等を使用して .pem ファイルとして保存するか、Azure Key Vault などのセキュアなストレージへ格納してください。
  • フォーマットの選択: Java等のレガシーシステムと連携する場合は ExportPkcs8PrivateKeyPem の代わりに ExportEncryptedPkcs8PrivateKeyPem を使用し、パスワード付きでエクスポートすることを検討してください。

注意点

  1. 秘密鍵の流出厳禁: 出力された secretToken(秘密鍵)は決して第三者に渡してはいけません。GitHub等のリポジトリへのコミットも厳禁です。
  2. ToXmlStringの利用回避: 古いコードで見られる ToXmlString はWindows固有の実装に依存する場合があり、Linux/Docker環境で動作しないことがあります。現代の.NET開発では上記のようなPEM形式またはDER(バイナリ)形式の使用が推奨されます。
  3. エフェメラルキーの寿命: RSA.Create() で生成されたキーはメモリ上にのみ存在します。アプリケーション終了とともに消滅するため、永続化が必要な場合は必ずエクスポートして保存してください。

応用

署名データの作成(秘密鍵を使用)

生成したキーを使用して、データの改ざん検知用署名を作成する例です。

using System.Text;

// ... (前述のコードでキー生成済みとする) ...

var data = "Important Contract Data";
var dataBytes = Encoding.UTF8.GetBytes(data);

// 署名の作成(SHA256ハッシュを使用)
byte[] signature = secureIdentity.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

Console.WriteLine($"\nSignature generated: {BitConverter.ToString(signature).Replace("-", "")}");

まとめ

秘密鍵の管理には細心の注意を払い、必要な場合のみエクスポート処理を行ってください。

RSAキー生成には RSACryptoServiceProvider ではなく RSA.Create() を使用します。

キーの文字列化には、互換性の低いXML形式ではなく、標準的なPEM形式(Export...Pem)を使用するのが現代の定石です。

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

この記事を書いた人

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

目次