I am using openssl to create a signature for a file contents and use openssl to verify the contents using the signature file. The public key is from an x509 cert. All works great.
I need to verify a file contents using Java. So I have written a sample Java application and it returns false and should return true. I use the same artifacts as I did for the openssl. I think the saved binary file of the signature may need some conversion for Java but thats my guess? The computed SHA1 for the message digest by openssl and by Java are the same. So thats a good start. The Java Application is enclosed below. Basically 1 open the x509 and extract the public key. 2 read the contents of the file and make a SHA1 message digest 3 read the binary signature file 4 check signature against message digest using public key. I searched the forum and have not really found anything definitive for this. I use int rc= RSA_sign(NID_sha1, md, 20, sigret, &siglen, rsapriv); /** * Write out Digital Signature File ***/ fp = fopen("signature.rsasigned,"wb"); fwrite(sigret, 1, siglen, fp); fclose(fp) to create the signature file. /***************************************************** This will read the X509 certificate RSApublic.x509.1 created by the openssl commands and print out information about it. javac sample.java java sample *****************************************************/ import java.util.Date; import java.io.*; import java.security.cert.X509Certificate; import java.security.*; import java.security.cert.*; public class sample { public static PublicKey x509GetPublic(String filename){ try{ File f = new File(filename); FileInputStream fis = new FileInputStream(f); BufferedInputStream ksbufin = new BufferedInputStream(fis); X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(ksbufin); if (certificate!= null){ System.out.println("yes we can open it \n"); } Principal p= certificate.getIssuerDN(); System.out.println("DN: "+p.getName()+"\n"); Date d= certificate.getNotAfter(); if (d!=null) System.out.println("got Not After Date \n"+d.toString()); PublicKey pubkey= certificate.getPublicKey(); if (pubkey!=null) System.out.println("\n got public key \n"); System.out.println("public key format is "+pubkey.getFormat()); return pubkey; }catch (Exception e){ e.printStackTrace(); } return null; } public static byte[] SHA1(String filename)throws Exception { MessageDigest md = MessageDigest.getInstance("SHA-1"); FileInputStream fis = new FileInputStream(filename); byte[] dataBytes = new byte[1024]; int nread = 0; while ((nread = fis.read(dataBytes)) != -1) { md.update(dataBytes, 0, nread); }; byte[] mdbytes = md.digest(); System.out.println("SHA1 Length is "+mdbytes.length); return mdbytes; } static void hexout(byte[] mdbytes){ StringBuffer sb = new StringBuffer(); for (int i = 0; i < mdbytes.length; i++) { sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); } System.out.println("Hex format : " + sb.toString()); } /**************************** The signature algorithm with SHA-* and the RSA encryption algorithm as defined in the OSI Interoperability Workshop, using the padding conventions described in PKCS #1. SHA1withRSA SHA256withRSA SHA384withRSA SHA512withRSA The ECDSA signature algorithms as defined in ANSI X9.62. Note:"ECDSA" is an ambiguous name for the "SHA1withECDSA" algorithm and should not be used. The formal name "SHA1withECDSA" should be used instead. NONEwithECDSA SHA1withECDSA SHA256withECDSA SHA384withECDSA SHA512withECDSA *****************************/ static public void checkSignature(PublicKey pubkey, byte[] mdbytes, byte[] sigToVerify){ try{ // Signature sig = Signature.getInstance("SHA256withRSA"); //, "SUN"); Signature sig = Signature.getInstance("SHA1withRSA"); //,"SUN"); sig.initVerify(pubkey); sig.update(mdbytes, 0, mdbytes.length); boolean verifies = sig.verify(sigToVerify); System.out.println("signature verifies: " + verifies); }catch (Exception e){ e.printStackTrace(); } } /** * @param args */ public static void main(final String[] args) { System.out.println("hello\n"); try{ /** * Get public key from X509 cert **/ PublicKey pubkey=x509GetPublic("RSApublic.x509.1"); /** * Make MessageDigest from file contents **/ byte[] mdbytes=SHA1("landscape.steg.jpg"); System.out.println("openssl says SHA1 is 9ceb5e5cbf223a2b9a3d349eead52383e4c9fef9 \n"); hexout(mdbytes); /** * Read Signature into bytes **/ FileInputStream sigfis = new FileInputStream("landscape.steg.jpg.rsasigned"); int len=sigfis.available(); System.out.println("Signature length is "+len); byte[] sigToVerify = new byte[len]; int n= sigfis.read(sigToVerify); System.out.println("read SIGNATURE BYTES "+n); sigfis.close(); /** * Check signature with public key, Message Digest of file and its signature **/ checkSignature( pubkey, mdbytes, sigToVerify); }catch (Exception e) { e.printStackTrace(); } } } The output is below. java sample hello yes we can open it DN: EMAILADDRESS=xx...@us.ibm.com, CN=R Redpath, OU=Sample Technology, O=MyCompany, L=RTP, ST=NC, C=US got Not After Date Mon Aug 29 08:52:51 EDT 2022 got public key public key format is X.509 SHA1 Length is 20 openssl says SHA1 is 9ceb5e5cbf223a2b9a3d349eead52383e4c9fef9 Hex format : 9ceb5e5cbf223a2b9a3d349eead52383e4c9fef9 Signature length is 128 read SIGNATURE BYTES 128 signature verifies: false -- View this message in context: http://old.nabble.com/openssl-RSA_sign%28%29--and-Java-verify-how-tp34621647p34621647.html Sent from the OpenSSL - User mailing list archive at Nabble.com. ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org