'Difference result by using sign and verify for signature

I tried to use private key to sign the message digest to generate the signature, and then use public key to verify the signature to get message digest. I want to compare with this two message digests, but i got a error about "java.security.SignatureException: Signature length not correct: got 250 but was expecting 128".

When i tried to print out Arrays.toString(data2), its all 0. I also tried to follow the link: 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");
      }

} 


Solution 1:[1]

I see a couple issues here. First, the actual signing code should be included with your question as well. Without being able to see the signing code, it's more difficult to debug the problem. Check if your signing algorithm is the same as your verification algorithm (SHA256withRSA).

Next, if you're using the SHA256withRSA algorithm, you don't need to calculate a message digest first. The algorithm will calculate it for you and sign the digest. You just pass in the entire file to be signed.

In your verification step, you are updating the Signature object with the same file that you are saying is the signature. Both files are Digital Signature Doctor.txt. You should update the Signature object with the file to be signed, which I believe from your example is 2.jpg. Then when you call the verify() method, pass in the signature bytes.

Finally, you are misinterpreting the return value of verify(). It returns a boolean. It does not return the message digest or the original message. When your code does String.valueOf(decryptmd2), the value will either be "false" or "true".

I'm not sure why you are trying to compare the message digests. Let's say you are sent a message with a signature signed by a private key corresponding to a public key that you trust. IF the verify() method returns true, you can be sure that:

  • the message was signed by that person
  • the message you received is identical to the message that was signed

That should be sufficient for what you need.

Solution 2:[2]

Echoing gtrig's comments, here is a complete example showing signature creation and verification:

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 gtrig
Solution 2 President James K. Polk