For educational purposes, I would like to be able to first create a Hash for a String and then to create RSA Digital Signature from that Hash so that the result is the same as when using SHA256withRSA in one go. This way I want to confirm that I fully understand all the steps that are actually being done automatically for us when we call SHA256withRSA.
I also have one additional question. Is Digital Signature done on Hash or on Base64 Encoded Hash?
Below is the code that I am currently using and here is the output of the code which shows that these two approaches produce different signatures which means that I am missing soma manual steps.
AUTOMATICALLY SIGN & VERIFY
SIGNATURE = Hj6a86sR2cJoQFolbxj0blk2I9CAdTdx6WOles5t/pyUyJwa9rp2/SRx2wyXWgc6GsvoZYGLUedeJ2Lklm5hYgT/TtNBATk5eChgfkJMz3NBIRPrsl7ZPG7Wvo4VmHsPpoZZ8PdRk8qY9RLou86OyIqRcX62isuV+e/0deHJ+yTZz4vqA3y+PE4yRFp96A8sKw5VlDnByn7bsxM/QOS+sQWTsETzU9s4YSRfKNq1Urn8/VDoel7n0ORjR918P+0kwE+G77bAOI70yQZorvmbgrMLSBJeVzkKzM/YECLWyrJsqdjfp86FkA9MPGB1V6rO8q8m5GhNoJOmNhC7Ek95Bw==
MANUALLY SIGN & VERIFY
HASH = lDlahWCWx2b5TYUji52uPeReSW7vbro2wXuRsPKmOdA=
SIGNATURE = gsxw7UQpqni5HyPAw8wI2pvepbrDzizkOvO0hab1+7vi4EaYJi3n4lvnkBTOU5LXQKLZGzJcug0mL2pL/PVh8lrvzZ/F9CxULLxKpayrNkvL9yEWMvcfcku9Go5EGrxSzD7VYvkwOzHvGe4GgUGD1JOjvzXBAfJRT8h/wnZi9IPA9n31/tWI2eFw17Js/gymElycp7pjrpEhUNe/IVTP9HVfRQfAxEDAPW8GY/WFdxbD3Jk05LKvpTxua4jzCX9wJh/s8aiT9OvEXh3/zt06JSEpfgf+CpkOFJupmRhsgqebPfVQEo24ctw1DnipKkL771mm30bFcm/FF1reXuOqqQ==
public class Main {
//====================================================================================
// MAIN
//====================================================================================
public static void main(String[] args) throws Exception {
//CREATE DATA
String dataString = "Data to be encrypted";
byte[] dataBytes = dataString.getBytes();
//CREATE KEYS
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
//AUTOMATICALLY SIGN & VERIFY
System.out.println("\nAUTOMATICALLY SIGN & VERIFY");
byte[] automaticSignatureBytes = AutomaticHash.sign ("SHA256withRSA", privateKey, dataBytes);
//MANUALLY SIGN & VERIFY
System.out.println("\nMANUALLY SIGN & VERIFY");
byte[] manualHashBytes = ManualHash.hash ("SHA-256", dataBytes);
byte[] manualSignatureBytes = ManualHash.sign ("NONEwithRSA", privateKey, manualHashBytes);
}
}
public class AutomaticHash {
//====================================================================================
// AUTOMATICALLY SIGN
//====================================================================================
public static byte[] sign(String algorithms, PrivateKey privateKey, byte[] dataBytes) throws Exception {
//CREATE SIGNATURE (use Hash first)
Signature signature = Signature.getInstance(algorithms);
signature.initSign(privateKey);
signature.update(dataBytes);
byte[] signatureBytes = signature.sign();
//ENCODE SIGNATURE
byte[] signatureEncodedBytes = Base64.getEncoder().encode(signatureBytes);
String signatureEncodedString = new String(signatureEncodedBytes);
//DISPLAY ENCODED SIGNATURE
System.out.println("SIGNATURE = " + signatureEncodedString);
//RETURN SIGNATURE
return signatureBytes;
}
}
public class ManualHash {
//====================================================================================
// MANUALLY HASH
//====================================================================================
public static byte[] hash(String algorithm, byte[] dataBytes) throws Exception {
//CREATE HASH
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte[] hashBytes = digest.digest(dataBytes);
//ENCODE HASH
byte[] hashEncoded = Base64.getEncoder().encode(hashBytes);
String hashEncodedString = new String(hashEncoded);
//DISPLAY ENCODED HASH
System.out.println("HASH = " + hashEncodedString);
//RETURN HASH
return hashBytes;
}
//====================================================================================
// MANUALLY SIGN
//====================================================================================
public static byte[] sign(String algorithm, PrivateKey privateKey, byte[] hashBytes) throws Exception {
//SIGN HASH
Signature signature = Signature.getInstance(algorithm);
signature.initSign(privateKey);
signature.update(hashBytes);
byte[] signatureBytes = signature.sign();
//ENCODE SIGNATURE
byte[] signatureEncodedBytes = Base64.getEncoder().encode(signatureBytes);
String signatureEncodedString = new String(signatureEncodedBytes);
//DISPLAY ENCODED HASH & SIGNATURE
System.out.println("SIGNATURE = " + signatureEncodedString);
//RETURN SIGNATURE
return signatureBytes;
}
}