From 0f0a1df38723142f32e39af3cbd3fad7ea542b85 Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 05:39:52 -0800 Subject: [PATCH 01/14] docs: highlight cloud KMS integration support for patch signing Add prominent call-to-actions for enterprise customers using cloud key management services (AWS KMS, GCP Cloud KMS, Azure Key Vault, HashiCorp Vault) or HSMs. Since Shorebird only signs a small hash, integrating with external signing services is straightforward. --- .../docs/code-push/guides/patch-signing.mdx | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index f3a144cc..1d06226c 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -35,9 +35,18 @@ limited set of signing algorithms at this time. Please contact us if you have other requirements—we'd be happy to work with you to support your needs. The `shorebird` tool expects to be able to read private and public keys from -`.pem` files on disk. If you need other ways of accessing your key material (or -signing via a cloud signing service) please contact us. We'd be happy to work -with you to support such. +`.pem` files on disk by default. + +### Cloud Signing & Key Management Services + +If your organization uses a cloud key management service (AWS KMS, GCP Cloud +KMS, Azure Key Vault, HashiCorp Vault) or hardware security modules (HSMs), +Shorebird's signing architecture can support these integrations. Since patch +signing only requires signing a small hash value, integrating with external +signing services is straightforward. + +Please [contact us](mailto:contact@shorebird.dev) if you'd like to discuss +integrating Shorebird with your existing key management infrastructure. ### Generate keys @@ -101,12 +110,15 @@ shorebird patch android --public-key-path /path/to/public.pem --private-key-path This tells shorebird to sign the patch with the key pair you provided. -:::note +:::tip[Enterprise Key Management] + +Storing private keys on disk is not ideal for production environments. If your +organization requires integration with cloud KMS (AWS, GCP, Azure), HSMs, or +secrets managers like HashiCorp Vault or 1Password, we'd love to help. Shorebird +only needs to sign a small hash, making integration with external signing +services straightforward. -Storing private keys on disk is not best-practice, and we recognize this. This -was built as a demonstration of the system, we look forward to working with -customers to integrate Shorebird to using the signing services and key storage -methods they are used to. +[Contact us](mailto:contact@shorebird.dev) to discuss your key management needs. ::: @@ -153,9 +165,10 @@ application to send patches to it. ## Trade Offs -The primary trade-off of using patch signing is complexity. Shorebird does not -yet offer automatic key management, so you will need to create and manage your -own key material to use signing. +The primary trade-off of using patch signing is key management complexity. If +your organization already uses a cloud KMS or secrets manager, integrating with +Shorebird is straightforward since we only sign a small hash. Otherwise, you +will need to create and manage your own key material. There is a very small slowdown in application launch. In our testing signature verification on launch takes <50ms on a 5 year old android phone. This From 7c8790510887a203cfa9ac53a44e44eb052919c3 Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 05:41:21 -0800 Subject: [PATCH 02/14] docs: remove passive/hedging language from patch signing guide - State what's supported directly instead of apologizing for limitations - Remove redundant "contact us" notes (already covered by Enterprise tip) - Use active voice throughout - Tighten verbose passages --- .../docs/code-push/guides/patch-signing.mdx | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 1d06226c..891c7441 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -30,12 +30,10 @@ application. ## Adding patch signing to your application -To start, you will need an RSA key pair. Shorebird has only tested with a -limited set of signing algorithms at this time. Please contact us if you have -other requirements—we'd be happy to work with you to support your needs. +To start, you will need an RSA key pair. Shorebird supports RSA keys in PEM +format (both PKCS#1 and PKCS#8). -The `shorebird` tool expects to be able to read private and public keys from -`.pem` files on disk by default. +By default, `shorebird` reads private and public keys from `.pem` files on disk. ### Cloud Signing & Key Management Services @@ -74,14 +72,6 @@ stored securely and kept secret. While the private key is not itself sufficient to make an update to your application (someone would also need access to your Shorebird credentials), it should not be checked into public source control. -:::note - -We do not yet manage signing keys for you or support non-RSA keys. Please -contact us if you have other requirements—we'd be happy to work with you to -support your needs. - -::: - ### Create a release containing the public key To create a release that requires signed patches, run the following command: @@ -95,8 +85,7 @@ This will include the public key in the release artifact produced by :::note -We're using Android to demo, but this will work on any platform Shorebird -supports. +These examples use Android, but patch signing works on all platforms. ::: @@ -170,14 +159,5 @@ your organization already uses a cloud KMS or secrets manager, integrating with Shorebird is straightforward since we only sign a small hash. Otherwise, you will need to create and manage your own key material. -There is a very small slowdown in application launch. In our testing signature -verification on launch takes <50ms on a 5 year old android phone. This -accounts for <10% slowdown on a fast application launch. - -:::note - -If this solution does not meet your needs, please reach out to us at -contact@shorebird.dev. We'd love to hear from you and see if we can find a -solution that works for you. - -::: +Signature verification adds a small overhead at app launch—under 50ms in our +testing on a 5-year-old Android phone. From f345b36f05f7d9fd63584726e78627b9acd632bd Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 05:41:40 -0800 Subject: [PATCH 03/14] docs: mention patch_verification install-only option --- src/content/docs/code-push/guides/patch-signing.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 891c7441..48d30de8 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -160,4 +160,6 @@ Shorebird is straightforward since we only sign a small hash. Otherwise, you will need to create and manage your own key material. Signature verification adds a small overhead at app launch—under 50ms in our -testing on a 5-year-old Android phone. +testing on a 5-year-old Android phone. For apps where this matters, you can set +`patch_verification: install-only` in `shorebird.yaml` to verify signatures only +when patches are installed rather than on every launch. From 5444e658a9352b1628ff27257cb1654710cffb5a Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 05:42:24 -0800 Subject: [PATCH 04/14] fix: correct patch_verification syntax (install_only not install-only) --- src/content/docs/code-push/guides/patch-signing.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 48d30de8..4dde0d2a 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -161,5 +161,5 @@ will need to create and manage your own key material. Signature verification adds a small overhead at app launch—under 50ms in our testing on a 5-year-old Android phone. For apps where this matters, you can set -`patch_verification: install-only` in `shorebird.yaml` to verify signatures only +`patch_verification: install_only` in `shorebird.yaml` to verify signatures only when patches are installed rather than on every launch. From 4ad47c8ce3533bbd5ad24c7a685d3e3b87910648 Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 05:44:29 -0800 Subject: [PATCH 05/14] fix: use parentheses instead of em-dash for readability --- src/content/docs/code-push/guides/patch-signing.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 4dde0d2a..938b1a5a 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -159,7 +159,7 @@ your organization already uses a cloud KMS or secrets manager, integrating with Shorebird is straightforward since we only sign a small hash. Otherwise, you will need to create and manage your own key material. -Signature verification adds a small overhead at app launch—under 50ms in our -testing on a 5-year-old Android phone. For apps where this matters, you can set +Signature verification adds a small overhead at app launch (under 50ms in our +testing on a 5-year-old Android phone). For apps where this matters, you can set `patch_verification: install_only` in `shorebird.yaml` to verify signatures only when patches are installed rather than on every launch. From 3f7be2d3d6ba40bfc18e02978eb0bb91b60505ed Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 05:45:01 -0800 Subject: [PATCH 06/14] docs: clarify verification overhead scales with app size --- src/content/docs/code-push/guides/patch-signing.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 938b1a5a..61f4ea25 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -160,6 +160,6 @@ Shorebird is straightforward since we only sign a small hash. Otherwise, you will need to create and manage your own key material. Signature verification adds a small overhead at app launch (under 50ms in our -testing on a 5-year-old Android phone). For apps where this matters, you can set +testing on a 5-year-old Android phone). For very large apps where this overhead increases, you can set `patch_verification: install_only` in `shorebird.yaml` to verify signatures only when patches are installed rather than on every launch. From 18604d9cc5234ad54472bfb3422a92b4045c10b5 Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 05:52:39 -0800 Subject: [PATCH 07/14] chore: wrap text --- src/content/docs/code-push/guides/patch-signing.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 61f4ea25..4c09a313 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -160,6 +160,8 @@ Shorebird is straightforward since we only sign a small hash. Otherwise, you will need to create and manage your own key material. Signature verification adds a small overhead at app launch (under 50ms in our -testing on a 5-year-old Android phone). For very large apps where this overhead increases, you can set -`patch_verification: install_only` in `shorebird.yaml` to verify signatures only -when patches are installed rather than on every launch. +testing with a medium size app on a 5-year-old Android phone). This overhead +increases with application size. For very large apps, if this overhead shows up +on your benchmarks, you can set `patch_verification: install_only` in +`shorebird.yaml` to verify signatures only when patches are installed rather +than on every launch. From 6e4850fe86db10fc6ffa6572b61dba1b2718c75f Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 06:13:12 -0800 Subject: [PATCH 08/14] chore: remove tradeoff para --- src/content/docs/code-push/guides/patch-signing.mdx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 4c09a313..010c6633 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -154,11 +154,6 @@ application to send patches to it. ## Trade Offs -The primary trade-off of using patch signing is key management complexity. If -your organization already uses a cloud KMS or secrets manager, integrating with -Shorebird is straightforward since we only sign a small hash. Otherwise, you -will need to create and manage your own key material. - Signature verification adds a small overhead at app launch (under 50ms in our testing with a medium size app on a 5-year-old Android phone). This overhead increases with application size. For very large apps, if this overhead shows up From 771dbf7c0db180c84aa086216d5cfbc239332552 Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 07:29:19 -0800 Subject: [PATCH 09/14] docs: add Cloud KMS integration examples for patch signing Add comprehensive documentation for command-based signing with: - HashiCorp Vault Transit - GCP Cloud KMS - AWS KMS - Azure Key Vault - 1Password CLI - macOS Keychain Also includes CI/CD integration tips and GitHub Actions example. --- .../docs/code-push/guides/patch-signing.mdx | 227 ++++++++++++++++-- 1 file changed, 212 insertions(+), 15 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 010c6633..b2837d1e 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -37,16 +37,32 @@ By default, `shorebird` reads private and public keys from `.pem` files on disk. ### Cloud Signing & Key Management Services -If your organization uses a cloud key management service (AWS KMS, GCP Cloud -KMS, Azure Key Vault, HashiCorp Vault) or hardware security modules (HSMs), -Shorebird's signing architecture can support these integrations. Since patch -signing only requires signing a small hash value, integrating with external -signing services is straightforward. +Shorebird supports command-based signing for integration with cloud key +management services (AWS KMS, GCP Cloud KMS, Azure Key Vault, HashiCorp Vault), +hardware security modules (HSMs), and secrets managers (1Password, etc.). -Please [contact us](mailto:contact@shorebird.dev) if you'd like to discuss -integrating Shorebird with your existing key management infrastructure. +Instead of storing keys on disk, you can use `--public-key-cmd` and `--sign-cmd` +to delegate key operations to external tools: -### Generate keys +```sh +# Release with cloud-managed public key +shorebird release android \ + --public-key-cmd="your-command-that-outputs-pem-public-key" + +# Patch with cloud-managed signing +shorebird patch android \ + --public-key-cmd="your-command-that-outputs-pem-public-key" \ + --sign-cmd="your-command-that-signs-stdin-and-outputs-base64" +``` + +**Contract:** +- `--public-key-cmd`: Command outputs a PEM-encoded public key to stdout +- `--sign-cmd`: Command reads data from stdin and outputs a base64 signature to stdout + +See [Cloud KMS Examples](#cloud-kms-examples) below for integration examples +with popular services. + +### Generate keys (file-based) If you do not already have an RSA key pair you'd like to use, you can generate a pair with `openssl`: @@ -101,13 +117,10 @@ This tells shorebird to sign the patch with the key pair you provided. :::tip[Enterprise Key Management] -Storing private keys on disk is not ideal for production environments. If your -organization requires integration with cloud KMS (AWS, GCP, Azure), HSMs, or -secrets managers like HashiCorp Vault or 1Password, we'd love to help. Shorebird -only needs to sign a small hash, making integration with external signing -services straightforward. - -[Contact us](mailto:contact@shorebird.dev) to discuss your key management needs. +For production environments, we recommend using `--public-key-cmd` and +`--sign-cmd` to integrate with your existing key management infrastructure +rather than storing keys on disk. See [Cloud KMS Examples](#cloud-kms-examples) +for integration patterns with AWS KMS, GCP Cloud KMS, HashiCorp Vault, and more. ::: @@ -160,3 +173,187 @@ increases with application size. For very large apps, if this overhead shows up on your benchmarks, you can set `patch_verification: install_only` in `shorebird.yaml` to verify signatures only when patches are installed rather than on every launch. + +## Cloud KMS Examples + +The following examples show how to integrate Shorebird patch signing with +popular key management services using `--public-key-cmd` and `--sign-cmd`. + +### HashiCorp Vault + +Vault's Transit secrets engine provides cryptographic operations without +exposing keys: + +```sh +# Store your key in Vault Transit +vault write transit/keys/shorebird-signing type=rsa-2048 + +# Release +shorebird release android \ + --public-key-cmd="vault read -field=public_key transit/keys/shorebird-signing" + +# Patch +shorebird patch android \ + --public-key-cmd="vault read -field=public_key transit/keys/shorebird-signing" \ + --sign-cmd="vault write -field=signature transit/sign/shorebird-signing \ + hash_algorithm=sha2-256 signature_algorithm=pkcs1v15 input=-" +``` + +### GCP Cloud KMS + +GCP Cloud KMS outputs PEM format natively: + +```sh +# Create a key ring and key +gcloud kms keyrings create shorebird --location=global +gcloud kms keys create signing-key --keyring=shorebird --location=global \ + --purpose=asymmetric-signing --default-algorithm=rsa-sign-pkcs1-2048-sha256 + +# Release +shorebird release android \ + --public-key-cmd="gcloud kms keys versions get-public-key 1 \ + --key=signing-key --keyring=shorebird --location=global" + +# Patch (using a helper script for signing) +shorebird patch android \ + --public-key-cmd="gcloud kms keys versions get-public-key 1 \ + --key=signing-key --keyring=shorebird --location=global" \ + --sign-cmd="gcloud kms asymmetric-sign --version=1 \ + --key=signing-key --keyring=shorebird --location=global \ + --digest-algorithm=sha256 --input-file=- --signature-file=- | base64" +``` + +### AWS KMS + +AWS KMS outputs DER format, which needs conversion to PEM: + +```sh +# Create an RSA signing key +aws kms create-key --key-spec RSA_2048 --key-usage SIGN_VERIFY + +# Create a helper script for public key (aws-kms-pubkey.sh) +#!/bin/bash +aws kms get-public-key --key-id alias/shorebird-signing --output text \ + --query PublicKey | base64 -d | openssl rsa -pubin -inform DER -outform PEM + +# Create a helper script for signing (aws-kms-sign.sh) +#!/bin/bash +HASH=$(cat - | openssl dgst -sha256 -binary | base64) +aws kms sign --key-id alias/shorebird-signing \ + --signing-algorithm RSASSA_PKCS1_V1_5_SHA_256 \ + --message-type DIGEST --message "$HASH" \ + --output text --query Signature + +# Release +shorebird release android --public-key-cmd="./aws-kms-pubkey.sh" + +# Patch +shorebird patch android \ + --public-key-cmd="./aws-kms-pubkey.sh" \ + --sign-cmd="./aws-kms-sign.sh" +``` + +### Azure Key Vault + +```sh +# Create a key in Azure Key Vault +az keyvault key create --vault-name myVault --name shorebird-signing \ + --kty RSA --size 2048 + +# Helper script for public key (azure-kv-pubkey.sh) +#!/bin/bash +az keyvault key download --vault-name myVault --name shorebird-signing \ + --encoding PEM --file /dev/stdout + +# Helper script for signing (azure-kv-sign.sh) +#!/bin/bash +HASH=$(cat - | openssl dgst -sha256 -binary | base64 -w0) +az keyvault key sign --vault-name myVault --name shorebird-signing \ + --algorithm RS256 --digest "$HASH" --query value -o tsv + +# Release +shorebird release android --public-key-cmd="./azure-kv-pubkey.sh" + +# Patch +shorebird patch android \ + --public-key-cmd="./azure-kv-pubkey.sh" \ + --sign-cmd="./azure-kv-sign.sh" +``` + +### 1Password CLI + +1Password can store and retrieve keys securely: + +```sh +# Store your keys in 1Password +op item create --category="Secure Note" --title="Shorebird Signing" \ + "public_key[text]=$(cat public.pem)" \ + "private_key[text]=$(cat private.pem)" + +# Helper script for signing (1password-sign.sh) +#!/bin/bash +PRIVATE_KEY=$(op item get "Shorebird Signing" --fields private_key) +cat - | openssl dgst -sha256 -sign <(echo "$PRIVATE_KEY") | base64 + +# Release +shorebird release android \ + --public-key-cmd="op item get 'Shorebird Signing' --fields public_key" + +# Patch +shorebird patch android \ + --public-key-cmd="op item get 'Shorebird Signing' --fields public_key" \ + --sign-cmd="./1password-sign.sh" +``` + +### macOS Keychain (Local Development) + +For local development on macOS, you can use the system keychain: + +```sh +# Import your key into the keychain +security import private.pem -k ~/Library/Keychains/login.keychain-db + +# Helper script for signing (keychain-sign.sh) +#!/bin/bash +# Note: This requires the key to be stored as an identity +security find-identity -v -p codesigning # List available identities +cat - | openssl dgst -sha256 -sign <(security find-key -l "your-key-label" \ + -w ~/Library/Keychains/login.keychain-db) | base64 + +# For simpler setups, store the PEM in keychain as a generic password +security add-generic-password -a "shorebird" -s "signing-key" \ + -w "$(cat private.pem)" + +# Helper script using generic password +#!/bin/bash +KEY=$(security find-generic-password -a "shorebird" -s "signing-key" -w) +cat - | openssl dgst -sha256 -sign <(echo "$KEY") | base64 +``` + +### CI/CD Integration Tips + +When using command-based signing in CI/CD pipelines: + +1. **Use environment variables** for sensitive configuration (key IDs, vault + addresses) +2. **Authenticate before running Shorebird** - ensure your cloud CLI is + authenticated (e.g., `gcloud auth`, `aws configure`, `vault login`) +3. **Use service accounts** with minimal permissions for automated pipelines +4. **Consider wrapper scripts** that handle authentication and error handling +5. **Test commands independently** before integrating with Shorebird + +Example GitHub Actions workflow: + +```yaml +- name: Authenticate to GCP + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.GCP_SA_KEY }} + +- name: Create signed patch + run: | + shorebird patch android \ + --public-key-cmd="gcloud kms keys versions get-public-key 1 \ + --key=signing-key --keyring=shorebird --location=global" \ + --sign-cmd="./scripts/gcp-sign.sh" +``` From f2eb1dc14dbcb99435f703d4c4b028a95f02c998 Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Fri, 6 Feb 2026 08:10:41 -0800 Subject: [PATCH 10/14] chore: format and add cspell words --- .cspell.yaml | 4 ++++ src/content/docs/code-push/guides/patch-signing.mdx | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.cspell.yaml b/.cspell.yaml index 043afb8f..daf52779 100644 --- a/.cspell.yaml +++ b/.cspell.yaml @@ -27,11 +27,13 @@ words: - codemagic - codepush - codesign + - codesigning - elif - evenodd - ffigen - jank - janky + - keyrings - libapp - libflutter - libupdater @@ -44,10 +46,12 @@ words: - nubank - podfile - prefs + - pubin - previewable - recompiles - riverpod - rollouts + - rsassa - sdkman - shorebirdtech - subosito diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index b2837d1e..a0f0bdb2 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -56,8 +56,10 @@ shorebird patch android \ ``` **Contract:** + - `--public-key-cmd`: Command outputs a PEM-encoded public key to stdout -- `--sign-cmd`: Command reads data from stdin and outputs a base64 signature to stdout +- `--sign-cmd`: Command reads data from stdin and outputs a base64 signature to + stdout See [Cloud KMS Examples](#cloud-kms-examples) below for integration examples with popular services. From ad06e96ae1d76cdb278a9d212c53b83ccb5dea23 Mon Sep 17 00:00:00 2001 From: Tom Arra Date: Fri, 6 Feb 2026 10:17:00 -0600 Subject: [PATCH 11/14] update intro --- src/content/docs/code-push/guides/patch-signing.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index a0f0bdb2..a1ec0e35 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -7,8 +7,9 @@ sidebar: {/* cspell:words outform pubout */} -In addition to our default security measures, Shorebird also provides optional -patch signing. +In addition to our default security measures, Shorebird also provides patch +signing for additonal security. This is optional at this time and needs to be +setup during your build and patch process. Patch signing allows developers to cryptographically sign patch updates with their own keys. This ensures that no one (including Shorebird) can change the From e8a41b40b696478af4f93fe547ba26d9e617ac63 Mon Sep 17 00:00:00 2001 From: Tom Arra Date: Fri, 6 Feb 2026 10:19:30 -0600 Subject: [PATCH 12/14] add link to updater --- src/content/docs/code-push/guides/patch-signing.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index a1ec0e35..5cb6f1ab 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -17,9 +17,9 @@ content of your patches without your private cryptographic keys. Signing works in two parts. First, `shorebird release` commands can take an optional `--public-key-path` argument to embed a public key in your released -application. The Shorebird updater will enforce that only patches signed with a -corresponding private key will be allowed to load for applications that include -a public key. +application. The [Shorebird updater](https://github.com/shorebirdtech/updater) +will enforce that only patches signed with a corresponding private key will be +allowed to load for applications that include a public key. Second, when you build your patch with `shorebird patch`, you can pass `--private-key-path` to have Shorebird sign your patch with your private key. From feab2dd6d3f4d7a84397cb52eaedf63b4d8add02 Mon Sep 17 00:00:00 2001 From: Tom Arra Date: Fri, 6 Feb 2026 13:23:58 -0600 Subject: [PATCH 13/14] fixing flow --- .../docs/code-push/guides/patch-signing.mdx | 184 ++++++------------ 1 file changed, 55 insertions(+), 129 deletions(-) diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 5cb6f1ab..1df7c593 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -29,43 +29,12 @@ There are no required changes to your code and you can add or remove this signing requirement at any time by simply making a new release of your application. -## Adding patch signing to your application +## Implementation -To start, you will need an RSA key pair. Shorebird supports RSA keys in PEM -format (both PKCS#1 and PKCS#8). +You will need an RSA key pair. Shorebird supports RSA keys in PEM format, both +PKCS#1 and PKCS#8. -By default, `shorebird` reads private and public keys from `.pem` files on disk. - -### Cloud Signing & Key Management Services - -Shorebird supports command-based signing for integration with cloud key -management services (AWS KMS, GCP Cloud KMS, Azure Key Vault, HashiCorp Vault), -hardware security modules (HSMs), and secrets managers (1Password, etc.). - -Instead of storing keys on disk, you can use `--public-key-cmd` and `--sign-cmd` -to delegate key operations to external tools: - -```sh -# Release with cloud-managed public key -shorebird release android \ - --public-key-cmd="your-command-that-outputs-pem-public-key" - -# Patch with cloud-managed signing -shorebird patch android \ - --public-key-cmd="your-command-that-outputs-pem-public-key" \ - --sign-cmd="your-command-that-signs-stdin-and-outputs-base64" -``` - -**Contract:** - -- `--public-key-cmd`: Command outputs a PEM-encoded public key to stdout -- `--sign-cmd`: Command reads data from stdin and outputs a base64 signature to - stdout - -See [Cloud KMS Examples](#cloud-kms-examples) below for integration examples -with popular services. - -### Generate keys (file-based) +### Generate Keys If you do not already have an RSA key pair you'd like to use, you can generate a pair with `openssl`: @@ -91,16 +60,24 @@ stored securely and kept secret. While the private key is not itself sufficient to make an update to your application (someone would also need access to your Shorebird credentials), it should not be checked into public source control. -### Create a release containing the public key +### Key Storage -To create a release that requires signed patches, run the following command: +Shorebird does not provided a Key Storage solution at this time. If you are +using this feature we highly recommend using a cloud key management service +instead of just storing keys on disk. **If for any reason you were to lose your +private key, there is no way to create a patch for an application containing the +corresponding public key.** Even Shorebird is not able to create a patch for +your application without your private key. In such a case, you would need to +make and distribute a new release of your application to send patches to it. -```sh -shorebird release android --public-key-path /path/to/public.pem -``` +Shorebird does support command-based signing for integration with cloud key +management services (HashiCorp Vault, GCP Cloud KMS, AWS KMS, Azure Key Vault), +hardware security modules (HSMs), and secrets managers (1Password, etc.). -This will include the public key in the release artifact produced by -`shorebird release` and cause the released app to require signed patches. +See [Cloud KMS Examples](#cloud-kms-examples) below for integration examples +with popular services. + +### Create a Signed Release :::note @@ -108,26 +85,42 @@ These examples use Android, but patch signing works on all platforms. ::: -### Create a signed patch - -To create a signed patch, run the following command: +To create a release that requires signed patches, run the following command: ```sh -shorebird patch android --public-key-path /path/to/public.pem --private-key-path /path/to/private.pem +# Build Release with local path to key file +shorebird release android --public-key-path /path/to/public.pem + +# Build Release with command for cloud-managed public key +# Ensure that the command outputs a PEM-encoded public key to stdout +shorebird release android \ + --public-key-cmd="your-command-that-outputs-pem-public-key" ``` -This tells shorebird to sign the patch with the key pair you provided. +This will include the public key in the release artifact produced by +`shorebird release` and cause the released app to require signed patches. -:::tip[Enterprise Key Management] +### Create a Signed Patch -For production environments, we recommend using `--public-key-cmd` and -`--sign-cmd` to integrate with your existing key management infrastructure -rather than storing keys on disk. See [Cloud KMS Examples](#cloud-kms-examples) -for integration patterns with AWS KMS, GCP Cloud KMS, HashiCorp Vault, and more. +To create a signed patch, run the following command: -::: +```sh +# Build Patch with local path to key files +shorebird patch android --public-key-path /path/to/public.pem \ + --private-key-path /path/to/private.pem + +# Build Patch with cloud-managed signing +# Ensure that the command outputs a PEM-encoded public key to stdout +# sign-cmd Should read data from stdin and outputs a base64 signature to +#stdout + shorebird patch android \ + --public-key-cmd="your-command-that-outputs-pem-public-key" \ + --sign-cmd="your-command-that-signs-stdin-and-outputs-base64" +``` -### Test it out +This tells shorebird to sign the patch with the key pair you provided. + +### Test and Verify Signed Patch You can verify that the patch is properly signed using `shorebird preview`. On the first launch, you should see something like the following in your app logs: @@ -162,20 +155,14 @@ patch at boot time. It will instead boot from the last known good patch (if still on disk) or the release build of the app. This will not cause your app to crash. -If for any reason you were to lose your private key, there is no way to create a -patch for an application containing the corresponding public key. Even Shorebird -is not able to create a patch for your application without your private key. In -such a case, you would need to make and distribute a new release of your -application to send patches to it. - ## Trade Offs -Signature verification adds a small overhead at app launch (under 50ms in our -testing with a medium size app on a 5-year-old Android phone). This overhead -increases with application size. For very large apps, if this overhead shows up -on your benchmarks, you can set `patch_verification: install_only` in -`shorebird.yaml` to verify signatures only when patches are installed rather -than on every launch. +Signature verification does add a small overhead at app launch. During our +testing this has been obvserved to be under 50ms with a medium size app on a +5-year-old Android phone. This overhead increases with application size. For +very large apps, if this overhead shows up on your benchmarks, you can set +`patch_verification: install_only` in `shorebird.yaml` to verify signatures only +when patches are installed rather than on every launch. ## Cloud KMS Examples @@ -184,9 +171,6 @@ popular key management services using `--public-key-cmd` and `--sign-cmd`. ### HashiCorp Vault -Vault's Transit secrets engine provides cryptographic operations without -exposing keys: - ```sh # Store your key in Vault Transit vault write transit/keys/shorebird-signing type=rsa-2048 @@ -204,8 +188,6 @@ shorebird patch android \ ### GCP Cloud KMS -GCP Cloud KMS outputs PEM format natively: - ```sh # Create a key ring and key gcloud kms keyrings create shorebird --location=global @@ -228,13 +210,12 @@ shorebird patch android \ ### AWS KMS -AWS KMS outputs DER format, which needs conversion to PEM: - ```sh # Create an RSA signing key aws kms create-key --key-spec RSA_2048 --key-usage SIGN_VERIFY -# Create a helper script for public key (aws-kms-pubkey.sh) +# Create a helper script for public key (aws-kms-pubkey.sh). +# Needed to get the format correct from DER to PEM #!/bin/bash aws kms get-public-key --key-id alias/shorebird-signing --output text \ --query PublicKey | base64 -d | openssl rsa -pubin -inform DER -outform PEM @@ -285,8 +266,6 @@ shorebird patch android \ ### 1Password CLI -1Password can store and retrieve keys securely: - ```sh # Store your keys in 1Password op item create --category="Secure Note" --title="Shorebird Signing" \ @@ -307,56 +286,3 @@ shorebird patch android \ --public-key-cmd="op item get 'Shorebird Signing' --fields public_key" \ --sign-cmd="./1password-sign.sh" ``` - -### macOS Keychain (Local Development) - -For local development on macOS, you can use the system keychain: - -```sh -# Import your key into the keychain -security import private.pem -k ~/Library/Keychains/login.keychain-db - -# Helper script for signing (keychain-sign.sh) -#!/bin/bash -# Note: This requires the key to be stored as an identity -security find-identity -v -p codesigning # List available identities -cat - | openssl dgst -sha256 -sign <(security find-key -l "your-key-label" \ - -w ~/Library/Keychains/login.keychain-db) | base64 - -# For simpler setups, store the PEM in keychain as a generic password -security add-generic-password -a "shorebird" -s "signing-key" \ - -w "$(cat private.pem)" - -# Helper script using generic password -#!/bin/bash -KEY=$(security find-generic-password -a "shorebird" -s "signing-key" -w) -cat - | openssl dgst -sha256 -sign <(echo "$KEY") | base64 -``` - -### CI/CD Integration Tips - -When using command-based signing in CI/CD pipelines: - -1. **Use environment variables** for sensitive configuration (key IDs, vault - addresses) -2. **Authenticate before running Shorebird** - ensure your cloud CLI is - authenticated (e.g., `gcloud auth`, `aws configure`, `vault login`) -3. **Use service accounts** with minimal permissions for automated pipelines -4. **Consider wrapper scripts** that handle authentication and error handling -5. **Test commands independently** before integrating with Shorebird - -Example GitHub Actions workflow: - -```yaml -- name: Authenticate to GCP - uses: google-github-actions/auth@v2 - with: - credentials_json: ${{ secrets.GCP_SA_KEY }} - -- name: Create signed patch - run: | - shorebird patch android \ - --public-key-cmd="gcloud kms keys versions get-public-key 1 \ - --key=signing-key --keyring=shorebird --location=global" \ - --sign-cmd="./scripts/gcp-sign.sh" -``` From 542680c6ad1308bcb595e35a427d07df5c8cbb08 Mon Sep 17 00:00:00 2001 From: Tom Arra Date: Fri, 6 Feb 2026 13:25:57 -0600 Subject: [PATCH 14/14] spelling --- .cspell.yaml | 2 ++ src/content/docs/code-push/guides/patch-signing.mdx | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.cspell.yaml b/.cspell.yaml index 82e8a2e1..ab7de148 100644 --- a/.cspell.yaml +++ b/.cspell.yaml @@ -45,9 +45,11 @@ words: - mipmap - mozallowfullscreen - nubank + - outform - podfile - prefs - pubin + - pubout - previewable - recompiles - riverpod diff --git a/src/content/docs/code-push/guides/patch-signing.mdx b/src/content/docs/code-push/guides/patch-signing.mdx index 1df7c593..e162d868 100644 --- a/src/content/docs/code-push/guides/patch-signing.mdx +++ b/src/content/docs/code-push/guides/patch-signing.mdx @@ -5,10 +5,8 @@ sidebar: order: 19 --- -{/* cspell:words outform pubout */} - In addition to our default security measures, Shorebird also provides patch -signing for additonal security. This is optional at this time and needs to be +signing for additional security. This is optional at this time and needs to be setup during your build and patch process. Patch signing allows developers to cryptographically sign patch updates with @@ -158,7 +156,7 @@ crash. ## Trade Offs Signature verification does add a small overhead at app launch. During our -testing this has been obvserved to be under 50ms with a medium size app on a +testing this has been observed to be under 50ms with a medium size app on a 5-year-old Android phone. This overhead increases with application size. For very large apps, if this overhead shows up on your benchmarks, you can set `patch_verification: install_only` in `shorebird.yaml` to verify signatures only