How ssign works, and what it does with your secrets
ssign is an independent client for the SimplySign cloud signing service. Here is what leaves your machine, what is kept on disk, and what to protect.
What is sent where
| Destination | What ssign sends |
|---|---|
cloudsign.webnotarius.plHTTPS |
|
Timestamp serverhttp://time.certum.pl/ by default, changed with
--timestamp-url | An RFC 3161 request carrying the SHA-256 hash of the signature. |
| Nobody | Your files, which are hashed locally, and your TOTP seed, from which the code is computed locally. |
HTTPS certificates are checked through the operating system's trust store.
The login and the key
- The login is an OAuth 2.0 authorization-code flow through Certum's CAS identity provider. The credentials are the e-mail and the 6-digit code; no account password is involved.
- It returns a bearer token valid for about 30 minutes. The SimplySign card needs no PIN
(
pinrequired: false): the bearer token is the only control. - The key is RSA-4096 and the private key stays in the cloud HSM. ssign only receives signatures.
The TOTP seed is a long-lived secret
-O/--otp (environment variable CERTUM_OTP) is your TOTP seed, the base32 secret behind your
authenticator. It is long-lived: anyone who has it and your e-mail can sign code as you,
indefinitely, until you re-issue the SimplySign QR code. Treat it like a private key.
- Never pass it as a command-line argument: it lands in your shell history and in the process list. Use the environment variable.
- Prefer
-T/--token(a one-shot 6-digit code) for local, manual signing, so the seed never leaves your authenticator app. - In CI, store it as a protected environment secret with required reviewers (how), not as a plain repository secret.
- If it ever leaks, rotate it: re-issue the QR code from Certum.
The account e-mail is not sensitive. The 6-digit code expires in about 30 seconds and is low-risk.
In memory, the command keeps the seed or code in a buffer that is wiped when it is no longer needed. That cannot undo
an exposure that happens before ssign starts: a value passed as --otp is visible in
/proc/<pid>/cmdline, and one passed through CERTUM_OTP in
/proc/<pid>/environ.
The session cache
To avoid a second login (Certum accepts each code only once), the ssign command and the PKCS#11 module
save the session after logging in, and reuse it on the next runs.
- Where:
$XDG_RUNTIME_DIR/ssign/session.json; ifXDG_RUNTIME_DIRis not set,$HOME/.cache/ssign/session.json; otherwisessign/session.jsonin the system temporary folder. - What: the account e-mail, the bearer token, an expiry time, the card serial and the signing certificate. Neither the seed nor the code is written.
- How long: ssign trusts a saved token for 20 minutes, inside the token's own lifetime of about 30 minutes, and logs in again when less than 2 minutes remain.
- Permissions: on Unix systems the folder is created with mode
0700and the file with0600, readable by your user only. - A cache saved for another e-mail address, expired or unreadable is ignored, and ssign logs in again.
session.json can sign as you until the token expires. On a shared
machine, keep that in mind.What the signature contains
ssign builds a standard Authenticode PKCS#7 SignedData: the file's Authenticode SHA-256 hash, the signing time, the
optional description and URL (-n, -u), the RSA signature from the cloud, your certificate and
the Certum “Code Signing 2021 CA” intermediate, and the RFC 3161 timestamp token. It is embedded in the PE certificate
table and the PE checksum is updated. The digest sent to the cloud is the SHA-256 of the signed attributes that carry
the file's hash.
The SimplySign protocol
ssign speaks the cloud protocol directly:
- Certum cloudLog inOAuth login with your e-mail and a 6-digit one-time code → bearer token
- Certum cloudFetch the cardcard serial and signing certificate
- Your machineHashAuthenticode SHA-256 of each file
- Certum cloudRequest the signaturethe digest and the certificate → asynchronous task
- Certum cloudPoll→ RSA-4096 signature
- Your machineAssemble and embedPKCS#7 + certificate chain + RFC 3161 timestamp, written into the file
The protocol was reverse-engineered from the author's own licensed SimplySign Desktop 2.9.14 install, for interoperability, with a redacting proxy that recorded the structure of the requests and masked every value: no token, code, PIN or signature was written to disk. The whole flow is plain HTTPS, with no cryptographic activation step: session control is the OAuth bearer token. SimplySign Desktop's own PKCS#11 module is a thin shim that relays to the running desktop application, which is why it cannot sign on its own. The full reference, endpoints and dead ends: docs/simplysign-protocol.md.