问题描述
我正在学习 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。