如何validation签名的jar是否包含时间戳?

签名jar并使用-tsa选项后,如何validation时间戳是否包含在内? 我试过了:

jarsigner -verify -verbose -certs myApp.jar 

但输出没有指定时间戳的任何内容。 我问,因为即使我在-tsa URL路径中有拼写错误,jarsigner也会成功。 这是GlobalSign TSA URL: http : //timestamp.globalsign.com/scripts/timstamp.dll ,它背后的服务器显然接受任何路径(即timestamp.globalsign.com/foobar),所以最后我是不确定我的jar子是否加盖时间戳。

刚花了最近2个小时寻找这个问题,最后找到了一种方法来识别jar文件是否实际上包含了Signature Block文件中的时间戳信息。 我可以在/META-INF/FOO.DSA文件的hexeditor中看到GlobalSign证书,但我找不到任何可以打印出您需要的信息的工具。

您可以将FOO.DSA文件重命名为foo.p7b以在Windows CertMgr中打开它,但它也不会显示任何时间戳信息。 我也没有设法使用OpenSSL来validationDSA文件(它是PKCS#7文件格式)。

所以我想出了下面的代码,它将显示Time Stamp SignerInfo和创建时间戳的日期。 我希望这对你来说是一个好的开始。 您需要在类路径中使用bcprov-jdk16-144.jar,bctsp-jdk16-144.jar和bcmail-jdk16-144.jar。 从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; } } } 

来自https://blogs.oracle.com/mullan/entry/how_to_determine_if_a :

您可以使用jarsigner实用程序来确定签名的JAR是否已按时间戳加时间戳:

jarsigner -verify -verbose -certs signed.jar

其中signed.jar是您签名的JAR的名称。 如果带有时间戳,则输出将包含以下行,表示签名时间:

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

如果JAR没有带时间戳,则输出将不包括这些行。

Java的keytool可以确认签名的JAR是否带有时间戳,还可以显示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提供了很棒的代码(printDSAInfos)。 在我的工作中帮助我。 但是需要进行一些更改。 DEREncodable类现在更改为ASN1Encodable,getDERObject()方法更改为ASN1Primitive。 所以代码看起来像这样

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