서명 된 JAR에 타임 스탬프가 포함되어 있는지 확인하는 방법은 무엇입니까?
-
22-07-2019 - |
문제
항아리에 서명하고 -tsa 옵션을 사용한 후에는 타임 스탬프가 포함되어 있는지 어떻게 검증 할 수 있습니까? 나는 시도했다 :
jarsigner -verify -verbose -certs myApp.jar
그러나 출력은 타임 스탬프에 대해 아무것도 지정하지 않습니다. -tsa URL 경로에 오타가 있더라도 Jarsigner가 성공하기 때문에 묻습니다. 이것이 GlobalSign TSA URL입니다. http://timestamp.globalsign.com/scripts/timstamp.dll 그리고 그 뒤에있는 서버는 분명히 어떤 경로를 수락합니다 (예 : timestamp.globalsign.com/foobar). 결국 내 병이 시간이 찍혀 있는지 아닌지는 확실하지 않습니다.
해결책
지난 2 시간 동안이 문제를 찾아 보았고 마지막으로 JAR 파일에 실제로 서명 블록 파일에 타임 스탬프 정보가 있는지 확인하는 방법을 찾았습니다. /meta-inf/foo.dsa 파일의 Hexeditor에서 GlobalSign이 인증을받을 수 있었지만 필요한 정보를 인쇄 할 도구를 찾지 못했습니다.
foo.dsa 파일의 이름을 foo.p7b로 바꾸어 Windows certmgr에서 열 수 있지만 시간 스탬프 정보도 표시되지 않습니다. 또한 OpenSSL을 사용하여 DSA 파일을 확인하지 않았습니다 (PKCS#7 파일 형식).
그래서 나는 타임 스탬프 서명자와 타임 스탬프가 생성 된 날짜를 보여줄 다음 코드를 생각해 냈습니다. 나는 그것이 당신에게 좋은 출발이기를 바랍니다. ClassPath에 bcprov-jdk16-144.jar, bctsp-jdk16-144.jar 및 bcmail-jdk16-144.jar가 필요합니다. 그것들을 얻으십시오 바운시 캐슬
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
서명 된 항아리의 이름입니다. 타임 스탬프가있는 경우 출력에는 서명 된 시간을 나타내는 다음 줄이 포함됩니다.
[entry was signed on 8/2/13 3:48 PM]
항아리가 타임 스탬프되지 않은 경우 출력에는 해당 라인이 포함되지 않습니다.
Java 's 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());