Pergunta

Depois de um frasco é assinado ea opção -tsa foi usado, como posso confirmar que o carimbo de hora foi incluído? Eu tentei:

jarsigner -verify -verbose -certs myApp.jar

Mas a saída não especifica nada sobre o carimbo de tempo. Estou perguntando porque mesmo se eu tiver um erro de digitação no caminho -tsa URL, o jarsigner êxito. Esta é a GlobalSign TSA URL: http://timestamp.globalsign.com/scripts/timstamp.dll eo servidor por trás dele aparentemente aceita qualquer caminho (ie. timestamp.globalsign.com/foobar), para que no final eu não estou realmente certo de meu jar é hora marcada ou não.

Foi útil?

Solução

Apenas passou os últimos 2 horas olhando para este problema e, finalmente, encontrou uma maneira de identificar se um arquivo jar na verdade tem informações de carimbo de tempo na assinatura arquivo Bloco incluído. Eu podia ver o certifcate GlobalSign no editor hexadecimal do arquivo /META-INF/FOO.DSA, mas não havia nenhuma ferramenta que iria imprimir as informações que você precisa.

Você pode renomear o arquivo FOO.DSA para foo.p7b para abri-lo no Windows certmgr, mas também não mostra qualquer informação carimbo de tempo. Eu também não conseguiu usar OpenSSL para verificar o arquivo DSA (É formato PKCS # 7 arquivo).

Então, eu vim com o seguinte código que irá mostrar o Time Stamp SignerInfo ea data em que o Timestamp foi criado. Espero que seja um bom começo para você. Você precisa bcprov-jdk16-144.jar, bctsp-jdk16-144.jar e bcmail-jdk16-144.jar no classpath. Obtê-los a partir 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;
        }
    }
}

Outras dicas

A partir https://blogs.oracle.com/mullan/entry/how_to_determine_if_a :

Você pode usar o utilitário jarsigner para determinar se um JAR assinado foi timestamped da seguinte forma:

jarsigner -verify -verbose -certs signed.jar

onde signed.jar é o nome do seu JAR assinado. Se for timestamped, a saída irá incluir linhas do seguinte indicando o momento em que foi assinado:

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

Se o JAR não é timestamped, a saída não incluem essas linhas.

keytool pode confirmar de Java se um JAR assinado é timestamped, e também pode exibir o certificado do 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 oferece grandes código (printDSAInfos). me ajuda muito no meu trabalho. No entanto, um par de mudanças necessárias. classe DEREncodable é agora mudada para ASN1Encodable e getDERObject método () são alterados para toASN1Primitive. Então o olhar um código como este

    ASN1Encodable dob = attribute.getAttrValues().getObjectAt(0);
    CMSSignedData signedData = new CMSSignedData(dob.toASN1Primitive().getEncoded());
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top