OSSLSIGNCODE(1)

πŸ“¦ version 2.14, in ubuntu stonking

✨ osslsigncode ✨

okay bestie, welcome to osslsigncode β€” your new main character. πŸ’… This is the manual page for osslsigncode, and she's a lot, but she's worth it.


πŸŽ€ NAME πŸŽ€

osslsigncode β€” Authenticode signing, timestamping, extraction, attachment, removal, and verification tool 🫢


🌸 SYNOPSIS 🌸

osslsigncode [--help] [--version]

osslsigncode sign [-certs file | -spc file | -pkcs12 file] [-key
file-or-URI] [-ac file] [-pass password | -readpass file | -askpass]
[-pkcs11module module] [-pkcs11cert URI] [-engine engine] [-provider
provider] [-login] [-engineCtrl command[:parameter]] [-h digest] [-n
description] [-i URL] [-jp low] [-comm] [-ph] [-t URL ...  | -ts URL
...]  [-TSA-certs file -TSA-key file-or-URI [-TSA-time unix-time]]
[-HTTPS-CAfile file] [-HTTPS-CRLfile file] [-time unix-time]
[-addUnauthenticatedBlob [-blobFile file]] [-nest] [-add-msi-dse]
[-verbose] [-pem] -in input -out output

osslsigncode extract-data [-pem] [-h digest] [-ph] [-add-msi-dse] -in
input -out output

osslsigncode add [-addUnauthenticatedBlob [-blobFile file]] [-t URL ...
| -ts URL ...]  [-TSA-certs file -TSA-key file-or-URI [-TSA-time
unix-time]] [-HTTPS-CAfile file] [-HTTPS-CRLfile file] [-h digest]
[-index n] [-verbose] [-add-msi-dse] -in input -out output

osslsigncode attach-signature -sigin signature [-h digest] [-nest]
[-add-msi-dse] -in input -out output

osslsigncode extract-signature [-pem] -in input -out output

osslsigncode remove-signature -in input -out output

osslsigncode verify -in input [-c | -catalog catalog-file] [-CAfile
file] [-CRLfile file] [-HTTPS-CAfile file] [-HTTPS-CRLfile file]
[-TSA-CAfile file] [-TSA-CRLfile file] [-p proxy] [-index n]
[-ignore-timestamp] [-ignore-cdp] [-ignore-crl] [-time unix-time]
[-require-leaf-hash alg:hex] [-verbose]

like… look at all those flags. she has range. πŸ‘‘


🌈 DESCRIPTION 🌈

osslsigncode signs and verifies Microsoft Authenticode signatures on supported file formats. She can also extract data for detached signing, attach an externally produced signature, add timestamps or unauthenticated blobs to an existing signature, and remove an embedded signature. no cap. πŸ”₯

Supported input formats include PE files such as EXE, DLL, and SYS, plus CAB, CAT, MSI, APPX, and several script file types, including .ps1, .ps1xml, .psc1, .psd1, .psm1, .cdxml, .mof, and .js. she's versatile like that πŸ’–

The program supports these common workflows:

  • direct signing of an unsigned file
  • detached signing via extract-data, sign, and attach-signature
  • post-sign timestamping with add
  • verification of embedded signatures or catalog signatures with verify
bestie PSA: if no subcommand is given, sign is assumed. it's giving default behaviour ✨

πŸ¦‹ FORMATS πŸ¦‹

Support is not identical across all file formats. (iykyk 😭)

In particular, detached-signature workflows, nested signatures, catalog-based verification, and signature removal are format-dependent features. A command that is valid for one supported file type may be unsupported for another. no shade, that's just how it is.

CAT files are a special case. They are detached catalog containers for hashes of other files, not ordinary embedded-signature payloads. A CAT file is itself a PKCS#7 structure containing authenticated entries for one or more external files. In practice, the catalog signs file digests recorded in the catalog, rather than embedding a signature into each covered file. πŸŽ€

