目次
概要
「—–BEGIN RSA PRIVATE KEY—–」で始まるPKCS#1形式のPEMファイルを読み込み、その秘密鍵を使用して暗号化データを復号する実装です。 .NET Core 3.0以降で追加された ImportRSAPrivateKey メソッドを使用し、テキスト処理で抽出したバイナリデータから鍵情報を復元します。
仕様(入出力)
- 入力:
- RSA秘密鍵ファイル(PKCS#1形式 PEM:
private.key) - 暗号化されたデータ(Base64文字列)
- RSA秘密鍵ファイル(PKCS#1形式 PEM:
- 出力: 復号された平文(UTF-8)
- 前提: 読み込むファイルはPKCS#1形式(ヘッダーにRSAが含まれる)であること。
基本の使い方
using System.Security.Cryptography;
using System.Text;
// 秘密鍵のPEM文字列からヘッダー・フッターを除去してバイナリ化
var pemStr = File.ReadAllText("private.key");
var base64 = pemStr.Replace("-----BEGIN RSA PRIVATE KEY-----", "")
.Replace("-----END RSA PRIVATE KEY-----", "")
.Replace("\r", "").Replace("\n", "");
var keyBytes = Convert.FromBase64String(base64);
// RSA初期化とインポート
using var rsa = RSA.Create();
rsa.ImportRSAPrivateKey(keyBytes, out _);
// 復号(暗号化時と同じパディングを指定)
var encrypted = Convert.FromBase64String("Base64Data...");
var decrypted = rsa.Decrypt(encrypted, RSAEncryptionPadding.OaepSHA256);
コード全文
このコードは、ファイル読み込みから復号までの一連のプロセスを、自己完結するコンソールアプリとして記述しています。
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
class Program
{
static void Main()
{
// 1. テストデータの準備
// 実際には外部から受け取ったBase64文字列を使用します
string encryptedBase64 = "(ここに暗号化されたBase64文字列が入ります)";
// 動作検証用にダミーの鍵と暗号データを作成します(本来は不要な処理)
CreateDummyEnvironment(out string keyFilePath, out encryptedBase64);
try
{
Console.WriteLine($"Reading Private Key from: {keyFilePath}");
// 2. PEMファイルの読み込みと整形
// PKCS#1形式のヘッダーとフッター、改行コードを削除してBase64部分のみ抽出します
string pemContent = File.ReadAllText(keyFilePath);
string privateKeyBase64 = pemContent
.Replace("-----BEGIN RSA PRIVATE KEY-----", "")
.Replace("-----END RSA PRIVATE KEY-----", "")
.Replace("\r", "")
.Replace("\n", "")
.Trim();
byte[] privateKeyBytes = Convert.FromBase64String(privateKeyBase64);
// 3. RSAインスタンスへの秘密鍵インポート
using var rsa = RSA.Create();
// PKCS#1形式としてインポート
rsa.ImportRSAPrivateKey(privateKeyBytes, out int bytesRead);
Console.WriteLine($"Key imported. ({bytesRead} bytes read)");
// 4. 復号処理
byte[] encryptedData = Convert.FromBase64String(encryptedBase64);
// 暗号化時と一致するパディングモードを指定(推奨: OAEP SHA256)
byte[] decryptedData = rsa.Decrypt(encryptedData, RSAEncryptionPadding.OaepSHA256);
// 5. 結果出力
string plainText = Encoding.UTF8.GetString(decryptedData);
Console.WriteLine("\n[Decrypted Message]");
Console.WriteLine(plainText);
}
catch (FormatException)
{
Console.WriteLine("Error: The key file format is invalid.");
}
catch (CryptographicException ex)
{
Console.WriteLine($"Decryption Error: {ex.Message}");
Console.WriteLine("Hint: Check padding mode or if the key matches the encryption key.");
}
}
// 検証用:ダミーの鍵ファイルと暗号化データを作成するヘルパー
static void CreateDummyEnvironment(out string path, out string encryptedBase64)
{
path = "test_private_pkcs1.pem";
using var rsa = RSA.Create(2048);
// 秘密鍵ファイルの作成
byte[] keyBytes = rsa.ExportRSAPrivateKey();
var sb = new StringBuilder();
sb.AppendLine("-----BEGIN RSA PRIVATE KEY-----");
sb.AppendLine(Convert.ToBase64String(keyBytes, Base64FormattingOptions.InsertLineBreaks));
sb.AppendLine("-----END RSA PRIVATE KEY-----");
File.WriteAllText(path, sb.ToString());
// 暗号化データの作成
byte[] data = Encoding.UTF8.GetBytes("Secret Code: 777");
byte[] enc = rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
encryptedBase64 = Convert.ToBase64String(enc);
}
}
カスタムポイント
- パディングの変更: 入力されたコード例の
fOAEP: trueは古い実装(SHA1使用)を指すことが多いです。互換性が必要な場合はRSAEncryptionPadding.OaepSHA1を使用してください。新規開発ではOaepSHA256が標準的です。 - キーファイルの形式: ファイルの中身が
-----BEGIN PRIVATE KEY-----(RSAが付かない)で始まっている場合は、PKCS#8形式です。その場合はImportPkcs8PrivateKeyメソッドを使用してください。
注意点
- 秘密鍵の管理: 秘密鍵ファイルはシステムの最も重要な機密情報です。ファイルシステムのアクセス権限(ACL)を厳格に設定し、アプリケーション実行ユーザーのみが読み取れるように制限してください。
- ヘッダー文字列の正確性: 手動で置換を行う場合、ヘッダー文字列(
-----BEGIN...)が一文字でも間違っていると正しくBase64文字列にならず、例外が発生します。 - 例外処理: パスワードで保護されたPEMファイル(Encrypted Private Key)はこの方法では読み込めません。その場合は
ImportEncryptedPkcs8PrivateKeyなどの専用メソッドが必要になります。
応用
ImportFromPemによる簡略化(.NET 5以降)
手動の文字列操作(Replace)を廃止し、.NETの機能でPEMを自動解析する推奨パターンです。
using var rsa = RSA.Create();
// ファイルの中身をそのまま渡すだけで、ヘッダーや形式(PKCS#1/PKCS#8)を自動判別
string pemContent = File.ReadAllText("private.key");
rsa.ImportFromPem(pemContent);
// 以降は同じ
var result = rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA256);
まとめ
PKCS#1形式の秘密鍵を利用するには、ImportRSAPrivateKey メソッドを使用します。これにより、従来のXML形式への変換を経ることなく、OpenSSL等で生成された標準的な鍵ファイルを直接扱えるようになります。ただし、より現代的な .NET 5以降の環境では、ヘッダー処理や形式判別を自動化してくれる ImportFromPem メソッドの使用が最も安全で効率的です。
