How to validate if a signed jar contains a timestamp?

前端 未结 4 769
忘了有多久
忘了有多久 2020-12-29 06:46

After a jar is signed and the -tsa option was used, how can I validate that the time stamp was included? I tried:

jarsigner -verify -verbose -certs myApp.jar         


        
相关标签:
4条回答
  • 2020-12-29 06:58

    mhaller provides great code (printDSAInfos). Helps me greatly in my work. However a couple of changes required. DEREncodable class is now changed to ASN1Encodable and getDERObject() method are changed to toASN1Primitive. So the code look like this

        ASN1Encodable dob = attribute.getAttrValues().getObjectAt(0);
        CMSSignedData signedData = new CMSSignedData(dob.toASN1Primitive().getEncoded());
    
    0 讨论(0)
  • 2020-12-29 07:21

    From https://blogs.oracle.com/mullan/entry/how_to_determine_if_a:

    You can use the jarsigner utility to determine if a signed JAR has been timestamped as follows:

    jarsigner -verify -verbose -certs signed.jar

    where signed.jar is the name of your signed JAR. If it is timestamped, the output will include lines of the following indicating the time it was signed:

    [entry was signed on 8/2/13 3:48 PM]

    If the JAR is not timestamped, the output will not include those lines.

    0 讨论(0)
  • 2020-12-29 07:23

    Just spent the last 2 hours looking for this issue and finally found a way to identify whether a jar file actually has time stamp information in the Signature Block file included. I could see the GlobalSign certifcate in the hexeditor of the /META-INF/FOO.DSA file, but I did not find any tool which would print out the information you need.

    You can rename the FOO.DSA file to foo.p7b to open it in the Windows CertMgr, but it does also not show any time stamp information. I also did not manage to use OpenSSL to verify the DSA file (It's PKCS#7 file format).

    So I came up with the following code which will show the Time Stamp SignerInfo and the date when the Timestamp was created. I hope it is a good start for you. You need bcprov-jdk16-144.jar, bctsp-jdk16-144.jar and bcmail-jdk16-144.jar in the classpath. Get them from Bouncycastle

    package de.mhaller.bouncycastle;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.Security;
    import java.util.Collection;
    import java.util.jar.JarEntry;
    import java.util.jar.JarInputStream;
    
    import org.bouncycastle.asn1.DEREncodable;
    import org.bouncycastle.asn1.cms.Attribute;
    import org.bouncycastle.asn1.cms.AttributeTable;
    import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
    import org.bouncycastle.cms.CMSException;
    import org.bouncycastle.cms.CMSSignedData;
    import org.bouncycastle.cms.SignerId;
    import org.bouncycastle.cms.SignerInformation;
    import org.bouncycastle.cms.SignerInformationStore;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.tsp.TSPException;
    import org.bouncycastle.tsp.TimeStampToken;
    import org.bouncycastle.tsp.TimeStampTokenInfo;
    
    public class VerifyTimestampSignature {
    
        private static boolean found;
    
        public static void main(String[] args) throws Exception {
            if (args == null || args.length != 1) {
                System.out.println("usage: java " + VerifyTimestampSignature.class.getName()
                        + " [jar-file|dsa-file]");
                return;
            }
    
            BouncyCastleProvider provider = new BouncyCastleProvider();
            Security.addProvider(provider);
    
            String filename = args[0];
    
            if (filename.toLowerCase().endsWith(".dsa")) {
                InputStream dsa = new FileInputStream(filename);
                printDSAInfos(filename, dsa);
                return;
            }
    
            if (filename.toLowerCase().endsWith(".jar")) {
                InputStream jar = new FileInputStream(filename);
                JarInputStream jarInputStream = new JarInputStream(jar);
                JarEntry nextJarEntry;
                do {
                    nextJarEntry = jarInputStream.getNextJarEntry();
                    if (nextJarEntry == null) {
                        break;
                    }
                    if (nextJarEntry.getName().toLowerCase().endsWith(".dsa")) {
                        printDSAInfos(nextJarEntry.getName(), jarInputStream);
                    }
                } while (nextJarEntry != null);
            }
    
            if (!found) {
                System.out.println("No certificate with time stamp information found in " + filename);
            } else {
                System.out.println("Found at least one time stamp info");
                System.out.println("Note: But it was NOT verified for validity!");
            }
        }
    
        private static void printDSAInfos(String file, InputStream dsa) throws CMSException,
                IOException, TSPException {
            System.out.println("Retrieving time stamp token from: " + file);
            CMSSignedData signature = new CMSSignedData(dsa);
            SignerInformationStore store = signature.getSignerInfos();
            Collection<?> signers = store.getSigners();
            for (Object object : signers) {
                SignerInformation signerInform = (SignerInformation) object;
                AttributeTable attrs = signerInform.getUnsignedAttributes();
                if (attrs == null) {
                    System.err
                            .println("Signer Information does not contain any unsigned attributes. A signed jar file with Timestamp information should contain unsigned attributes.");
                    continue;
                }
                Attribute attribute = attrs.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
                DEREncodable dob = attribute.getAttrValues().getObjectAt(0);
                CMSSignedData signedData = new CMSSignedData(dob.getDERObject().getEncoded());
                TimeStampToken tst = new TimeStampToken(signedData);
    
                SignerId signerId = tst.getSID();
                System.out.println("Signer: " + signerId.toString());
    
                TimeStampTokenInfo tstInfo = tst.getTimeStampInfo();
                System.out.println("Timestamp generated: " + tstInfo.getGenTime());
                found = true;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-29 07:24

    Java's keytool can confirm whether a signed JAR is timestamped, and can also display the TSA's certificate:

    $ keytool -printcert -jarfile myApp.jar
    
    ...
    
    Timestamp:
    
    Owner: CN=GeoTrust Timestamping Signer 1, O=GeoTrust Inc, C=US
    Issuer: CN=Thawte Timestamping CA, OU=Thawte Certification, O=Thawte, L=Durbanville, ST=Western Cape, C=ZA
    Serial number: 5e8d2daca44665546bb587978191a8bf
    Valid from: Wed Oct 31 00:00:00 GMT 2007 until: Mon Oct 30 23:59:59 GMT 2017
    Certificate fingerprints:
         MD5:  E5:30:07:8E:91:8D:A0:6C:18:6D:91:2A:B6:D2:3A:56
         SHA1: 22:3C:DA:27:07:96:73:81:6B:60:8A:1B:8C:B0:AB:02:30:10:7F:CC
         SHA256: D7:B8:44:BD:39:5A:17:36:02:39:51:C6:4D:6C:81:65:45:93:AD:29:1D:DC:E4:6C:8D:79:B6:65:DF:31:0C:F6
         Signature algorithm name: SHA1withRSA
         Version: 3
    
    ...
    
    0 讨论(0)
提交回复
热议问题