RSA鍵による署名って、フツーはJava JCEでもCryptoAPIでも.NETでもOpenSSLでも、一つのオペレーションになっていて、中でどう処理されているから知る必要もないんですが、やろうと思えばハッシュとRSA鍵による暗号化・復号の暗号プリミティブで実装することはできます。

今回はRSA署名の中身を図説したものって、なかなか良い物が無かったので、ちょっと書いてみて、関連した相互運用上の問題なんかを紹介します。

RSA署名とは何?よ〜し父さん図説しちゃうぞ



RSA署名って、

文書のハッシュ取って秘密鍵で暗号化するんだよね


って簡単に解説しているものがあったりしますが、その説明って、なんか合っているようで合っていないというか、うそ臭いというか、「本当はどうなの?」っていうはなしが抜けているようで、これまでスッキリしませんでした。多分、それはパディングの話が無いからなんじゃないかと思うんです。

RSA署名の方式はPKCS#1 v2.1の中で定められているんですが、一般的な公開鍵証明書やCMS署名なんかは、その中で定められた "RSASSA-PKCS1-v1_5" というアルゴリズムを使っています。

RSASSA-PKCS1_v1_5アルゴリズムにかなり忠実に図説してみたのがコレ:

図1



左から右(→)が「署名の生成」で、右から左(←)が「署名の検証」です。

RSASSA-PKCS1-v1_5 のオペレーションは大きく、

・ハッシュの計算
・パディング処理
・公開鍵暗号

の3つに分かれます。DigestInfoを作るとこも含めてパディング処理と読んだりすることもあり、この図の方が間違っているかもしれませんが、一般的なプログラミング上のパディング処理を知っている方なら、DigestInfoを作った後からをパディング処理と呼んだ方がスッキリするようなが気がします。

DigestInfoと相互運用性



署名では、署名対象データのハッシュ値とハッシュアルゴリズムを格納するためにDigestInfoというASN.1構造を使います。

RSA PKCS#1 v2.1より
DigestInfo ::= SEQUENCE {
digestAlgorithm DigestAlgorithm,
digest OCTET STRING
}

DigestAlgorithm ::= AlgorithmIdentifier { {PKCS1-v1-5DigestAlgorithms} }

PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= {
{ OID id-md2 PARAMETERS NULL }|
{ OID id-md5 PARAMETERS NULL }|
{ OID id-sha1 PARAMETERS NULL }|
{ OID id-sha256 PARAMETERS NULL }|
{ OID id-sha384 PARAMETERS NULL }|
{ OID id-sha512 PARAMETERS NULL }
}


署名生成時のアルゴリズムパラメータNULL



DigestInfoでハッシュアルゴリズムを指定する際に、アルゴリズムパラメータを指定できるんですが、SHA1、SHA2シリーズの場合にはNULLを指定します。このNULLを入れる入れないで、相互運用上の問題が起きたりします。

この辺りは昔、RSAとNISTの間で紆余曲折あったそうなんですが、解決のためにRSAはv2.1の訂正(PKCS #1 v2.1 Errat)を2005年12月に出しています。結論から言うと

・署名生成時:NULLを含めるものとする(SHALL)
・署名検証時:NULLがあってもなくても検証できるものとする(SHALL)

生成については、これまで自分が触ることができた10ぐらいの署名実装で一つを除き問題なくNULLが含まれていましたし、手当たり次第調べた証明書、CRLなんかも全てNULLが含まれた形になっています。残りの一つについても、パッチが出ているそうなので早く修正されるといいなぁ、、、と思います。(とある製品が国内2つの実サービスで使われているんですが、もう長いことパッチ未適用になってます。残念。)

検証については、目にした殆どの実装がNULLがあっても無くても検証できるようになっているんですが、入手できたうちの20%ぐらいの実装はNULLが無いと検証失敗します。

この辺りは、ハッシュとRSA暗号のプリミティブを使ってNULLの入ってない署名を作ったり、生の署名値、証明書、CMS署名、XML署名などで署名値のDigestInfoにNULLが入っているのかどうかをチェックするツールを作って調べました。

なんか、今回も細かい話ですみませんね。ではでは。