Skip to main content

Code signing with CodePush

Abstract

Code signing is a security mechanism that adds a digital signature to your CodePush bundles (JavaScript updates). This signature allows the client app to verify that a trusted source created the update and that it has not been tampered with during delivery.

Code signing is a security mechanism that adds a digital signature to your CodePush bundles (JavaScript updates). This signature allows the client app to verify that a trusted source created the update and that it has not been tampered with during delivery.

CodePush code signing is done in three stages:

  1. Generating an RSA keypair:

    • The private key is used to sign the CodePush bundles.

    • The public key is embedded into the mobile app to verify signatures.

  2. When releasing a CodePush update, the Bitrise CodePush CLI signs the bundle using the private key. It creates a JWT (JSON Web Token) containing the bundle's hash, digitally signed with this private key.

  3. The mobile app (with the embedded public key) verifies the JWT signature before applying the update. If verification fails, the update is rejected.

Signing your app

iOS

Android

  1. Use version 5.1.0 or higher of the CodePushNext React Native SDK. Earlier versions don't support code signing.

    You can find the SDK here: CodePushNext repository.

  2. Make sure the Bitrise CodePush CLI version is 1.0.0 or higher to take advantage of code signing features.

  3. Generate an RSA keypair in PEM format with Open SSL:

    openssl genrsa -out private_key.pem 2048
    openssl rsa -in private_key.pem -pubout -out public_key.pem

    You must keep the private key secure and never share it! The public key will be embedded inside the app itself.

  4. Add the public key string inside your app’s Info.plist:

    <key>CodePushPublicKey</key>
    <string>-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVJ2k...
    -----END PUBLIC KEY-----</string>
  5. Rebuild your iOS app with the updated react-native-code-push SDK (>= 5.1.0) that supports code signing.

  6. Bundle and sign your updates with the Bitrise CodePush CLI. The output directory must be named CodePush.

    bitrise :codepush bundle --platform ios --private-key-path ./private_key.pem

    The signed JWT (.codepushrelease file) is generated inside the bundle directory and uploaded to the server. The uploaded .zip file contains both the .codepushrelease file and the bundled output file.

  7. Push the already bundled update:

    bitrise :codepush push ./CodePush \
      --deployment Staging \
      --app-version 1.0.0 \
      --private-key-path ./private_key.pem

    Tip

    Optionally, you can bundle, sign, and push in one command:

    bitrise :codepush push --bundle --platform ios \
      --deployment Staging \
      --app-version 1.0.0 \
      --private-key-path ./private_key.pem
  1. Use version 5.1.0 or higher of the CodePushNext React Native SDK. Earlier versions don't support code signing.

    You can find the SDK here: CodePushNext repository.

  2. Make sure the Bitrise CodePush CLI version is 1.0.0 or higher to take advantage of code signing features.

  3. Generate an RSA keypair in PEM format with Open SSL:

    openssl genrsa -out private_key.pem 2048
    openssl rsa -in private_key.pem -pubout -out public_key.pem

    You must keep the private key secure and never share it! The public key will be embedded inside the app itself.

  4. Add the public key string in /android/app/src/main/res/values/strings.xml:

    <resources>
        <string name="CodePushPublicKey">-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVJ2k...
    -----END PUBLIC KEY-----</string>
    </resources>
  5. Configure the CodePush client instance.

    You can use a constructor:

    new CodePush("deployment-key", getApplicationContext(), BuildConfig.DEBUG, R.string.CodePushPublicKey);
    

    Or you can use a builder:

    new CodePushBuilder("deployment-key", getApplicationContext())
        .setIsDebugMode(BuildConfig.DEBUG)
        .setPublicKeyResourceDescriptor(R.string.CodePushPublicKey)
        .build();
  6. Rebuild your Android app with the updated react-native-code-push SDK (>= 5.1.0) that supports code signing.

  7. Bundle and sign your updates with the Bitrise CodePush CLI. The output directory must be named CodePush.

    bitrise :codepush bundle --platform android --private-key-path ./private_key.pem

    The signed JWT (.codepushrelease file) is generated inside the bundle directory and uploaded to the server. The uploaded .zip file contains both the .codepushrelease file and the bundled output file.

  8. Push the already bundled update:

    bitrise :codepush push ./CodePush \
      --deployment Staging \
      --app-version 1.0.0 \
      --private-key-path ./private_key.pem

    Tip

    Optionally, you can bundle, sign, and push in one command:

    bitrise :codepush push --bundle --platform android \
      --deployment Staging \
      --app-version 1.0.0 \
      --private-key-path ./private_key.pem

Code signing support for Expo

CodePushNext and the Bitrise CodePush CLI both support code signing for Expo projects, too. The overall flow is the same as for standard React Native apps: generate an RSA key pair, embed the public key in the app, and sign bundles at release time using the --private-key-path flag.

The main difference for managed Expo workflows is how the public key gets embedded: this typically requires EAS Build and a custom config plugin. When bundling and pushing updates, use the standard bitrise :codepush commands as usual.

Note

The --sourcemap-output flag is not supported for Expo projects and should be omitted.