signature.verify 是返回 false

问题描述

我正在学习 Java 签名,我从 Java 文档中获取代码,但它似乎不起作用。谁能告诉我我做错了什么。任何帮助将不胜感激。

第一部分是创建签名,第二部分是检查签名

import java.io.*;
import java.security.*;
import java.security.spec.*;

public class SignatureVerification {
   public static void main(String args[]) throws Exception{
      
      KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA","SUN");
      
      SecureRandom random = SecureRandom.getInstance("SHA1PRNG","SUN");
        keyGen.initialize(1024,random);
      //Generate the pair of keys
      KeyPair pair = keyGen.generateKeyPair();
      PrivateKey priv = pair.getPrivate();
      PublicKey pub = pair.getPublic();


      //Creating a Signature object
      Signature dsa = Signature.getInstance("SHA256withDSA","SUN");
      
      dsa.initSign(priv);
      
      FileInputStream fis = new FileInputStream("Cust.ser");
        BufferedInputStream bufin = new BufferedInputStream(fis);
        byte[] buffer = new byte[1024];
        int len;
        while ((len = bufin.read(buffer)) >= 0) {
            dsa.update(buffer,len);
        };
        bufin.close();
      
      byte[] realSig = dsa.sign();
      
        
        byte[] key = pub.getEncoded();


        // /////////////////////////////////////////////////////////////////

            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(key);
            KeyFactory keyFactory = KeyFactory.getInstance("DSA","SUN");
            PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);


            Signature sig = Signature.getInstance("SHA256withDSA","SUN");
            sig.initVerify(pubKey);

            FileInputStream datafis = new FileInputStream("Cust.ser");
            BufferedInputStream bufin2 = new BufferedInputStream(datafis);

            byte[] buffer2 = new byte[1024];
            int len2;
            while (bufin2.available() != 0) {
                len2 = bufin2.read(buffer);
                sig.update(buffer2,len2);
            };

            bufin2.close();

            System.out.println(realSig);
            System.out.println(sig);


            boolean verifies = sig.verify(realSig);

            System.out.println("signature verifies: " + verifies);


   }
}

cmd输出如下

java SignatureVerification
[B@5cad8086
Signature object: SHA256withDSA<initialized for verifying>
signature verifies: false

解决方法

当您剪切和粘贴代码时,您没有正确编辑。它仍然读取数据到buffer,但它不使用该数据,而是使用buffer2(全零):

            byte[] buffer2 = new byte[1024];
            int len2;
            while (bufin2.available() != 0) {
                len2 = bufin2.read(buffer);
                sig.update(buffer2,len2);
            };

此外,一般情况下,即使文件中有更多数据,available() 也可以返回 0,因此这是不可靠的;您在签名部分使用的方法,while( (len=inputstream.read(buffer))>=0 ) 好多了。

如果您不知道,1024 位 DSA 尽管实际上尚未损坏(尚未),但不再被认为是安全的,并且不再允许在需要安全性的情况下使用,尤其是不能与 SHA-256 结合使用。自 2014 年 j8 以来的 Java 加密支持 2048 位和 3072 位 DSA,根据 FIPS 186-3 使用 SHA-2。