Java Cryptography/Security Error

88 views Asked by At

I have some code below, which should create a hash of a message using SHA1, print the hash, encrypt the message using a RSA algorithm, print out the encrypted message, then decrypt the message and print the hash again. The fist and third print messages should match as they are both the unencrypted hash of the original message but in my code they do not - can anybody tell me why? Thanks. My code is as follows:

    String          input = "input message test";
    MessageDigest   hash = MessageDigest.getInstance("SHA1");

    hash.update(Utils.toByteArray(input));

    System.out.println("digest : " +hash.digest());

    Cipher           cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    SecureRandom     random = new SecureRandom();

    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");

    generator.initialize(512, random);

    KeyPair          pair = generator.generateKeyPair();
    Key              pubKey = pair.getPublic();
    Key              privKey = pair.getPrivate();

    cipher.init(Cipher.ENCRYPT_MODE, privKey);

    byte[] ciphertext = cipher.doFinal(hash.digest());

    System.out.println("cipher: " + ciphertext);

    cipher.init(Cipher.DECRYPT_MODE, pubKey);

    byte[] plaintext = cipher.doFinal(ciphertext);

    System.out.println("plaintext : " + plaintext);

Update: I already have this, I just removed it as it was in a second file. My method is:

    public static String toHex(byte[] data, int length) {
    StringBuffer buf = new StringBuffer();

    for (int i = 0; i != length; i++) {
        int v = data[i] & 0xff;

        buf.append(digits.charAt(v >> 4));
        buf.append(digits.charAt(v & 0xf));
    }

    return buf.toString();
}

But this returns:

digest : b2cad21e87dbd57f1a1928e4013b56fb553bb82a
cipher: 502cffa545bda39f677b72f677f1a6a4308a329747a8f4de9b0d1ffd83fcec10c5b41a218201e204c7949b45a8119eb42e6ab5dc0c97f97b6d59600632d2b2ad
plaintext : da39a3ee5e6b4b0d3255bfef95601890afd80709
1

There are 1 answers

6
nitishagar On BEST ANSWER

The Hash digest need to be done just once (see the doc):

System.out.println("digest : " + hash.digest());   //1
byte[] ciphertext = cipher.doFinal(hash.digest()); //2

Calling hash.digest() once creates the digest and then resets the hash object. Which is why you get different output.

Below is the change which I made:

 byte[] inputHash = hash.digest();
 System.out.println("digest : " + bytesToHex(inputHash));
 byte[] ciphertext = cipher.doFinal(inputHash);

Here is the output which I get:

digest    : 4b03b72ccc3b238e3df3c0a9dcb8d03fd6417848
plaintext : 4b03b72ccc3b238e3df3c0a9dcb8d03fd6417848

You can use any byte array to hex converted. Below is a snippet which you can use:

public static String bytesToHex(byte[] hash) {
    StringBuffer hexString = new StringBuffer();

    for (int i = 0; i < hash.length; i++) {
      String hex = Integer.toHexString(0xff & hash[i]);
      if(hex.length() == 1) hexString.append('0');
      hexString.append(hex);
    }

    return hexString.toString();
  }