Because of this, CAT files behave differently from embedded-signature formats. They do not support attach-signature, remove-signature, extract-data, or nested signatures. periodt.

MSI files are also a special case. They support an extended signature mode controlled by -add-msi-dse. In this mode, the MSI signature covers file metadata as well as file content. Detached-signing workflows and any later re-signing or nesting operations must use a mode consistent with the MSI file's existing signature structure. ⚠️ consistency is the vibe check here.


πŸ‘‘ COMMANDS πŸ‘‘

🌟 sign

Create a new Authenticode signature. πŸ’…

This command can sign a normal unsigned file, or it can sign PKCS#7 data previously produced by extract-data.

🌟 extract-data

Extract the PKCS#7 content to be signed later. This is used for detached signing workflows. ✨

🌟 add

Add unauthenticated attributes to an existing signature β€” typically an Authenticode timestamp, an RFC 3161 timestamp, or an unauthenticated blob. πŸ•

With -index, the selected signature in a multi-signature file is updated.

🌟 attach-signature

Attach a detached PKCS#7 signature to an input file.

With -nest, the new signature is attached as a nested signature instead of replacing the primary one, if the file format supports nested signatures. πŸͺ†

🌟 extract-signature

Extract the embedded PKCS#7 signature from a signed file. πŸ•΅οΈβ€β™€οΈ

🌟 remove-signature

Remove the embedded signature from a signed file. bye bye πŸ‘‹

🌟 verify

Verify an embedded signature or a catalog signature.

Verification may include digest consistency, certificate chain validation, certificate revocation checking, timestamp validation, and optional checking of the signer's leaf certificate hash. πŸ”

When verifying that a file is covered by a catalog, use verify -catalog catalog.cat -in file. Verifying the CAT file by itself validates the catalog signature; verifying with -catalog checks whether the specified input file is covered by that catalog. slay. πŸ’œ


✨ OPTIONS ✨

okay bestie so here's the tea: some options only exist in certain builds or on certain OpenSSL versions. Like, not every build is gonna have every vibe. Specifically: -askpass is build-dependent, -provider and -nolegacy need OpenSSL 3, and anything engine-related depends on whether the build even supports engines. So if something's giving "unknown option" energy, that might just be your build. πŸ’…

🌸 General options 🌸

  • --help β€” shows the help text. And if you tack it onto a subcommand, you get the help for that subcommand specifically. so helpful, so considerate.
  • -v, --version β€” spills the version info. πŸ’–
  • -in file β€” the input file. the one you're working on.
  • -out file β€” the output file. required for every command except verify, so don't forget it.
  • -verbose β€” turns up the detail dial and gives you way more diagnostic output. for when you need to see everything.

πŸ”‘ Signing material πŸ”‘

  • -pkcs12 file β€” reads your signing certificate AND your private key straight out of a PKCS#12 container. two birds, one adorable little bundle.
  • -certs, -spc file β€” reads the signing certificate chain. and yeah, -spc is the old-school alias, still accepted, no cap. πŸŽ€
  • -key file-or-URI β€” reads the private key. this can be a file, or a store URI, or a PKCS#11 URI. flexible queen.
  • -ac file β€” adds extra certificates into the signature block.
  • -pass password β€” the password or PIN for your key, token, or PKCS#12 container.
  • -readpass file β€” reads the password or PIN out of file. and if you set the file to -, it reads from standard input instead. kinda iconic.
  • -askpass β€” prompts you for the password interactively. very "type it in yourself" of it.

