Question

Une fois qu'un fichier jar est signé et que l'option -tsa a été utilisée, comment puis-je valider que l'horodatage est inclus? J'ai essayé:

jarsigner -verify -verbose -certs myApp.jar

Mais la sortie ne spécifie rien sur l'horodatage. Je demande parce que même si j'ai une faute de frappe dans le chemin de l'URL -tsa, le jarsigner réussit. Il s'agit de l'URL TSA de GlobalSign: http://timestamp.globalsign.com/scripts/timstamp.dll et le serveur derrière accepte apparemment tous les chemins (timestamp.globalsign.com/foobar), donc je ne suis pas vraiment sûr que mon pot est horodaté ou non.

Était-ce utile?

La solution

Je viens de passer les deux dernières heures à rechercher ce problème et à trouver enfin un moyen d'identifier si un fichier jar contient effectivement des informations d'horodatage dans le fichier de bloc de signature inclus. Je pouvais voir le certificat GlobalSign dans le rédacteur hexagonal du fichier /META-INF/FOO.DSA, mais je n’ai trouvé aucun outil permettant d’imprimer les informations dont vous avez besoin.

Vous pouvez renommer le fichier FOO.DSA en foo.p7b pour l’ouvrir dans Windows CertMgr, mais il n’affiche aucune information d’horodatage. Je n'ai pas non plus réussi à utiliser OpenSSL pour vérifier le fichier DSA (c'est le format de fichier PKCS # 7).

Je suis donc arrivé avec le code suivant qui montrera le Time Stamp SignerInfo et la date à laquelle l’horodatage a été créé. J'espère que c'est un bon début pour vous. Vous avez besoin de bcprov-jdk16-144.jar, bctsp-jdk16-144.jar et bcmail-jdk16-144.jar dans le chemin d'accès aux classes. Obtenez-les auprès de 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;
        }
    }
}

Autres conseils

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

  

Vous pouvez utiliser l'utilitaire jarsigner . pour déterminer si un fichier JAR signé a été horodaté comme suit:

     

jarsigner -verify -verbose -certs signed.jar

     

signed.jar est le nom de votre fichier JAR signé. S'il est horodaté, la sortie inclura les lignes suivantes indiquant l'heure à laquelle il a été signé:

     

[l'entrée a été signée le 8/2/13 15:48]

     

Si le fichier JAR n'est pas horodaté, la sortie n'inclura pas ces lignes.

keytool peut confirmer si un fichier JAR signé est horodaté et afficher le certificat de la TSA:

$ 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

...

mhaller fournit un excellent code (printDSAInfos). M'aide beaucoup dans mon travail. Cependant, quelques modifications sont nécessaires. La classe DEREncodable est maintenant remplacée par ASN1Encodable et la méthode getDERObject () est remplacée par toASN1Primitive. Donc, le code ressemble à ceci

    ASN1Encodable dob = attribute.getAttrValues().getObjectAt(0);
    CMSSignedData signedData = new CMSSignedData(dob.toASN1Primitive().getEncoded());
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top