> ## Documentation Index
> Fetch the complete documentation index at: https://docs.futurex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JSign command examples

> Practical examples of using JSign to sign a Windows artifact with a CryptoHub-resident key and verify the signature.

JSign applies an Authenticode signature to Windows artifacts using a key that stays on the CryptoHub. It runs on any JVM, so you can sign from a Linux or a Windows host.

The examples in this section sign a PowerShell script (`hello.ps1`), because a script is the simplest artifact to create and inspect. JSign also signs Windows PE files (`.exe` and `.dll`), MSI installers, CAB archives, and APPX and MSIX packages. The commands are the same for any supported artifact type; only the file name changes.

<Warning>
  JSign takes the **SunPKCS11 provider** configuration (`pkcs11.cfg`) as its `--keystore` argument, not the Futurex library configuration (`fxpkcs11.cfg`). Both files must be correct: `--keystore` lets JSign build the provider, and **FXPKCS11\_CFG** lets the Futurex library find the CryptoHub. If you pass `fxpkcs11.cfg` to `--keystore`, JSign cannot construct the provider.
</Warning>

## Sign a file

Before signing, confirm the CryptoHub-resident signing key is visible to Java and copy its alias.

<Steps>
  <Step>
    Run the following **keytool** command to list the keys on the CryptoHub that the configured identity has access to. The `-providerArg` flag passes the `pkcs11.cfg` file you created earlier:

    ```shell expandable lines wrap title="Shell" theme={null}
    keytool -list -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /usr/local/etc/pkcs11.cfg -providerName SunPKCS11-Futurex
    ```

    <Note>
      When prompted for the KeyStore password, enter the CryptoHub identity password configured inside the `<CRYPTO-OPR-PASS>` tag in the `fxpkcs11.cfg` file.
    </Note>

    <Check>
      The response should be similar to the following:

      ```shell expandable lines wrap title="Shell" theme={null}
      Keystore type: PKCS11
      Keystore provider: SunPKCS11-Futurex

      Your keystore contains 1 entry

      jsign-demo-1785267399:jsign-demo, PrivateKeyEntry,
      Certificate fingerprint (SHA-256): C0:05:05:D8:F8:5E:B9:FE:DA:52:C3:C3:56:05:E8:1F:F3:0A:15:73:D1:6D:FE:9A:91:27:2D:E1:EF:58:C5:B4
      ```
    </Check>

    <Warning>
      Copy the alias from this output exactly as it appears, including the numeric segment and the colon. The alias JSign requires is the full `<alias>-<id>:<alias>` form the CryptoHub assigned, not the short `-alias` value you passed to `keytool -genkeypair`. The `<id>` segment is generated per key, so it differs in your environment from the example shown here.
    </Warning>
  </Step>

  <Step>
    Create a test artifact to sign.

    On Linux:

    ```shell expandable lines wrap title="Shell" theme={null}
    echo 'Write-Host "Hello from JSign"' > hello.ps1
    ```

    On Windows, use PowerShell:

    ```powershell expandable lines wrap title="PowerShell" theme={null}
    Set-Content -Path .\hello.ps1 -Value 'Write-Host "Hello from JSign"'
    ```
  </Step>

  <Step>
    Run JSign to sign the artifact with the CryptoHub-resident key. Replace the alias with the value you copied in step 1:

    ```shell expandable lines wrap title="Shell" theme={null}
    java -jar jsign-7.4.jar --storetype PKCS11 --keystore /usr/local/etc/pkcs11.cfg --storepass <PIN> --alias "<alias-from-keytool-list>" --alg SHA-384 hello.ps1
    ```

    On Windows, run the equivalent command in a Command Prompt or PowerShell window:

    ```shell expandable lines wrap title="Command Prompt" theme={null}
    java -jar jsign-7.4.jar --storetype PKCS11 --keystore C:\path\to\pkcs11.cfg --storepass <PIN> --alias "<alias-from-keytool-list>" --alg SHA-384 hello.ps1
    ```

    <Note>
      Replace `<alias-from-keytool-list>` with the full alias you copied in step 1. The value must match the alias `keytool -list` displayed, including the numeric segment and the colon, and it differs in your environment. Replace `<PIN>` with the CryptoHub identity password (PKCS #11 PIN) from the `<CRYPTO-OPR-PASS>` tag in `fxpkcs11.cfg`.
    </Note>

    <Warning>
      Unlike keytool, JSign does not prompt for the PIN, so you must supply it. A PIN passed on the command line is visible in your shell history and in the system process list. In an automated pipeline, read it from a secret your CI system injects rather than writing it into a script.
    </Warning>

    <Check>
      If the signing succeeds, the response is:

      ```shell expandable lines wrap title="Shell" theme={null}
      Adding Authenticode signature to hello.ps1
      ```
    </Check>
  </Step>
</Steps>

<Note>
  `--alg SHA-384` sets the digest algorithm for the Authenticode signature. JSign also accepts `SHA-256`. Match this value to your organization's code signing policy.
</Note>

<Note>
  For production signing, consider adding an RFC 3161 timestamp with JSign's `--tsaurl` option so signatures remain verifiable after the signing certificate expires. Refer to the JSign documentation for the timestamping options.
</Note>

<Note>
  JSign's `--certfile` option adds certificates to the signature's chain. It cannot substitute for the certificate that must exist on the token alongside the private key, and it does not make an older JSign release embed the signer certificate. If `keytool -list` does not show a `PrivateKeyEntry`, resolve that first; `--certfile` does not work around it.
</Note>

## Verify the signature

Verify the signature in two ways: confirm the signature block is present in the artifact, and validate the Authenticode signature itself.

### Confirm the signature block

On either operating system, inspect the signed script. JSign appends the Authenticode signature to a PowerShell script as a comment block at the end of the file.

On Linux:

```shell expandable lines wrap title="Shell" theme={null}
cat hello.ps1
```

On Windows:

```shell expandable lines wrap title="Command Prompt" theme={null}
type hello.ps1
```

<Check>
  The file ends with a signature block delimited as follows:

  ```none expandable lines wrap title="hello.ps1" theme={null}
  # SIG # Begin signature block
  ...
  # SIG # End signature block
  ```
</Check>

This confirms JSign wrote a signature into the artifact. It does not validate the signature cryptographically.

### Validate the Authenticode signature

Authenticode validation is a Windows operation. On a Windows host, run the following PowerShell cmdlet against the signed artifact:

```powershell expandable lines wrap title="PowerShell" theme={null}
Get-AuthenticodeSignature .\hello.ps1
```

The cmdlet returns a `Status` field, a `SignatureType` field, and a `SignerCertificate` field.

<Check>
  `SignatureType` reads `Authenticode`, and `SignerCertificate` shows the subject of the certificate you generated, which confirms the signature came from the CryptoHub-resident key:

  ```none expandable lines wrap title="PowerShell" theme={null}
  Status         : UnknownError
  StatusMessage  : A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider
  SignatureType  : Authenticode
  Signer Subject : CN=jsign-demo, O=Futurex
  Sig Algorithm  : sha384RSA
  Key Size       : 3072
  ```
</Check>

<Note>
  The certificate this guide generates is self-signed, so Windows does not trust its issuer and `Status` reports the untrusted-root result shown above rather than `Valid`. This is expected for a test certificate and does not indicate a signing failure. Adding the test certificate to the **Trusted Root Certification Authorities** store on the verifying host changes `Status` to `Valid` and `StatusMessage` to `Signature verified.` For production signing, use a certificate issued by a code signing CA the verifying hosts already trust.
</Note>

<Warning>
  If `SignatureType` reads `None` and `StatusMessage` reads `The certificate for the signer of the message is invalid or not found`, the signing tool did not embed the signer certificate in the signature. Confirm you signed with **JSign 7.4 or later**; JSign 7.1 omits the certificate, and `--certfile` does not compensate for it.
</Warning>

<Note>
  JSign has no verification subcommand. On Linux, the JSign exit status, the `Adding Authenticode signature` output, and the signature block in the artifact together confirm the operation completed. Full Authenticode chain validation requires a Windows host.
</Note>
