Convert X.509 Certificates to an SPC with cert2spc

Authenticode signing wants a Software Publisher Certificate, not a bare X.509 file, and cert2spc is the Mono tool that builds one. Feed it one or more X.509 certificates, or certificate revocation lists, and it combines them into a PKCS#7 file ready for a signing workflow such as signcode.

This guide uses the cert2spc shipped by Ubuntu's mono-devel package, version 6.8.0.105+dfsg-3.6ubuntu2 on the reference system. Allow about five minutes if the input certificates already exist; creating disposable test material takes a little longer.

Before you start

  1. Install Mono's development tools if the command is not already present. This changes system state and normally needs elevated privileges.
sudo apt install mono-devel
cert2spc 2>&1 | sed -n '1,8p'

The versioned program identifies itself before reporting the expected missing-argument error. A useful checkpoint is output containing Mono Cert2Spc - version 6.8.0.105 and the usage line cert2spc certificate|crl [certificate|crl] [...] outputfile.spc.

You need readable certificate or CRL files and a destination path. The manpage treats both kinds of input as positional arguments: there are no switches for selecting them. Do not confuse an SPC with a private key. cert2spc packages public certificate material; it does not sign the input and it does not copy a private key into the output.

1. Choose the input material

Put the certificates or CRLs you intend to publish in a working directory, then inspect the names before composing the command. Use explicit paths when a script or a release process is involved, because an accidental shell glob can drag in an unrelated certificate:

cd /path/to/certificate-directory
ls -l -- *.cer *.crt *.crl

For a certificate chain, list each certificate in the command. For a CRL bundle, list each CRL instead. The installed manual supports X.509 certificates and X.509 CRLs as input types, nothing else. If you have a PEM or PKCS#12 file, do not assume it can be passed directly: convert or extract the material with a tool whose input format is documented, then inspect the resulting files first.

2. Build the SPC

Place the output path last. It is the only position that identifies the destination, so a typo in the argument order can turn a source file into the intended output path:

cert2spc \
  /path/to/leaf.cer \
  /path/to/intermediate.cer \
  /path/to/publisher.spc

On the reference installation, a successful run prints the Mono banner followed by Success. The output is a DER-encoded PKCS#7 Signed Data file: not a text certificate, and not useful just because you rename it to look like .cer.

For CRLs, the shape is identical:

cert2spc \
  /path/to/publisher.crl \
  /path/to/older-publisher.crl \
  /path/to/revocation-data.spc

There is no elevation requirement for reading ordinary files and writing into a directory you own. Use sudo only when the chosen destination is protected, and consider writing to a private staging directory before moving a verified result into a release location.

3. Verify the result

First check that the file exists and is the expected container format:

file /path/to/publisher.spc
openssl pkcs7 -inform DER -in /path/to/publisher.spc -print_certs -noout

The first command should describe DER-encoded PKCS#7 Signed Data. The OpenSSL command should list the certificates in an SPC made from certificates. For a CRL-only file, use a PKCS#7 inspection command that suits your OpenSSL version, or validate it in the consumer that will perform the signing. A successful cert2spc message only proves the file was written, not that it holds the material you meant to select.

Record the certificate subjects and expiry dates before a release. Inspect an individual input with:

openssl x509 -in /path/to/leaf.cer -noout -subject -issuer -dates

If the input is DER rather than PEM, add -inform DER. That option belongs to openssl x509, not to cert2spc.

4. Handle overwrites and recovery

Check the destination before running the command in automation:

test ! -e /path/to/publisher.spc && echo 'destination is new' || echo 'destination exists'

Warning: the manpage explicitly says an existing output file will be overwritten. That is the main destructive edge case here. Preserve the old file if it might still be needed, or write to a new temporary name and replace the original only after verification:

cp -- /path/to/publisher.spc /path/to/publisher.spc.bak
cert2spc /path/to/leaf.cer /path/to/intermediate.cer /path/to/publisher.spc.new
file /path/to/publisher.spc.new
mv -- /path/to/publisher.spc.new /path/to/publisher.spc

The mv is the only state-changing step in this safer pattern. If conversion fails, delete the unverified .new file and the original is still sitting there untouched. If you already overwrote the destination without a backup, recovery depends on another copy in your release archive or backup system; cert2spc has no undo option of its own.

Common traps

Done means