Sign your bundles
Create a signing key pair, ship a build that trusts it, sign every upload in CI and rotate or retire keys without breaking devices in the field.
Signing makes a device apply nothing your team did not sign. The key is yours: the CLI signs the bundle manifest at upload with a private key on your machine. The device verifies the signature over the bytes it downloaded before it applies anything.
The private key never reaches HotCodePush, and signing is opt-in and available on every plan. The signature covers the bundle, not the channel index. How an update reaches a device says what an unsigned index can and cannot do. The short version is the site's OTA update security page.
Prerequisites
- Quickstart has run, so the SDK is installed and a first release is live.
- The CLI is signed in, or
HOTCODEPUSH_TOKENis in the environment. - You hold the Owner or Admin role on the app. Organizations lists the roles.
1. Create a signing key pair
If init already generated one for you, skip to step 2. Run the command in the project root:
npx hotcodepush signing-key createThe CLI generates an RSA key pair on your machine and registers the public key with the app. It appends the key to publicKeys in hotcodepush.json and writes the private key to hotcodepush-private-key.pem, never printing it. A pair the team already holds, such as a CodePush app's key, is added with signing-key add instead.
The console's Signing keys page lists keys and deletes them, while the pair is generated on your machine.
Keep the private key out of version control
Add hotcodepush-private-key.pem to .gitignore before the next commit. Whoever holds the file can sign the app's bundles. CI holds the file's content as a secret, never the file in the repository.
2. Ship a store build that trusts the key
signing-key create wrote the public key into hotcodepush.json:
{
"appId": "7f3c2d1e-9a4b-4c5d-8e6f-0a1b2c3d4e5f",
"channel": "production",
"publicKeys": [
"rsa-v1_5-sha256:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA…"
]
}The build step writes every listed key into the binary, so a binary trusts the keys listed when it was built. Ship a store build with the list in place.
A binary with a key refuses an unsigned or wrongly signed bundle and keeps the one it runs. A binary built with an empty list checks the content hashes alone, so the signed uploads of step 3 reach older binaries too.
3. Sign every upload
Once a public key is registered, an unsigned upload for the app is refused. Every release create and bundle upload now carries the key:
npx hotcodepush release create --path dist --private-key-path hotcodepush-private-key.pemIn CI, store the file's content as the secret HOTCODEPUSH_SIGNING_KEY. The CLI reads it when --private-key-path is absent. Ship every commit shows where both secrets go. A pull-request pipeline that runs release create --dry-run signs nothing and needs no key.
The release applies within about a minute. If nothing happens, see Troubleshooting.
4. Rotate a key
Rotation is a store release, in this order, since a binary that trusts only the old key refuses a bundle signed with the new one:
- Create the second key with
npx hotcodepush signing-key create --private-key-path hotcodepush-private-key-2.pem. It is appended topublicKeys, so every build from now on trusts both keys. - Ship a store build.
- Keep signing with the old key while binaries that trust only it still have devices.
binary listshows each binary with its device count. - Switch to the new key, through
--private-key-pathor theHOTCODEPUSH_SIGNING_KEYsecret. - Delete the old key with
npx hotcodepush signing-key deleteonce no binary that trusts only it has devices.
To leave signing, ship a store build whose publicKeys is empty, keep signing while binaries that trust the keys still have devices, then delete every key. The CLI signs only while the hotcodepush.json it reads lists the key, so during that window release with --config pointing at a copy that still lists it.
A mistaken delete is reversed with signing-key add, as long as the team holds the private key.
Next steps
- Ship every commit has the pipeline that carries the token and the signing secret.
- signing-key lists every flag of
create,add,listanddelete. - Migrate from CodePush covers bringing the key pair a CodePush app already signs with.
Last updated on