我尝试使用私钥对邮件摘要进行签名以生成签名,然后使用公钥验证签名以获取邮件摘要。我想与这两个消息摘要进行比较,但我得到一个关于“java.security.SignatureException:签名长度不正确:得到250但是期待128”的错误。
当我试图打印出Arrays.toString(data2)时,它全部为0。 我还尝试按照链接:Verify the Signature
public void firstDigitalSignature() throws IOException, NoSuchAlgorithmException, Throwable
{
//*Generate Message Digest1*
byte[] buffer=null;
buffer = new byte[(int) inputFile1.length()];
FileInputStream fis = new FileInputStream(inputFile1);
fis.read(buffer);
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(buffer);
digestBytes = messageDigest.digest();
//convert the byte to hex format method 2
StringBuffer hexString = new StringBuffer();
for(int i=0;i<digestBytes.length;i++){
hexString.append(Integer.toHexString(0xFF & digestBytes[i]));
}
System.out.println("Message Digest-1: "+hexString.toString());
//*Using private key to encrypt the image-Digital signauture1 *
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(digestBytes);
encryptmd= signature.sign();
StringBuffer hexString2 = new StringBuffer();
for(int i=0;i<encryptmd.length;i++){
hexString2.append(Integer.toHexString(0xFF & encryptmd[i]));
x=hexString2.toString();
File file = new File("c://Directroy111");
if (!file.exists()) {
if (file.mkdir()) {
System.out.println("Doctor is created!");
} else {
System.out.println("Failed to create Doctor!");
}
}
BufferedWriter out = new BufferedWriter(
new FileWriter("C:\\Directroy111\\Digital Signature Doctor.txt"));
out.write(x);
out.close();
this.copyImageFiles(sourceFile, destinationDir);
}
System.out.println("Message Digest Encrypted-1: "+hexString2.toString()+"\n");
}
public void firstVerify() throws IOException, NoSuchAlgorithmException, Throwable
{
//Generate Message Digest1 - Decrypt
String verifyfile= "c:\\Directroy111\\2.jpg";
File decryptfile= new File(verifyfile);
byte[] buffer2=null;
buffer2 = new byte[(int) decryptfile.length()]; //array type is integer, thats why we use int here
FileInputStream fis2 = new FileInputStream(decryptfile);
fis2.read(buffer2);
MessageDigest messageDigest2 = MessageDigest.getInstance("SHA-256");
messageDigest2.update(buffer2);
byte[] digestBytes2 = messageDigest2.digest();
StringBuffer hexString22 = new StringBuffer();
for(int i=0;i<digestBytes2.length;i++){
hexString22.append(Integer.toHexString(0xFF & digestBytes2[i]));
}
System.out.println("Message Digest(Hash)-1(Decryption): "+hexString22.toString()); //System.out.println(hexString);
//*******Decypt*************//
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
//FileReader read= new FileReader("C:\\TEMP1\\Doctor\\Digital Signature Doctor.txt");
FileInputStream br2 = new FileInputStream("C:\\Directroy111\\Digital Signature Doctor.txt");
//BufferedInputStream bis=new BufferedInputStream(br2);
//BufferedReader br = new BufferedReader(new FileReader(br2));
byte[] data2=new byte[br2.available()];
System.out.println(Arrays.toString(data2));
br2.read(data2);
br2.close();
FileInputStream datafis=new FileInputStream("C:\\Directroy111\\Digital Signature Doctor.txt");
BufferedInputStream bufin=new BufferedInputStream(datafis);
byte[] buffer=new byte[1024];
int len;
while(bufin.available()!=0){
len=bufin.read(buffer);
signature.update(buffer,0,len);
};
bufin.close();
System.out.println("111111");
boolean decryptmd2= signature.verify(data2);
System.out.println("signature verifies: " + decryptmd2);
if(decryptmd2==false){
str = String.valueOf(decryptmd2);
System.out.println("Message Digest-1(Decryption): "+str);
}else{
System.out.println("1111");
}
//**Verify*
if(str.equals(hexString22.toString())){
System.out.println("Digital Signature-1 was not modified"+"\n");
}else{
System.out.println("ERROR!!! Digital Signature-1 was modified"+"\n");
}
}
答案 0 :(得分:0)
我在这里看到几个问题。首先,实际的签名代码也应包含在您的问题中。如果无法看到签名代码,则调试问题会更加困难。检查您的签名算法是否与验证算法(SHA256withRSA)相同。
接下来,如果您使用的是SHA256withRSA
算法,则无需先计算消息摘要。算法将为您计算并签署摘要。您只需传入要签名的整个文件。
在验证步骤中,您使用与您所说的签名相同的文件更新Signature对象。这两个文件都是Digital Signature Doctor.txt
。您应该使用要签名的文件更新Signature对象,我相信您的示例是2.jpg
。然后,当您调用verify()
方法时,传入签名字节。
最后,您误解了verify()
的返回值。它返回一个布尔值。它不会返回消息摘要或原始消息。当您的代码执行String.valueOf(decryptmd2)
时,该值将为“false”或“true”。
我不确定您为什么要尝试比较消息摘要。假设您收到一条消息,其签名由与您信任的公钥对应的私钥签名。如果verify()
方法返回true,则可以确定:
这应该足以满足你的需要。
答案 1 :(得分:0)
回应gtrig的评论,这是一个显示签名创建和验证的完整示例:
import java.io.*;
import java.security.*;
public class RSASignatureExample {
private static int BUFSIZE = 8192;
private PrivateKey privateKey;
private PublicKey publicKey;
public RSASignatureExample() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
publicKey = kp.getPublic();
}
private static void processData(File f, Signature s) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f), BUFSIZE);
byte[] buf = new byte[BUFSIZE];
int numRead;
while ((numRead = bis.read(buf)) > 0) {
s.update(buf, 0, numRead);
}
bis.close();
}
public byte[] sign(File fileToSign) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
processData(fileToSign, signature);
return signature.sign();
}
public boolean verify(File fileToVerify, byte[] signatureBytes) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
processData(fileToVerify, signature);
return signature.verify(signatureBytes);
}
public static void main(String[] args) throws Exception {
RSASignatureExample example = new RSASignatureExample();
File tempFile = File.createTempFile("rsa", null);
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write("Hello World".getBytes("UTF-8"));
fos.close();
// Sign the file
byte [] signatureBytes = example.sign(tempFile);
// Verify the signature
boolean isVerified = example.verify(tempFile, signatureBytes);
System.out.printf("Signature verified ?: %b", isVerified);
}
}