web-dev-qa-db-ja.com

生のモジュラスと指数をRSA公開鍵(.pem形式)に変換する方法

RSA公開鍵のモジュラスと指数をバイナリファイルに埋め込んでいます。blob全体を抽出して、使用可能な.pem公開鍵を作成しようとしています。

現在、260バイト全体(指数は4バイト、モジュラスは256バイト)を抽出し、base64としてエンコードしています。私は次のシェルコマンドを使用してそれを行っています:

tail -c $((filesize - start_of_key_data)) filename | head -c $size_of_key_data | base64 > outkey

これにより、次の文字列が得られます。

<<<<<< modulus & exponent extracted from binary file, base64-encoded >>>>>>

tZyrQA6cZFJfVm6FyXwtZaLQYg8EecuO+ObrHTwc8JO+XrgnpNAdmlhbAEPxSNnjwhNnbYGYGL4F
vzmnZXzZU71Key42HQPh1k2Zx1UDbrH5ciODKx1ZbuEx8K24SHnL1nY/H75hwhT/ZRRVGQDvYDT+
sgzw2vmV66+dflw1Zs8BLhqjLjczdHvjeVXsDRJ9Mvvd/dhFH8UlTf4JpLGya9nsNIfNBBIf1Lll
RWwCTiEIbaOMgWcLjLV/2tk/j5Dra/oQnVf/2hVsEF/hXEx41YjeEW/warweoDVG7zaxrHEc/k/r
ZCUCZKxf8nBKdqax/gRICvkG6e5xg2GQw0W/ZwABAAE=

さて、モジュラスと指数が最初に抽出されたkey.pemキーペアを取得し、そのように公開部分を表示すると

openssl rsa -in key.pem -pubout -out pubkey.pem

この文字列を取得します(ヘッダーとフッターの行を省略しました:

<<<<<<<<< valid public key data extracted from keypair >>>>>>>>>

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtZyrQA6cZFJfVm6FyXwt
ZaLQYg8EecuO+ObrHTwc8JO+XrgnpNAdmlhbAEPxSNnjwhNnbYGYGL4FvzmnZXzZ
U71Key42HQPh1k2Zx1UDbrH5ciODKx1ZbuEx8K24SHnL1nY/H75hwhT/ZRRVGQDv
YDT+sgzw2vmV66+dflw1Zs8BLhqjLjczdHvjeVXsDRJ9Mvvd/dhFH8UlTf4JpLGy
a9nsNIfNBBIf1LllRWwCTiEIbaOMgWcLjLV/2tk/j5Dra/oQnVf/2hVsEF/hXEx4
1YjeEW/warweoDVG7zaxrHEc/k/rZCUCZKxf8nBKdqax/gRICvkG6e5xg2GQw0W/
ZwIDAQAB

私が抽出してbase64でエンコードした鍵データは、opensslを使用してkey.pemから抽出した有効な公開鍵データのデータに実際に存在していることがわかります。ただし、最初は45文字で、自分で抽出したデータにはありません-

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA

最後の8文字も異なります。

ZwIDAQAB

モジュラスと指数を使用可能な公開鍵に変換する方法について誰かがアドバイスを提供できますか?

(目標は、これをbashスクリプトで行うことであり、pythonまたは多くの人が示唆しているようにCではありません。)

11
Erik Nyquist

使用したコマンドopenssl rsa -in key.pem -pubout -out pubkey.pemは、次のようなASN.1構造を生成します。

SEQUENCE(2 elem)
  SEQUENCE(2 elem)
    OBJECT IDENTIFIER 1.2.840.113549.1.1.1
    NULL
  BIT STRING(1 elem)
    SEQUENCE(2 elem)
      INTEGER(2048 bit) 229263895356027367204242482830890190076375310244080661230946245232688…
      INTEGER 65537

openssl asn1parse -in pubkey.pemを使用するか、 オンラインASN.1デコーダー を使用して構造を確認できます)。

内容:

  1. 固定ヘッダー(すべてのバイトを含み、シーケンス全体のエンコードとモジュラスのエンコードを指定します)
  2. 係数
  3. 指数のエンコーディングを指定するヘッダー
  4. 指数

モジュラスバイトと指数バイトが正しく収集されている場合は、これら4つを連結することにより、OpenSSLで理解できる形式で公開鍵を作成できます。あなたはすでに最初の長いヘッダーを持っています。 「中央のヘッダー」は「0203」です。

  1. 整数の場合は「02」
  2. 整数自体の長さは3バイトです(65537 = 01 00 01)

モジュラスが2048バイトで指数が3バイトの場合(長さフィールドが有効なままになるように)、PEMファイルは次の4つを連結することで作成できます。

<header> <modulus> 0x02 0x03 <exponent>

バイナリダンプの最後のバイトがOpenSSL出力と異なるのはそのためです。抽出された260バイトには02 03が含まれていませんが、代わりに65537を00 01 00 01として記録します(ASNのように01 00 01ではありません)。 1エンコーディング)。

要約すると、次のようにPEMファイルを作成できます。

抽出したモジュラス+指数をbase64から変換して戻し、それらを抽出します(257バイトオフセットに注意して、65537の先頭のゼロバイトをスキップしてください!):

echo 'tZyrQA6cZFJfVm6FyXwtZaLQYg8EecuO+ObrHTwc8JO+XrgnpNAdmlhbAEPxSNnjwhNnbYGYGL4FvzmnZXzZU71Key42HQPh1k2Zx1UDbrH5ciODKx1ZbuEx8K24SHnL1nY/H75hwhT/ZRRVGQDvYDT+sgzw2vmV66+dflw1Zs8BLhqjLjczdHvjeVXsDRJ9Mvvd/dhFH8UlTf4JpLGya9nsNIfNBBIf1LllRWwCTiEIbaOMgWcLjLV/2tk/j5Dra/oQnVf/2hVsEF/hXEx41YjeEW/warweoDVG7zaxrHEc/k/rZCUCZKxf8nBKdqax/gRICvkG6e5xg2GQw0W/ZwABAAE=' | base64 -d > modulus-exp.bin
dd if=modulus-exp.bin of=modulus.bin bs=1 count=256
dd if=modulus-exp.bin of=exponent.bin bs=1 skip=257 count=3

ヘッダーを作成します。

echo 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA' | base64 -d > header.bin
echo '02 03' | xxd -r -p > mid-header.bin

それらを連結します。

cat header.bin modulus.bin mid-header.bin exponent.bin > key.der

PEMに変換:

openssl pkey -inform der -outform pem -pubin -in key.der -out key.pem

動作するキーを取得することをテストします-ASN.1デコーダーでチェックするか、

openssl asn1parse -in key.pem
openssl asn1parse -in key.pem -strparse 19
16