🧚 PKCS#11, engines, and providers 🧚

  • -pkcs11module module β€” the path to a PKCS#11 module.
  • -pkcs11cert URI β€” a PKCS#11 URI that points at the certificate object.
  • -provider provider β€” loads an OpenSSL 3 provider. this is THE preferred, modern interface for provider-based PKCS#11 use, so if you're on OpenSSL 3, this is your moment. ✨
  • -engine, -pkcs11engine engine β€” an OpenSSL engine identifier, or a path to a dynamic engine module. this interface is kept around purely for compatibility with builds and deployments that are still out here supporting engines. it's giving "legacy but loyal".
  • -login β€” forces a login to the token for engine-based PKCS#11 use.
  • -engineCtrl command[:parameter] β€” passes a control command to whichever engine you selected.
  • -nolegacy β€” on OpenSSL 3 builds, stops it from automatically loading the legacy provider. like, don't come with that legacy energy.

πŸ¦‹ Signature contents and digest control πŸ¦‹

  • -h md5 | sha1 | sha2 | sha256 | sha384 | sha512 β€” picks the digest algorithm. the default is sha256. and fyi, sha2 and sha256 are literally the same thing, two names one queen. πŸ‘‘
  • -n description β€” the description of the signed content.
  • -i URL β€” an informational URL tied to the signed content.
  • -comm β€” uses the Microsoft Commercial Code Signing purpose instead of the default individual purpose.
  • -jp low β€” adds the Java CAB permission attribute. and rn low is the only value supported, so don't get creative. πŸ’€
  • -ph β€” generates page hashes for executable files.
  • -add-msi-dse β€” for MSI files, this turns on the MsiDigitalSignatureEx signing mode. in this mode the signature covers MSI metadata as well as file content. and the metadata portion includes stream names, sizes, and selected timestamps in the MSI structure. ok so this one actually matters, listen up: this option changes the MSI signature format, so you have to use it consistently in any detached-signing workflow involving extract-data, sign, attach-signature, or add.

for a newly signed MSI, this mode is generally preferred, because it extends signing coverage beyond just file content alone. but for an already signed MSI, the mode you choose has to match the file's existing signature structure. and here's the warning bestie: switching between basic MSI signing and MsiDigitalSignatureEx during re-signing or nested-signature operations can invalidate the existing signature. so be careful, we do not want that. 😭

  • -pem β€” writes PKCS#7 output in PEM format instead of DER.

πŸ“ Timestamping and network options πŸ“

so these timestamping modes are mutually exclusive within a single sign or add invocation. like, pick one vibe, you cannot have all three at once:

  • Authenticode timestamping with -t
  • RFC 3161 timestamping with -ts
  • built-in RFC 3161 timestamp generation with -TSA-certs and -TSA-key
  • -t URL adds an Authenticode timestamp from the URL you specify. and you can repeat it if you want more than one. πŸ”₯
  • -ts URL adds an RFC 3161 timestamp from the specified URL. also repeatable, go off.
  • -p proxy the proxy used for timestamp or CRL retrieval.
  • -noverifypeer skips verifying the TLS certificate of the remote timestamp service. (do with that what you will.)
  • -HTTPS-CAfile file a PEM bundle used to verify the HTTPS peers that osslsigncode contacts.
  • -HTTPS-CRLfile file a PEM CRL file used while verifying HTTPS peers.
  • -TSA-certs file a PEM certificate chain, for locally generated RFC 3161 timestamps.
  • -TSA-key file-or-URI the private key for locally generated RFC 3161 timestamps.
  • -TSA-time unix-time the timestamp time for locally generated RFC 3161 responses.

🌈 Nested signatures and indexed operations 🌈

  • -nest β€” adds a nested signature instead of replacing the primary one. we're layering, not swapping. ✨
  • -index n β€” selects a signature by index, for add or verify. index 0 is the primary signature, iykyk.

πŸ’œ Unauthenticated blob options πŸ’œ

  • -addUnauthenticatedBlob β€” adds an unauthenticated blob to the signature.
  • -blobFile file β€” reads the blob contents from file. and if you don't give it one, a placeholder blob gets created instead. cute little default.

