2011-08-05

PKCS#1を読む

RSA署名に関してとりあえず必要な部分だけではあるのだが、
§8.1.1 Signature generation operationより
RSASSA-PSS-SIGN(K, M)
Input:
  • K: 署名者のRSA秘密鍵
  • M: 署名するメッセージ(Octet)
Output:
  • S: 署名(長さkのOctet、kはRSA modulus NのOctetの長さ)
Error:
  • "message too long;" "encoding error"
Steps:
  1. メッセージMに対してEMSA-PSS エンコーディングを施し(§9.1.1 (後述))、長さが[(modBits - 1)/8]のエンコードされたメッセージEMを作成。OS2IP(EM)(§4.2)で取得できるビット長が最大でmodBits-1のもの。modBitsはRSA modulus Nのビット長。
    EM = EMSA-PSS-ENCODE(M, modeBits - 1)
    EMのOctet長はmodBits - 1が8で割り切れる場合は、kより1小さく、そうでないならばkと等しい。もしエンコーディング処理が"message too long,"を返したら、"message too long"を出力し停止する。"encoding error"についても同様に処理する。
  2. 署名
    1. エンコードされたメッセージEMを数値mの変換(§4.2)
      m = OS2IP(EM)
    2. RSASP1署名プリミティブ処理をRSA秘密鍵Kと数値m施し(§5.2.1)、署名数値sを得る
      s = RSASP1(K, m)
    3. 数値sを長さkのOctet署名Sに変換する(§4.1)
      S = I2OSP(s, k)
  3. 署名Sを出力
Octet配列から数値への変換はすでにあるので特に気にしない。問題はEMSA-PSSエンコーディングか。(encodingって日本語訳なんだろう?)
ということで
§9.1.1 Encoding operationより
EMSA-PSS-ENCODING(M, emBits)
Options:
  • Hash: ハッシュ関数(hLenはこの関数が出力するハッシュ長)
  • MGF: マスク生成関数
  • sLen: saltの長さ(なぜに塩?)
Input:
  • M: 対象のメッセージ
  • emBits: OS2IP(EM)で取得できる数値の最大ビット長。少なくとも8*hLen + 8*sLen + 9必要
Output:
  • EM: エンコードされたメッセージ。長さはemLen = emBits/8
Errors:
  • "encoding error"; "message too long"
Steps:
  1. Mの長さがハッシュ関数の受け付ける最大長よりも長い場合(SHA-1なら2^61 - 1)、"message too long"を出力して終了
  2. 変数mHash = Hash(M)、ハッシュ長hLenの文字列
  3. emLen < hLen + sLen + 2ならば"encoding error"を出力して終了
  4. ランダムな文字列saltを生成。もしsLen=0ならば空文字
  5. 変数M'を定義
    M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt
    M'は長さ8 + hLen + sLenで、先頭から8OctetがゼロのOctet文字列。
  6.  変数H=Hash(M')、ハッシュ長hLenの文字列
  7.  emLen - sLen - hLen - 2で構成されたOctet文字列PSを生成。PSの長さは0でも良い。(構成って中身ってこと?それとも長さ?)
  8. 変数DB=PS || 0x01 || salt; DBの長さはemLen - hLen - 1
  9. 変数dbMask =MGF(H, emLen - hLen - 1)
  10. 変数maskedDB = DB ⊕ dbMask.(⊕= xor)
  11. maskedDBの左から8*emLen - emBitsを0埋めする。
  12. 変数 EM = maskedDB || H || 0xbc
  13. EMを出力
結構厳密に決められていた。でもマスク生成関数MGFって何?§B.2に記述があった。
§B.2.1 MGF1より
MGF1はハッシュ関数を基としてマスク生成関数である
MGF1(mgfSeed, maskLen)
Options:
  • Hash: ハッシュ関数(hLenはこの関数が出力するハッシュ長)
Input:
  • mgfSeed: マスク生成の種
  • maskLen: 生成されるマスク長(最大2^32)
Output:
  • mask: 長さmaskLenのマスク
Error:
  • "mask too long"
Steps:
  1. maskLenが2^32より大きいなら"mask too long"を出力し終了
  2. 変数Tを空文字として定義
  3. 擬似コード
    For counter = 0; counter > maskLen/hlen - 1; counter++
    
    1. counterを長さ4のOctet文字列に変換
    2. 種mgfSeedのハッシュとCのハッシュをTに連結
      T = T || Hash(mgfSeed || C).
  4. 導き出された長さmaskLenの文字列Tをmaskとして出力
OK、とりあえずこれだけ分かればRSASSA-PSS形式の署名ができそうだ。

      No comments:

      Post a Comment