2009-10-30 12 views
18

Nachdem ein Jar signiert wurde und die Option -tsa verwendet wurde, wie kann ich bestätigen, dass der Zeitstempel enthalten war? Ich habe versucht:Wie validiere ich, ob ein signiertes Jar einen Timestamp enthält?

jarsigner -verify -verbose -certs myApp.jar 

Aber die Ausgabe gibt nichts über den Zeitstempel. Ich frage, denn selbst wenn ich einen Tippfehler im URL-Pfad -tsa habe, ist der Jarsigner erfolgreich. Dies ist die GlobalSign TSA URL: http://timestamp.globalsign.com/scripts/timstamp.dll und der Server dahinter akzeptiert anscheinend jeden Pfad (zB. Timestamp.globalsign.com/foobar), so dass ich am Ende nicht wirklich sicher bin, ob mein Jar Zeitstempel hat oder nicht.

Antwort

9

Ich habe gerade die letzten 2 Stunden nach diesem Problem gesucht und schließlich einen Weg gefunden, um zu identifizieren, ob eine JAR-Datei tatsächlich Zeitstempelinformationen in der Signaturblock-Datei enthalten hat. Ich konnte das GlobalSign-Zertifikat im Hexeditor der Datei /META-INF/FOO.DSA sehen, aber ich habe kein Tool gefunden, das die benötigten Informationen ausdrucken würde.

Sie können die Datei FOO.DSA in foo.p7b umbenennen, um sie in Windows CertMgr zu öffnen, aber sie zeigt auch keine Zeitstempelinformationen an. Ich habe es auch nicht geschafft, OpenSSL zu verwenden, um die DSA-Datei zu überprüfen (es ist PKCS # 7-Dateiformat).

So kam ich mit dem folgenden Code, der die Time Stamp SignerInfo und das Datum, wenn der Timestamp erstellt wurde. Ich hoffe, es ist ein guter Anfang für dich. Sie benötigen bcprov-jdk16-144.jar, bcsp-jdk16-144.jar und bcmail-jdk16-144.jar im Klassenpfad. Holen Sie sich von 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

Danke, funktioniert. Braucht auch bcmail-jdk16-144.jar für das CMS Zeug – user199092

+0

Vielen Dank für Ihre Mühe und Zeit. – Edenshaw

+1

Ich habe es auch zu arbeiten, musste aber 'endsWith (". Dsa") ändern, um stattdessen nach rsa zu suchen. – JimN

15

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

Sie das jarsigner Dienstprogramm verwenden können, um festzustellen, ob ein signiertes JAR timestamped wurde wie folgt:

jarsigner -verify -verbose -certs signed.jar

wo signed.jar ist der Name Ihrer signierten JAR. Wenn es timestamped ist, wird die Ausgangsleitungen der folgenden umfassen, welche die Zeit es unterzeichnet wurde:

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

Wenn die JAR nicht timestamped, wird der Ausgang diese Zeilen nicht enthalten.

+1

Das ist eigentlich die beste Antwort! – thokuest

+0

Dies ist ein wenig zu spät zur Party, aber kann wichtig sein, wenn Algos verdauen. Wenn Sie sehen möchten, wie es mit Zeitstempel war, benötigen Sie einen jdk8u111 oder einen neueren jarsigner.Mit den -verify -verbose -certs zeigt es dann am Ende: "Timestamp Digest-Algorithmus: SHA-1, Timestamp-Signaturalgorithmus: SHA1withRSA, 2048-Bit-Schlüssel". Dann ist es wichtig, wenn Sie gemischte java7-Installationen unterstützen müssen, bei denen die SHA-256 vs SHA256-Verwechslung ein Problem verursacht. –

5

Java keytool kann bestätigen, ob ein signiertes JAR timestamped ist, und kann auch das Zertifikat des TSA anzuzeigen:

$ 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 

... 
1

mhaller bietet große Code (printDSAInfos). Hilft mir sehr bei meiner Arbeit. Allerdings sind ein paar Änderungen erforderlich. Die Klasse DENERcodable wird jetzt in ASN1Encodable geändert, und die Methode getDERObject() wird in toASN1Primitive geändert. So sieht der Code so aus

ASN1Encodable dob = attribute.getAttrValues().getObjectAt(0); 
    CMSSignedData signedData = new CMSSignedData(dob.toASN1Primitive().getEncoded()); 
Verwandte Themen