2017-07-07 8 views
0

SHAwithECDSAを使用して変更されない秘密鍵で変更されないバイトストリームに署名しようとしています。コードを実行する頻度にかかわらず、同じ結果が得られるはずです。 しかし、すべての実行で結果の出力が変化するので説明できないランダム性が発生します。ここでSHAwithECDSAを使用したJava Signature.sign()は複数の実行で異なる結果を生成します

は、(最小限の例)私は何をすべきかです:

public byte[] sign() { 
    Signature ecdsa = Signature.getInstance("SHA256withECDSA", "SunEC"); 

    // This is a hexadecimal byte sequence I need to sign 
    String dataToBeSigned = "808112B43A3A381D1797BBBBBB973B99" + 
         "9737B93397AA2917B1B0B737B734B1B0" + 
         "B616B2BC3497A1AB43A3A381D1797BBB" + 
         "BBB973B999737B933979918181897981" + 
         "A17BC36B63239B4B396B6B7B93291B2B" + 
         "1B239B096B9B430991A9B22062349443" + 
         "1025687474703A2F2F7777772E77332E" + 
         "6F72672F54522F63616E6F6E6963616C" + 
         "2D6578692F4852D0E8E8E0745E5EEEEE" + 
         "EE5CEE665CDEE4CE5E646060625E6068" + 
         "5EF0DAD8CADCC646E6D0C2646A6C841A" + 
         "36BC07A00CB7DCAD662F3088A60A3D6A" + 
         "99431F81C122C2E9F1678EF531E95523" + 
         "70"; 

    String hexPrivKey = "B9134963F51C4414738435057F97BBF1" + 
         "010CABCB8DBDE9C5D48138396AA94B9D"; 
    byte[] privKey = DatatypeConverter.parseHexBinary(hexPrivKey); 

    ecdsa.initSign(getPrivateKey(privKey)); 
    ecdsa.update(dataToBeSigned); 
    byte[] signature = ecdsa.sign(); 

    System.out.println("Signature: " + DatatypeConverter.printHexBinary(signature)); 
} 

public ECPrivateKey getPrivateKey(byte[] privateKeyBytes) { 
    try { 
     AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); 
     parameters.init(new ECGenParameterSpec("secp256r1")); 

     ECParameterSpec ecParameterSpec = parameters.getParameterSpec(ECParameterSpec.class); 
     ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(new BigInteger(privateKeyBytes), ecParameterSpec); 

     ECPrivateKey privateKey = (ECPrivateKey) KeyFactory.getInstance("EC").generatePrivate(ecPrivateKeySpec); 

     return privateKey; 
    } catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidParameterSpecException e) { 
     System.out.println(e.getClass().getSimpleName() + " occurred when trying to get private key from raw bytes", e); 
     return null; 
    } 
} 

あなたは、これは同じシグネチャ出力で、私はこのコードを実行するたびにもたらさない理由の任意のヒントを持っていますか? 同様の質問が提起されたhereしかし、実際の答えはまだ見つかりませんでした。

それに関連するもう一つの問題: Iは、署名クラスによって提供される別するinitSign方法があることを確認: するinitSign(のPrivateKeyのPrivateKey、のSecureRandomランダム) なぜ署名を作成するときにランダムソース/シードを入れたいですか?受信側は、ランダムな種が知られていない場合、どのようにその署名を検証することになっていますか?

ありがとうございました! マルク

答えて

2

specification of the algorithmはそれを説明する:DSAとECDSAの

一つの特徴は、それらが 各署名生成のために、生成する必要があることであり、新鮮なランダム値(以下、Kなど と命名します)。効果的なセキュリティのためには、暗号化 セキュアプロセスを使用して、kをランダムに選択し、 を一式の整数から一様に選択する必要があります。そのプロセスのわずかな偏りでさえ、 を署名方式に対する攻撃に変えることができます。

あなたが見ているのは完全に正常です。もちろん、アルゴリズムの設計者は、受信者が署名を検証できるようにしました。そうでなければ、無意味です。それがあなたのテストで検証すべきものです。

+0

Aha、OK。 RFCへのヒントをありがとう。私はちょうどECDSA内のランダムキーがどのように相手側が検証できるかを想像できませんでしたが、私はそれに頼り、RFCを読んで理解する必要があると思います。とにかく、私は結果が完全に正常であることを今知っています。 – Marc

関連する問題