Rotate a signing key
Rotate a product’s signing key when you want to move to a new one, or when the current one has leaked. A build of your app embeds one public key, and a build you already shipped cannot be changed. So plan a rotation together with your releases. Rotating takes one click in the Console, or one call to the Admin API; the work is in the order you do things around it.
What a rotation does
Section titled “What a rotation does”Sealcord generates a new Ed25519 key for the product, stores it encrypted and never shows the private half. From that moment:
- Every new licence key and every verdict is signed with the new key.
- The old public key moves to the product’s previous public keys, and keys signed with it keep activating, unless you chose to stop accepting them.
- A key you read back from a licence is signed again with the current key, so it is the one to send a customer who needs a key their new build accepts.
- A build that holds only the old public key cannot check keys or verdicts signed with the new one.
Rotate and retire
Section titled “Rotate and retire”- Rotate together with a new major version of your app. An owner or admin rotates the key in the
Console, on the product’s page, with Rotate signing key, and keeps accepting the earlier keys. Or
call the rotate route with
{ "keep_previous": true }, which needs theproducts:writescope. Builds that embed the old public key now reject new keys and verdicts, so ship the next step before you tell customers to update. - Ship the build that embeds the new public key. Read it from the product’s page in the Console,
or from
public_keyin the product’s answer. Customers on older builds keep the keys they have. - Re-issue keys to customers who move to the new build. Reading a licence through the Admin API, or opening it in the Console, gives its key under the current signing key.
- Retire the old public key only when no build you support still uses it. In the Console, use
Stop accepting on the earlier key; or call
the retire route with
{ "public_key": "<64 hex characters>" }. Keys signed with it then stop activating within 30 seconds, withlicence_key_invalid. Builds already shipped still accept those keys offline, and machines keep the verdict they hold until it expires. Re-issue keys to customers still on the old key first.
The current key cannot be retired: rotate first, or the call answers 409 conflict. Retiring a key that the product does not accept
answers 404 public_key_not_found.
curl https://api.sealcord.com/v1/admin/products/acme-notes/rotate-signing-key \ -H "authorization: Bearer $SEALCORD_TOKEN" \ -H 'content-type: application/json' \ -d '{ "keep_previous": true }'The answer is the product, with its new public_key, the old one in previous_public_keys, and its
key_history.
If a signing key leaks
Section titled “If a signing key leaks”Rotate with { "keep_previous": false } at once. Every key signed with the leaked key stops
activating within 30 seconds of the rotation, and the API answers licence_key_invalid for it. If the
leaked key is already a previous one, retire it instead.
Then ship a build with the new public key and re-issue keys to your paying customers. Builds you already shipped keep accepting keys signed with the leaked key offline, because they cannot know it leaked; only the API refuses them.
See which keys a product accepts
Section titled “See which keys a product accepts”A product’s answer carries two fields that help during a rotation:
signing_key_statusisreadywhen the API opens the private key and it matches the pinned public key. When it isunavailable, issuing and activating for the product answerproduct_unavailable.key_historylists the keys the product accepts, the current one first. Each has itspublic_key, afingerprint(the first 16 hex characters of the SHA-256 of the key, to tell keys apart at a glance),current,sinceandreplaced_at.
The Console shows the same history on the product’s page, naming each key by its fingerprint.
Questions
Section titled “Questions”How long until a rotation takes effect?
Section titled “How long until a rotation takes effect?”On the API instance that handled the call, at once. Another instance picks it up within 30 seconds, because each keeps a copy of the product catalogue for that long. For that time it can still sign with, and accept keys under, the previous key.
Do customers have to enter a new key?
Section titled “Do customers have to enter a new key?”Only if you retire the old public key, or rotate without keeping it. While the old key is accepted, existing keys keep activating. A customer needs a new key to use a build that embeds only the new public key.
Can I undo a rotation or a retirement?
Section titled “Can I undo a rotation or a retirement?”No. Rotating again generates yet another key; it does not bring an old one back. Retiring a public key cannot be undone either, so check that no supported build uses it first.
Can I choose the new key myself?
Section titled “Can I choose the new key myself?”No. Sealcord generates and stores each product’s signing key, and the private half is never shown or returned, so nobody can issue keys for your product outside Sealcord.