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 @@

    extract


    +

    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);