diff --git a/docs/index.html b/docs/index.html
index 8336abf5..9aebad6f 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -131,6 +131,7 @@
Command Line Tool
timestamp
extract
remove
+ show
tag
@@ -368,6 +369,27 @@
+Show signature
+
+To check whether a file has been signed and with which certificate, use the show command to list details about any signature present on the file.
+
+
+ jsign show foo.exe
+ Signature 0
+ Digest Algorithm: SHA256
+ Digest Value: c481bb3892d066ffacba0650adaa4c252580b776b1dd6026cf4a8bea6c813939
+ Is Timestamped? false
+ Certificate
+ Subject: CN=net.jsign.signing-cert
+ Issuer: CN=net.jsign.issuing-cert
+ Not Before: Fri Dec 03 14:34:46 CST 2021
+ Not After: Wed May 24 14:34:46 CST 2119
+ Expired: false
+ Serial: 148957645726085760686199624248870688956
+
+
+
+
tag
@@ -1040,7 +1062,6 @@ GitHub Actions
${{ github.workspace }}/dist/application.exe
-
API
Jsign also provides a simple API for signing files and can be embedded in another application.
diff --git a/jsign-cli/src/main/java/net/jsign/JsignCLI.java b/jsign-cli/src/main/java/net/jsign/JsignCLI.java
index 0173bd29..0bb2eea1 100644
--- a/jsign-cli/src/main/java/net/jsign/JsignCLI.java
+++ b/jsign-cli/src/main/java/net/jsign/JsignCLI.java
@@ -147,6 +147,10 @@ private Map getOptions() {
map.put("remove", options);
+ options = new Options();
+
+ map.put("show", options);
+
options = new Options();
options.addOption(Option.builder().hasArg().longOpt(PARAM_VALUE).argName("VALUE").desc("The value of the unsigned attribute").build());
diff --git a/jsign-core/src/main/java/net/jsign/SignerHelper.java b/jsign-core/src/main/java/net/jsign/SignerHelper.java
index d9457f4c..3408357d 100644
--- a/jsign-core/src/main/java/net/jsign/SignerHelper.java
+++ b/jsign-core/src/main/java/net/jsign/SignerHelper.java
@@ -333,6 +333,9 @@ public void execute(File file) throws SignerException {
case "remove":
remove(file);
break;
+ case "show":
+ show(file);
+ break;
case "tag":
tag(file);
break;
@@ -496,6 +499,32 @@ private void attach(Signable signable, File detachedSignature) throws IOExceptio
// todo warn if the hashes don't match
}
+ private void printSignatures(Signable signable) throws IOException {
+ List signatures = signable.getSignatures();
+ for (int i = 0; i < signatures.size(); i++) {
+ CMSSignedData signature = signatures.get(i);
+ SignerInformation signerInformation = signature.getSignerInfos().iterator().next();
+
+ String digestAlgorithmName = new DefaultAlgorithmNameFinder().getAlgorithmName(signerInformation.getDigestAlgorithmID());
+ SignerId signerId = signerInformation.getSID();
+ X509CertificateHolder cert = (X509CertificateHolder) signature.getCertificates().getMatches(signerId).iterator().next();
+
+ byte[] digest = signable.computeDigest(DigestAlgorithm.of(signerInformation.getDigestAlgorithmID().getAlgorithm()));
+
+ System.out.println("Signature " + i);
+ System.out.println(" Digest Algorithm: " + digestAlgorithmName);
+ System.out.println(" Digest Value: " + Hex.toHexString(digest));
+ System.out.println(" Is Timestamped? " + SignatureUtils.isTimestamped(signature));
+ System.out.println(" Certificate");
+ System.out.println(" Subject: " + cert.getSubject());
+ System.out.println(" Issuer: " + cert.getIssuer());
+ System.out.println(" Not Before: " + cert.getNotBefore());
+ System.out.println(" Not After: " + cert.getNotAfter());
+ System.out.println(" Expired: " + cert.getNotAfter().before(new Date()));
+ System.out.println(" Serial: " + cert.getSerialNumber());
+ }
+ }
+
private void detach(Signable signable, File detachedSignature) throws IOException {
List signatures = signable.getSignatures();
@@ -576,6 +605,20 @@ private void remove(File file) throws SignerException {
}
}
+ private void show(File file) throws SignerException {
+ if (!file.exists()) {
+ throw new SignerException("Couldn't find " + file);
+ }
+
+ try (Signable signable = Signable.of(file)) {
+ printSignatures(signable);
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
+ throw new SignerException(e.getMessage(), e);
+ } catch (Exception e) {
+ throw new SignerException("Couldn't show the signatures of" + file, e);
+ }
+ }
+
private void tag(File file) throws SignerException {
if (!file.exists()) {
throw new SignerException("Couldn't find " + file);