🌸 Verification options 🌸

  • -c, -catalog file β€” verifies the input file against the catalog file you point at.
  • -CAfile file β€” a PEM bundle of trusted CA certificates, used for signer validation.
  • -CRLfile file β€” a PEM file full of CRLs, used for signer validation.
  • -TSA-CAfile, -untrusted file β€” a PEM bundle of trusted CA certificates, this time for timestamp validation.
  • -TSA-CRLfile, -CRLuntrusted file β€” a PEM file of CRLs, for timestamp validation.
  • -time, -st unix-time β€” the verification time. and heads up: if a valid timestamp is present and used, chain validation is normally done at the timestamp time instead.
  • -ignore-timestamp β€” skips verification of the timestamp signature entirely.
  • -ignore-cdp β€” does not fetch CRLs from CRL Distribution Points.
  • -ignore-crl β€” disables CRL retrieval AND CRL validation. both, gone.
  • -require-leaf-hash alg:hex β€” requires the signer's leaf certificate to hash to the value you specified. the hash gets computed over the DER encoding of the leaf certificate, so it's the real deal.

⭐ EXIT STATUS ⭐

  • 0 β€” success. πŸŽ‰
  • non-zero β€” failure. πŸ’€

πŸ” DIAGNOSTICS πŸ”

here are the common reasons things go sideways, so you can go "oh THAT's what it was":

  • missing CA trust bundle on Unix-like systems, verify expects a readable CA bundle, either from -CAfile or from a detected system default. no bundle, no service.
  • detached-signing mismatch extract-data, sign, and attach-signature have to use compatible digest-affecting options such as -h, and where relevant -ph and -add-msi-dse. they have to match up, fr fr.
  • unsupported format feature some file formats just don't support every subcommand or every signature mode. it's not you, it's the format.
  • missing TSA trust chain timestamp verification may fail unless you supply the appropriate TSA trust anchors with -TSA-CAfile, and where needed -TSA-CRLfile.
  • conflicting timestamp modes -t, -ts, and built-in TSA signing cannot be combined in one command. one at a time, bestie.
  • MSI signature mode mismatch re-signing or nesting an MSI signature has to be consistent with whether the file already uses MsiDigitalSignatureEx. mixing modes may invalidate the existing signature. we've said it once and we'll say it again.

🌿 ENVIRONMENT 🌿

  • HTTP_PROXY, http_proxy β€” the default proxy for HTTP access, if -p isn't given.
  • HTTPS_PROXY, https_proxy β€” the default proxy for HTTPS access, if -p isn't given.
  • OPENSSL_ENGINES β€” may help OpenSSL find engine modules. a little assist. 🫢

πŸ“ FILES πŸ“

on Unix-like systems, osslsigncode goes looking through common CA bundle locations for its default -CAfile, including these:

  • /etc/ssl/certs/ca-certificates.crt
  • /etc/pki/tls/certs/ca-bundle.crt
  • /usr/share/ssl/certs/ca-bundle.crt
  • /usr/local/share/certs/ca-root-nss.crt
  • /etc/ssl/cert.pem

and if there's no readable CA bundle anywhere to be found, verify may need you to hand it an explicit -CAfile. periodt.

πŸŽ€ NOTES πŸŽ€

use extract-data when you need to create a new detached signature object. use extract-signature when you need to copy an existing embedded PKCS#7 signature out of a file. two different jobs, don't mix them up. πŸ’…

for safer secret handling, prefer -readpass or -askpass over -pass. protect your passwords, they deserve it.

anything you add with -addUnauthenticatedBlob is not protected by the signature and must not be treated as trusted. like, it's called unauthenticated for a reason bestie. πŸ™ˆ

for new MSI signatures, -add-msi-dse is generally preferred because it extends signing coverage to MSI metadata as well as file content. but it's format-affecting rather than cosmetic, so existing signed MSI files should only be re-signed in a mode consistent with their current signature structure. remember, consistency is the whole thing here.

