0

我尝试使用私钥对消息摘要进行签名以生成签名,然后使用公钥验证签名以获取消息摘要。我想与这两个消息摘要进行比较,但我收到一个关于“java.security.SignatureException:签名长度不正确:得到 250 但预期为 128”的错误。

当我尝试打印出 Arrays.toString(data2) 时,它全部为 0。我还尝试点击链接:验证签名

 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");
      }

} 
4

2 回答 2

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);
    }
}
于 2013-10-02T16:17:51.687 回答
0

我在这里看到几个问题。首先,实际的签名代码也应该包含在您的问题中。如果无法看到签名代码,则更难以调试问题。检查您的签名算法是否与您的验证算法 (SHA256withRSA) 相同。

接下来,如果您使用该SHA256withRSA算法,则无需先计算消息摘要。该算法将为您计算并签署摘要。您只需传入要签名的整个文件。

在您的验证步骤中,您正在使用与您所说的签名相同的文件更新 Signature 对象。两个文件都是Digital Signature Doctor.txt. 您应该使用要签名的文件更新 Signature 对象,我相信您的示例是2.jpg. 然后,当您调用该verify()方法时,传入签名字节。

最后,您误解了verify(). 它返回一个布尔值。它不返回消息摘要或原始消息。当您的代码执行此操作String.valueOf(decryptmd2)时,该值将是“false”或“true”。

我不确定您为什么要尝试比较消息摘要。假设您收到一条消息,其签名由与您信任的公钥相对应的私钥签名。如果该verify()方法返回 true,您可以确定:

  • 该消息由该人签名
  • 您收到的消息与已签名的消息相同

这应该足以满足您的需要。

于 2013-10-02T02:27:40.053 回答