2017-07-07 34 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,但尚未找到真正的答案。

相关的另一个问题: 我看到有由Signature类提供了另一种initSign方法: initSign(专用密钥专用密钥,SecureRandom的随机) 为什么我会想要插入随机的源/种子创建签名是什么时候?接收方应该如何验证该签名,然后如果随机种子未知?

感谢您的宝贵意见! 马克

回答

2

specification of the algorithm的解释它:

DSA和ECDSA的

一个特征是,它们需要生产,对于每个 签名生成,新鲜的随机值(以下称作为 K)。为了有效的安全性,必须从一组模块整数中随机地选择k,并使用加密的 安全过程。在这个过程中,即使是轻微的偏差,也可能会被攻击成签名方案 。

所以你看到的是完全正常的。当然,这些算法的设计者可以让接收者验证签名,否则它将毫无意义。这就是你的测试应该验证的内容。

+0

啊哈,好的。感谢RFC的提示。我无法想象ECDSA中的随机密钥是否可以让对方验证,但我想我只需要依赖它并阅读RFC以了解如何。无论如何,现在我知道结果非常正常。 – Marc

相关问题