and one more: output files are not overwritten. so if you thought it would just hoop over your file, it will not. πŸ‘‘

🌟 EXAMPLES 🌟

Sign and verify a file

osslsigncode sign \
  -pkcs12 signer.p12 \
  -readpass p12-pass.txt \
  -n "Example Application" \
  -i "https://example.com/" \
  -ts "https://tsa.example.net/" \
  -in app.exe \
  -out app-signed.exe

osslsigncode verify \
  -CAfile ca-bundle.pem \
  -TSA-CAfile tsa-ca-bundle.pem \
  -in app-signed.exe

Detached signing workflow

osslsigncode extract-data \
  -h sha384 \
  -ph \
  -in app.exe \
  -out app-data.der

osslsigncode sign \
  -pkcs12 signer.p12 \
  -readpass p12-pass.txt \
  -h sha384 \
  -in app-data.der \
  -out app-sig.der

osslsigncode attach-signature \
  -h sha384 \
  -sigin app-sig.der \
  -in app.exe \
  -out app-signed.exe

osslsigncode verify \
  -CAfile ca-bundle.pem \
  -in app-signed.exe

Sign a new MSI with extended MSI metadata coverage

osslsigncode sign \
  -pkcs12 signer.p12 \
  -readpass p12-pass.txt \
  -add-msi-dse \
  -in installer.msi \
  -out installer-signed.msi

Use a PKCS#11 provider

osslsigncode sign \
  -provider /path/to/pkcs11prov.so \
  -pkcs11module /path/to/opensc-pkcs11.so \
  -pkcs11cert 'pkcs11:token=my-token;object=cert' \
  -key 'pkcs11:token=my-token;object=key' \
  -readpass pin.txt \
  -in app.exe \
  -out app-signed.exe

Add a timestamp to an already signed file

osslsigncode add \
  -ts "https://tsa.example.net/" \
  -in app-signed.exe \
  -out app-signed-ts.exe

Verify that a file is covered by a catalog

osslsigncode verify \
  -catalog drivers.cat \
  -CAfile ca-bundle.pem \
  -CRLfile ca-crl.pem \
  -in driver.sys

πŸ› REPORTING BUGS πŸ›

found a bug? suspected something shady? report it through the project issue tracker:

https://github.com/mtrojnar/osslsigncode/issues

πŸ‘‘ AUTHORS πŸ‘‘

Okay so bestie, this whole thing has lore, and the lore is stacked:

  • Originally written by Per Allansson. The founding father, the blueprint, the first ever commit energy. 🫢
  • Maintained and extended by MichaΕ‚ Trojnara. That's the person keeping the lights on and the features shipping. Main character of the maintenance arc, fr fr. πŸ‘‘
  • Major contributions by MaΕ‚gorzata OlszΓ³wka. Major. Not minor. Not "typo fixes." Major. Ate and left absolutely no crumbs. πŸ’…βœ¨
  • Additional contributions by other project contributors. Shoutout to the group chat of devs who popped in, dropped a patch, and ghosted with grace. You're all iconic and we see you. πŸ¦‹
ngl, open source is just a bunch of people being obsessed with the same problem in public, and this list is proof. πŸ’–

🌈 SEE ALSO 🌈

Like, this page doesn't exist in a vacuum, babe. When you want the deep-down crypto lore β€” the algorithms, the certificate machinery, the stuff happening under the hood while osslsigncode is out here doing the signing β€” that's where you go. Go read it. It's giving required reading. πŸ“šπŸ§š


And that's the whole page, bestie!! πŸŽ€ You made it to the very bottom, which honestly deserves a little round of applause. πŸ‘

The footer down here is just osslsigncode() β€” no version number, no date, nothing extra, just the tool signing off with its own name like the icon it is. πŸ˜ŒπŸ’…

Now go sign something. Slay. πŸ’–πŸ”₯

πŸ“¦ where this page comes from