一个罐子签名并使用了-tsa选项后,我如何可以验证时间戳被列入? 我试过了:
jarsigner -verify -verbose -certs myApp.jar
但是,输出不指定有关时间戳什么。 我问,因为即使我在-tsa URL路径的错字,在成功的jarsigner。 这是在GlobalSign TSA网址: http://timestamp.globalsign.com/scripts/timstamp.dll和服务器背后显然接受任何路径(即timestamp.globalsign.com/foobar),所以最后我真的不知道我的罐子打上时间戳与否。
刚刚花了2小时以来在寻找这个问题,终于找到了一个方法来识别一个jar文件是否确实有签名块文件的时间戳信息包括在内。 我可以看到GlobalSign的认证文件中/META-INF/FOO.DSA文件的16进制软件,但我没有找到这将打印出您所需要的信息的任何工具。
您可以重命名FOO.DSA文件foo.p7b在Windows CertMgr打开它,但它也没有表现出任何时间戳信息。 我也没能使用OpenSSL验证DSA文件(这是PKCS#7文件格式)。
所以,我想出了下面的代码,这将显示时间戳个SignerInfo当创建时间戳的日期。 我希望这是一个良好的开端为您服务。 您需要bcprov-jdk16-144.jar,bctsp-jdk16-144.jar和bcmail-jdk16-144.jar在classpath。 从让他们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()方法被改变为toASN1Primitive。 因此,代码如下所示
ASN1Encodable dob = attribute.getAttrValues().getObjectAt(0);
CMSSignedData signedData = new CMSSignedData(dob.toASN1Primitive().getEncoded());