web-dev-qa-db-ja.com

ECDSA署名からrとsを2つの連結整数(OpenSSL)として取得します。

EVP_DigestSignFinal()は、DERエンコードされた署名を私に与えます。

いくつかの例:

ECDSA-SHA-256

30 44 02 20 [..r..] 02 20 [..s..]
30 46 02 21 [..r..] 02 21 [..s..]
30 45 02 20 [..r..] 02 21 [..s..]

ECDSA-SHA-224

30 3d 02 1c [..r..] 02 1d [..s..]
30 3c 02 1c [..r..] 02 1c [..s..]

サイズは変わる可能性があるので、それらを連結したいと思います。署名が何バイトになるかを知る良い方法は何ですか?あるいは、OpenSSLにすでに実装されている機能があるのでしょうか?

1
tzippy

ECDSAシグニチャーは、2つのSEQUENCE値のINTEGERである ASN.1 構造としてエンコードされます。エンコードされると、最初のバイトは0x30SEQUENCEを意味します)で続き、1バイトまたは2バイトでエンコードされた長さが続きます。長さがnバイトの場合、値の1バイトとしてエンコードされますnif n≤127、または2バイトの値0x81 thenn、128≤n≤255(後者は、P-521のような「大きな」曲線を使用する場合に発生する可能性があります)。これらのnバイトは、2つのINTEGER値を連結したもので、それぞれに独自のタグ(値のバイト0x02 )、次にその長さ(同じエンコーディング。実際には、1バイト以上。1000ビット程度の曲線が必要になるため、複数の曲線が必要になるため)、次にINTEGER値。 INTEGERの値は符号付きビッグエンディアンを使用します(そのため、値の先頭バイトが0x00になる場合があります)。

ASN.1構造を適切にエンコードおよびデコードすることは難しい技術です。 OpenSSLにそのためのパブリック関数があるかどうかはわかりません。 この関数別のSSLライブラリ から、ASN.1から「未加工」のECDSA署名に変換します(「未加工」とは、2つの整数値が単にビッグエンディアンでエンコードされていることを意味します)と連結され、どちらも同じエンコード長になるように調整されます)。

2
Thomas Pornin