How do I get Message Digest from Signature?

When signing some data, first one computes the message digest, then encrypts the message digest with his private key to get the signature. So, if I have the public key, I should be able to take the signature and decrypt it, yielding the original message digest. Correct?

However, there doesn't seem to be any way to do this using standard JDK functionality (JDK1.3.1). The java.security.Signature object encapsulates the message digest computation and encryption into one operation, and encapsulates the signature verification into an operation; there doesn't seem to be a way to get at the message digest.

I downloaded the Cryptix library and used the Cipher class to try to decrypt the signature, but kept getting errors. The code and error are as follows. Thanks for any ideas on how to get this to work.

package misc;

import java.util.*;

import java.security.*;

import xjava.security.*;

import cryptix.provider.*;

public class SignatureTest {

public static void main(String[] args) {

try {

Security.addProvider(new Cryptix());

// create data to sign

byte[] data = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

// get message digest

MessageDigest md = MessageDigest.getInstance("SHA1");

byte[] digest = md.digest(data);

// generate keys

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

KeyPair keyPair = kpg.generateKeyPair();

PublicKey publicKey = keyPair.getPublic();

PrivateKey privateKey = keyPair.getPrivate();

// sign data

Signature s = Signature.getInstance("SHA1withRSA");

s.initSign(privateKey);

s.update(data);

byte[] signature = s.sign();

// decrypt the signature to get the message digest

Cipher c = Cipher.getInstance("RSA");

c.initDecrypt(publicKey);

byte[] decryptedSignature = c.crypt(signature);

// message digest obtained earlier should be the same as the decrypted signature

if (Arrays.equals(digest, decryptedSignature)) {

System.out.println("successful");

} else {

System.out.println("unsuccessful");

}

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

java.security.InvalidKeyException: RSA: Not an RSA private key

at cryptix.provider.rsa.RawRSACipher.engineInitDecrypt(RawRSACipher.java:233)

at xjava.security.Cipher.initDecrypt(Cipher.java:839)

at misc.SignatureTest.main(SignatureTest.java:35)

[2533 byte] By [danielboggs] at [2007-9-26 2:07:45]
# 1
Actually, I think Cipher might be used with secret keys (symmetric encryption) rather than public/private keys. So I was probably trying this the wrong way. But it would still be nice to know how to get the message digest from a signature.-daniel
danielboggs at 2007-6-29 8:55:27 > top of Java-index,Security,Cryptography...
# 2

I learned from someone how to do the decryption myself using BigInteger. The output shows that the decrypted signature is actually the message digest with some padding and other information prepended. See (quick and dirty) code and output below:

package misc;

import java.util.*;

import java.security.*;

import java.security.interfaces.*;

import java.security.spec.*;

import java.math.*;

public class SignatureTest {

public static void main(String[] args) {

try {

// create data to sign

byte[] data = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

// get message digest

MessageDigest md = MessageDigest.getInstance("SHA1");

byte[] digest = md.digest(data);

System.out.println("Computed digest:");

System.out.println(getHexString(digest));

System.out.println();

// generate keys

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

KeyPair keyPair = kpg.generateKeyPair();

PublicKey publicKey = keyPair.getPublic();

PrivateKey privateKey = keyPair.getPrivate();

// sign data

Signature s = Signature.getInstance("SHA1withRSA");

s.initSign(privateKey);

s.update(data);

byte[] signature = s.sign();

System.out.println("Signature:");

System.out.println(getHexString(signature));

System.out.println();

// decrypt the signature to get the message digest

BigInteger sig = new BigInteger(signature);

RSAPublicKey rsaPublicKey = (RSAPublicKey)publicKey;

BigInteger result = sig.modPow(rsaPublicKey.getPublicExponent(), rsaPublicKey.getModulus());

byte[] resultBytes = result.toByteArray();

System.out.println("Result of decryption:");

System.out.println(getHexString(resultBytes));

System.out.println();

} catch (Exception ex) {

ex.printStackTrace();

}

}

public static String getHexString(byte[] bytes) {

StringBuffer sb = new StringBuffer();

for (int i = 0; i < bytes.length; i++) {

sb.append(Integer.toHexString(new Byte(bytes[i]).intValue()));

sb.append(" ");

}

return sb.toString();

}

}

Output:

Computed digest:

ffffffe8 ffffff9a ffffffd5 ffffffa9 63 1c 3e fffffffd ffffffde ffffffd7 ffffffe3 ffffffec ffffffce 79 ffffffb4 ffffffd0 fffffffe ffffffdc ffffffe1 ffffffbf

Signature:

60 75 13 7c ffffffaf 77 6e ffffffc1 ffffffd2 4a 42 ffffffe8 45 47 20 4f ffffffbf 46 4 12 47 ffffffa9 1 ffffffe7 ffffffae 58 fffffff2 fffffffe 28 ffffffd1 25 32 49 ffffff9f ffffffe3 4 ffffffbf ffffffce 5d ffffffd9 67 70 ffffff99 ffffffbf ffffffdb 2f d ffffffb8 ffffffa4 6e ffffff9f 28 24 7d 71 50 38 ffffffe4 5f ffffffab fffffff5 ffffff93 54 4c ffffffe4 ffffff9a 11 23 66 49 ffffff8c ffffffc3 49 68 c ffffffa4 36 ffffff8f ffffffb3 57 a 58 ffffffb2 ffffffac 3e 55 ffffffe4 ffffff91 16 5e 7b ffffffe9 ffffffa6 50 ffffff9a fffffff5 22 7b ffffffd4 60 ffffffe2 fffffffe 24 ffffffa9 ffffff92 69 4b ffffffd9 44 ffffffb2 57 ffffff91 53 ffffffb9 7 fffffff7 ffffffa3 ffffffd5 61 ffffff81 ffffffb7 ffffff95 5 5b 30 7f 55 71

Result of decryption:

1 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 0 30 21 30 9 6 5 2b e 3 2 1a 5 0 4 14 ffffffe8 ffffff9a ffffffd5 ffffffa9 63 1c 3e fffffffd ffffffde ffffffd7 ffffffe3 ffffffec ffffffce 79 ffffffb4 ffffffd0 fffffffe ffffffdc ffffffe1 ffffffbf

danielboggs at 2007-6-29 8:55:27 > top of Java-index,Security,Cryptography...