🔐

RSA秘密鍵をJSONフォーマットで使用する

2024/10/23に公開

RSA秘密鍵をJSONフォーマットで使用する

概要

アプリケーション側でRSA署名をするにあたって、RSA秘密鍵をJSON形式で扱う機会がありました。やり方をまとめておきたいと思います。

RSA鍵の生成

RSA鍵の生成については、以下の記事に記載しましたので、ご覧ください。

https://zenn.dev/shimiyu/articles/5150ad996e2d87#opensslでrsa署名を試してみる

RSA秘密鍵の構成要素

RSA秘密鍵の構成要素は、opensslのコマンドでテキスト形式で出力できます。

下記コマンドを実行すると、秘密鍵の各パラメータ(モジュラス、公開指数、秘密指数、素因数など)が16進数で表示されます。

$ openssl rsa -in private_key.pem -text -noout
Private-Key: (2048 bit, 2 primes)
modulus:
    00:ad:...略
publicExponent: 65537 (0x10001)
privateExponent:
    25:1d:...略
prime1:
    00:d7:...略
prime2:
    00:cd:...略
exponent1:
    04:06:...略
exponent2:
    0a:37:...略
coefficient:
    17:0c:...略

https://datatracker.ietf.org/doc/html/rfc3447#appendix-A.1.2

JSON形式にする方法

上で見た通り、秘密鍵の各パラメータは、16進数で表記されています。

これをJSON形式で保存する場合、Base64エンコードを施す必要があります。

16進数からBase64エンコードする

MacOSの場合

下記コマンドにより、指定した16進数の文字列をBase64エンコードできます。

$ echo "base64エンコードしたい16進数の文字列" | xxd -r -p | openssl base64

以下の流れで、Base64エンコードした結果が表示されます。

  • echo "base64エンコードしたい16進数の文字列": echo コマンドで16進数の文字列を標準出力します
  • xxd -r -p: 16進数の文字列がバイナリデータに変換されます。xxdは、バイナリデータ↔︎16進数の変換に使われるLinuxコマンドです。-rは逆変換のオプションであり、16進数のデータをバイナリに戻す機能を提供します。
  • openssl base64: バイナリデータがBase64エンコードされます

Windowsの場合

Windowsの場合、Base64エンコードするPowerShellのScriptを用意します。

Param (
    [string]$hex
)

$hex = $hex -replace "[:\s]", ""

# 16進数データをバイナリに変換
$bytes = for ($i = 0; $i -lt $hex.Length; $i += 2) {
    [Convert]::ToByte($hex.Substring($i, 2), 16)
}

# バイト配列をBase64エンコード
$base64 = [Convert]::ToBase64String($bytes)

# Base64エンコード結果を表示
$base64

下記コマンドでBase64エンコードできます。

任意のディレクトリ\base64encode.ps1 -hex "16進数表記の値"

今回試していませんが、pythonがインストールされていれば、pythonでも簡単にBase64エンコードできそうです。

設定ファイルに保存する

前項でBase64エンコードした値をアプリケーション側に設定します。

例えば、appsettings.jsonのような設定ファイルで、RSA秘密鍵のパラメータを次のように設定します。

{
  "ClientSecret": {
    "Modulus": "modulusの値をBase64エンコードした値",
    "Exponent": "AQAB",
    "D": "privateExponentの値をBase64エンコードした値",
    "P": "prime1の値をBase64エンコードした値",
    "Q": "prime2の値をBase64エンコードした値",
    "DP": "exponent1の値をBase64エンコードした値",
    "DQ": "exponent2の値をBase64エンコードした値",
    "InverseQ": "coefficientの値をBase64エンコードした値"
  }
}

このようにRSA秘密鍵の構成要素をJSON形式で定義することで、アプリケーション内で秘密鍵を利用できるようになります。例えば、APIクライアント認証の際、アプリケーションがこの鍵を使ってRSA署名を行うケースなどが考えられます。

もちろん、秘密鍵を設定ファイルに直接保存するのはNGです。実際にはAzure Key VaultのようなKMS(Key Management Service)を使い、適切な場所に保管するのが大事です。

最後に

以上です。

秘密鍵をアプリケーション側で扱うケースは初めてだったので、やったことを整理しました。

RSAや暗号化などについては、「暗号技術入門」を読んでみたいなーと思ってます(積読)

https://cr.hyuki.net/

Discussion