2017-03-03 11 views
2

ハードウェアセキュリティモジュールのPKCS#11 APIにPKCS#11 Java Wrapperを使用してDSAでSHA-256ハッシュに署名したいとします。この目的のために、メカニズムCKM_DSAを選択し、対応するDSAキーをトークンからロードし、データ(バイト配列として読み取られた)を署名させた。私がテストに使う鍵は、1024ビットの長さです。OpenSSLでPKCS#11によって生成されたDSA署名の確認

すべてが正常に動作するようです:キーがロードされ、Session.sign()は長さ40のバイト[]配列を生成する。これは、PKCS#11言う仕様に対応:

」をするためにこの機構の目的のために、DSA署名は、DSAの連結に対応する40バイトの文字列、 は、それぞれ最上位バイトを占め、rおよびsの値である。」は

が今は使用してこの署名を検証しますopenSSL、すなわち、使用する:

openssl dgst -d -sha256 -verify ${PUBLIC_KEY} -signature signature.der <raw input file> 

このI

a)はOpenSSLの

Bを使用して署名を作成した場合に動作が)はBouncyCastleを使用して署名を作成し、ASN1符号化されたDER配列として結果をコード化します。

今、私はPKCS#11署名で同じことをしたいと思います。私の質問は:どのようにこの40バイト配列をフォーマットするのですか?私は、次のことを試してみました:

 //sign data 
     byte[] signedData = this.pkcs11Session.sign(dataToSign); 
     //convert result 
     byte[] r = new byte[20]; 
     byte[] s = new byte[20]; 
     System.arraycopy(signedData, 0, r, 0, 20); 
     System.arraycopy(signedData, 19, s, 0, 20); 

     //encode result 
     ASN1EncodableVector v = new ASN1EncodableVector(); 
     v.add(new ASN1Integer(r)); 
     v.add(new ASN1Integer(s)); 
     return new DERSequence(v).getEncoded(ASN1Encoding.DER); 

符号化部は、私はRを生成してはBouncyCastleと別のソフトウェアキーで直接sの場合、それは動作しますので、正しいと思われます。さらに、opensslは入力形式を受け入れますが、エラーが発生して検証が失敗することがあります。検証に失敗することもあります。

したがって、私はPKCS#11署名のrとsへの変換が間違っていると仮定します。誰かが間違いを見つけるのを助けることができますか?

+0

完全なスタックトレースを要求したコメントを含むコメントが削除されました。完全なスタックトレースと、いくつかのテストデータとキーを提供してください。 –

+0

2番目の配列のコピーは、19ではなく20番目の位置で開始してはいけませんか? rの最後のバイトが2回あり、sの最後のバイトを取得していないようです。 – bartonjs

答えて

3

あなたはおそらくrsの値をBigIntegerクラスに変換する必要があります。この理由は、ASN.1が符号付きの値のエンコーディングを使用し、DHの結果が符号なしの値のエンコーディングを使用するためです。したがって、ASN.1で負の値を取得する可能性が非常に高くなり、エラーが発生します。

変換を実行するには、new BigInteger(1, r)new BigInteger(1, s)を使用し、結果をASN1Integerインスタンスに入れます。ここで1は、値を正の値に変換する必要があることを示します(つまり、入力は符号なしの正数です)。

+0

LuxOnionは次のように書いています: "あなたの提案に感謝します。私はBigInteger(r)またはBigInteger(1、r) OpenSSLでASN1Sequenceを解析すると、値が常に正になります(そして、私は同意しますが、DSAの仕様によれば、sは負ではないと期待しています)。 –

関連する問題