0

I currently have been assigned the task to verify digital signatures generated using openssl , The files I recieve are basically two files one being the xml data and the other being the corresponding signature of that xml data , The key used to sign the data is RSA with an algorithm of SHA1 , the openssl command used is : openssl smime -sign -binary -in {datafile} -out {signaturefile} -outform der -inkey {privatekey} -signer {publickey} where {datafile} = The input file, in either CSV or XML format, containing the data to be signed {signaturefile} = The output file containing the digital signature only in PKCS#7 format, same filename as datafile but with .sig extension {privatekey} = The private key part of the key to be used for signing {publickey} = The public key part of the key to be used for signing , I have written a class to verify these files but the result always returns a false meaning the verification has failed. below is the code i have written: Could someone please help me on how to verify openssl detached signatures using java?

public PublicKey pubTest(String path) throws Exception
 {
     FileInputStream fin = new FileInputStream(path);
     CertificateFactory f = CertificateFactory.getInstance("X.509");
     X509Certificate certificate = (X509Certificate)f.generateCertificate(fin);
     PublicKey pk = certificate.getPublicKey();
     System.out.println(pk);
     return pk;
 }
 public byte[] signature(String sigPath) throws Exception
 {
     FileInputStream sigfis = new FileInputStream(sigPath);
     byte[] sigToVerify = new byte[sigfis.available()]; 
     sigfis.read(sigToVerify);
     sigfis.close();
     System.out.println(sigToVerify.length);

     return sigToVerify ;
 }

 public boolean verification(PublicKey pubKey , String dataPath , byte[] sigToVerify ) throws Exception, NoSuchProviderException ,SignatureException
{

    Signature sig = Signature.getInstance("SHA1withRSA");
    sig.initVerify(pubKey);
    FileInputStream datafis = new FileInputStream(dataPath);
    BufferedInputStream bufin = new BufferedInputStream(datafis);
    byte[] buffer = new byte[1024];
    int len;
    while (bufin.available() != 0)
    {
        len = bufin.read(buffer);
      sig.update(buffer, 0, len);
    }
    System.out.println(buffer.length);
    bufin.close();
    boolean verifies = sig.verify(sigToVerify);
    System.out.println("signature verifies: " + verifies);
    return verifies ;
}
Sparda
  • 9
  • 4
  • Have you tried to use hardcoded values as the input to see if the code provides the expected output without any dynamic interaction? Try to copy the values within the verification variables to something like Notepad++ and enable the option to see all characters, you might see some funny element that wasn't supposed to be there (just a wild guess). Have you tried to decompile/check the source for this method here `sig.verify(sigToVerify)` to see how it works? – the_marcelo_r Mar 18 '14 at 13:33
  • how do you get the source of the signature method java uses ? I was able to verify the signatures using openssl but that is a crude way to actually go about doing the verification, when I looked at the signature in der format through openssl, the bytes of the signature value doesn't add up to 256. – Sparda Mar 18 '14 at 14:32
  • the signature file has more than just the signature embedded in it because normally the signature should be a few lines but this file looks like it has more to it so I tried using an offset to get the last 256 bytes since thats where the signature lies but I still get the false return – Sparda Mar 18 '14 at 14:36
  • So, a quick dirty way to do it would be through the command line (well, you can invoke CLI operations through Java code... just sayin'). About the source-code question, you have to find the jar file where this class is stored (http://cua.li/Alain-Bearez.html), once you find it, you can use a decompiler to take a look: http://jd.benow.ca/ – the_marcelo_r Mar 18 '14 at 14:39
  • Currently what I did was I wrote code to call the verification command as a system call and I used if statements to read the output and determine if the signature is successful or not and then I used the code as a lib in my Talend job but as you said it is a dirty way , do I have to download the decompiler? – Sparda Mar 18 '14 at 14:42

1 Answers1

0

Late now but if anyone else comes across it:

openssl smime -sign by default generates an "indirect" detached signature, that is, one which does not contain the data in encapContentInfo but does use signedAttrs. See https://www.ietf.org/rfc/rfc3369.txt 5.3 through 5.6; you need to compare a hash of the data to the message-digest attribute in the signedAttrs, and then verify the signature against the signedAttrs (with the IMPLICIT tagging reverted to basic).

Standard Java crypto does not (currently?) do CMS/PKCS#7 but BouncyCastle does if that's an option. Consider Correct way to sign and verify signature using bouncycastle .

Community
  • 1
  • 1
dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70