Skip to content

Commit

Permalink
Merge pull request #237 from Cap-go/encryption_v2
Browse files Browse the repository at this point in the history
doc: encryption v2 migration
  • Loading branch information
riderx authored Sep 3, 2024
2 parents 99963fd + 9c9fd6d commit 43f8ced
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 74 deletions.
2 changes: 1 addition & 1 deletion loadedVectorStore/docstore.json
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@
[
"544dcd90-aa3e-4014-91c0-88c7ad9ba0fb",
{
"pageContent": "> This command will ignore bundles which are currently in use in any channel\n\n## End-to-End encryption (Zero trust)\n\nCapgo support end-to-end encryption, this mean that your code is encrypted before send to the cloud and decrypted on the device.\nFor that, you need to generate an RSA key pair, you can use the following command to generate it.\n\nThe encryption system is a combination of RSA and AES, the RSA key is used to encrypt the AES key, and the AES key is used to encrypt the file.\n\nSee below for more information about the encryption system.\n\n![crypto_explained](/crypto_explained.webp)\n\n### Create key for your app\n`npx @capgo/cli key create`\n\nOptionally, you can give:\n`--force` to overwrite the existing key.\nThis command will create for you a key pair in your app, and will ask you to save the private key in a safe place.\nIt's recommended to not git commit the private and public key, and to not share it with anyone.\n\n> After your local test remove the key from config file and add it on CI step with `key save`\n\n### Save key in your app config\n`npx @capgo/cli key save`\n\nOptionally, you can give:\n`--key [/path/to/my/private_key]` the path of your private key.\n`--key-data [privateKey]` the private key data, if you want to use inline.\nThis command is useful if you followed the recommendation and didn't commit the key in your app, and in the config.\n\n### Encrypt zip with your key\n`npx @capgo/cli encrypt [path/to/zip]`\nOptionally, you can give:\n`--key [/path/to/my/private_key]` the path of your private key.\n`--key-data [privateKey]` the private key data, if you want to use inline.\nThis command is use when you use external source to store your code or for test purpose.\nThe command will print your ivSessionKey and the encrypted zip, you can use it with the `--iv-session-key` and `--external` option of the `upload` command, or for decrypting the zip.\n\n\n### Decrypt zip with your key\n`npx @capgo/cli encrypt [path/to/zip] [ivSessionKey]`\n\nOptionally, you can give:\n`--key [/path/to/my/private_key]` the path of your private key.\n`--key-data [privateKey]` the private key data, if you want to use inline.\nThis command is mainly used for test purpose, it will decrypt the zip and print the base64 decrypted session key in the console.\n\n## Dev contribution\n\n1. Install development dependencies\n\n ```shell\n rm -rf node_modules\n npm i\n ```\n\n2. Set `\"sourceMap\": true,` in `tsconfig.json`\n\n3. Run webpack development server\n\n ```shell\n npm run dev\n ```\n\n4. Attach debugger to the process started with `npm run dev`\n\n > VS Code:\n\n - Run `Debug on fixtures` launch configuration\n - Edit configuration to debug on different files\n\n > Other IDEs:\n\n - Attach debugger of your choice to the running process, use `.vscode/launch.json` `Debug on fixtures` configuration as the example\n\n## Production build\n\n1. Set `\"sourceMap\": false,` in `tsconfig.json`\n\n > TODO: add separate build config\n\n2. Run",
"pageContent": "> This command will ignore bundles which are currently in use in any channel\n\n## End-to-End encryption (Zero trust)\n\nCapgo support end-to-end encryption, this mean that your code is encrypted before send to the cloud and decrypted on the device.\nFor that, you need to generate an RSA key pair, you can use the following command to generate it.\n\nThe encryption system is a combination of RSA and AES, the RSA key is used to encrypt the AES key, and the AES key is used to encrypt the file.\n\nSee below for more information about the encryption system.\n\n![crypto_explained](/crypto_explained.webp)\n\n### Create key for your app\n`npx @capgo/cli key create`\n\nOptionally, you can give:\n`--force` to overwrite the existing key.\nThis command will create for you a key pair in your app, and will ask you to save the private key in a safe place.\nIt's recommended to not git commit the private key, and to not share it with anyone.\n\n> After your local test remove the key from config file and add it on CI step with `key save`\n\n### Save key in your app config\n`npx @capgo/cli key save`\n\nOptionally, you can give:\n`--key [/path/to/my/private_key]` the path of your private key.\n`--key-data [privateKey]` the private key data, if you want to use inline.\nThis command is useful if you followed the recommendation and didn't commit the key in your app, and in the config.\n\n### Encrypt zip with your key\n`npx @capgo/cli encrypt [path/to/zip]`\nOptionally, you can give:\n`--key [/path/to/my/private_key]` the path of your private key.\n`--key-data [privateKey]` the private key data, if you want to use inline.\nThis command is use when you use external source to store your code or for test purpose.\nThe command will print your ivSessionKey and the encrypted zip, you can use it with the `--iv-session-key` and `--external` option of the `upload` command, or for decrypting the zip.\n\n\n### Decrypt zip with your key\n`npx @capgo/cli encrypt [path/to/zip] [ivSessionKey]`\n\nOptionally, you can give:\n`--key [/path/to/my/private_key]` the path of your private key.\n`--key-data [privateKey]` the private key data, if you want to use inline.\nThis command is mainly used for test purpose, it will decrypt the zip and print the base64 decrypted session key in the console.\n\n## Dev contribution\n\n1. Install development dependencies\n\n ```shell\n rm -rf node_modules\n npm i\n ```\n\n2. Set `\"sourceMap\": true,` in `tsconfig.json`\n\n3. Run webpack development server\n\n ```shell\n npm run dev\n ```\n\n4. Attach debugger to the process started with `npm run dev`\n\n > VS Code:\n\n - Run `Debug on fixtures` launch configuration\n - Edit configuration to debug on different files\n\n > Other IDEs:\n\n - Attach debugger of your choice to the running process, use `.vscode/launch.json` `Debug on fixtures` configuration as the example\n\n## Production build\n\n1. Set `\"sourceMap\": false,` in `tsconfig.json`\n\n > TODO: add separate build config\n\n2. Run",
"metadata": { "source": "https://raw.githubusercontent.com/Cap-go/capgo-cli/main/README.md", "loc": { "lines": { "from": 143, "to": 225 } } }
}
],
Expand Down
Binary file modified public/encryption_flow.webp
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Using RSA + AES cryptography to encrypt updates, designed for the e
author: Martin Donadieu
author_url: https://x.com/martindonadieu
created_at: 2022-11-27
updated_at: 2023-06-29
updated_at: 2024-08-27
head_image: "/secure_upload.webp"
head_image_alt: Secure upload Capgo
tag: Solution
Expand Down Expand Up @@ -51,16 +51,26 @@ Here is a simple* schema to explain how it works:
- RSA: Rivest–Shamir–Adleman, an asymmetric encryption algorithm, two keys are used: a public key and a private key.
- Cypher: The encrypted data.
- Session key: An AES key used to encrypt and decrypt data.
- Checksum: A hash calculated for a file
- Signature: A checksum that was encrypted with a private RSA key. It can be verified with a public RSA key

We use AES to encrypt the update and RSA to encrypt the AES key. The AES key is encrypted with the public key of the developer. The developer’s private key is used to decrypt the AES key and decrypt the update.
We use the AES algorithm to encrypt the update. A random AES key is generated for every upload, then the AES key and checksum (hereafter "signature") are encrypted with the private RSA key of the developer. The developer’s public RSA key is used in the app to decrypt the AES key and the signature (converting it back to a checksum). Later, the decrypted AES key is used to decrypt the update; a checksum of the decrypted update is calculated, and it is compared with the decrypted signature.

We use two different encryption algorithms because RSA cannot be used to encrypt large amounts of data. AES is used to encrypt the update and RSA is used to encrypt the AES key.
We use two different encryption algorithms because RSA cannot be used to encrypt large amounts of data. AES is used to encrypt the update and RSA is used to encrypt the AES key and the checksum.

With this, Capgo cannot even read the content of your bundle, it can only verify the integrity of the bundle. This is a strong security model that is used by many enterprise customers.
With this, even Capgo cannot read the content of your bundle. This is a robust security model that is used by many enterprise customers.

**Update encryption V2 2024-08-27:**
- We switched the key type that is stored in the app. This was done in order to prevent inferring the public key (previously used for encryption) from the private key (previously used for decryption). Now, the app stores the public key (now used for decryption).
- We switched the checksum from the CRC32 algorithm to the SHA256 algorithm. We also started [signing the bundle](https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Signing_messages). When encryption V2 is configured, an update must have a valid signature. This is strictly enforced by the plugin.
- We now enforce a valid signature encryption V2 is configured.
These 3 changes have been done after a security analysis from a member of the community. They are here to prevent cryptographic attacks during update.

If you used encryption V1, migrate to V2 to benefit from the new security features. Follow the [migration instructions](/docs/cli/migrations/encryption/).

With end-to-end code signing, Capgo becomes a “trustless” cloud infrastructure. If one of Capgo’s cloud providers or even Capgo itself were to modify a code-signed update, end users’ devices would reject that update and run the previous, trusted update that’s already on the device.

While web-level HTTPS is sufficient for many Ionic apps, some large companies find the extra level of security from end-to-end code signing appealing. Some of these companies make finance apps that issue high-value, permanent transactions. Other companies have CISOs who include compromised cloud infrastructure in their threat models. We built end-to-end code signing in to Capgo for these use cases and are interested in hearing more from companies with higher-level security needs.
While web-level HTTPS is sufficient for many apps, some large companies find the extra level of security from end-to-end code signing appealing. Some of these companies make finance apps that issue high-value, permanent transactions. Other companies have CISOs who include compromised cloud infrastructure in their threat models. We built end-to-end code signing in to Capgo for these use cases and are interested in hearing more from companies with higher-level security needs.

## Getting started for enterprise customers

Expand All @@ -70,7 +80,7 @@ For large companies or projects who care deeply about security, we want to make
- Support for code signing development servers with both Capgo and development builds
- Production code signing on every update

Capgo code signing is available for all customers. To get started, follow the [setup instructions](/docs/tooling/cli/#end-to-end-encryption-trustless).
Capgo code signing is available for all customers. To get started, follow the [setup instructions](/docs/cli/commands/#end-to-end-encryption-trustless).

## Credits

Expand Down
68 changes: 1 addition & 67 deletions src/content/docs/docs/cli/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ Ecryption schema

`npx @capgo/cli key create`

Optionally, you can give: `--force` to overwrite the existing key. This command will create for you a key pair in your app, and will ask you to save the private key in a safe place. It's recommended to not git commit the private and public key, and to not share it with anyone.
Optionally, you can give: `--force` to overwrite the existing key. This command will create for you a key pair in your app, and will ask you to save the private key in a safe place. It's recommended to not git commit the private key, and to not share it with anyone.

> After your local test, remove the key from the config file and add it on the CI step with `key save`
Expand All @@ -405,72 +405,6 @@ Optionally, you can give:

`--key-data [privateKey]` the private key data, if you want to use inline. This command is useful if you followed the recommendation and didn't commit the key in your app, and in the config.

## Bundle signing

### Video tutorial

<YouTube id="cw8zCU2uGEg" title="Capgo bundle signing" />

### Text tutorial

Capgo offers the ability to cryptographically sign a bundle. This prevents tampering and ensures that only the holder of the private key can send a bundle.
This is achieved by a combination of RSA (4096 key) signing and SHA512 hashing.
It serves a different purpose than encryption and can be enabled besides it.
It is strongly recommended to enable this feature as it greatly increases the security of capgo updates

In order to do so, please run the following command

`npx @capgo/cli sign create`

This will create/modify the following files:
- `capacitor.config.ts`
- `.capgo_sign_key.priv`
- `.capgo_sign_key.pub`

:::danger
⚠️ Keep the `.capgo_sign_key.priv` a secret. DO NOT SHARE IT !!!
:::

After running this command your upload will automatically sign the bundles.

### Bundle signing without capgo cloud

It is possible to use this feature if you do not use capgo cloud. Please follow the steps to generate the keys.
In order to generate the signature for a file please run:

`npx @capgo/cli sign signFile ./file.zip`

This will generate a `./file.zip.capgo_sign` with the signature

Alternatively, you can pass the following arguments to change the output:

- `--json` - Prints the signature in the stdout in a JSON format
- `--stdout` - Doesn't generate the `.capgo_sign` and prints the signature in the stdout

### Bundle signing in the CI/CD

You should **NEVER** commit your private signing key. This makes it a bit difficult to use capgo in a CI/CD environment.
After configuring signing you will very likely see the following error:

<figure><img src="/ci-cd-signing-fail.webp" alt="Capgo CI/CD upload fail"/></figure>

It is quite easy to fix. First please export the private signing key using the following command.

`npx @capgo/cli sign exportPrivateKey`

Then, please copy the output and create a new CI/CD secret (`CAPGO_SIGN_PRIVATE_KEY`).

After, please create a new CI/CD step (here is an example for GitHub actions).

```yml
- name: "Import capgo's private signature key"
env:
CAPGO_SIGN_PRIVATE_KEY: ${{ secrets.CAPGO_SIGN_PRIVATE_KEY }}
run: npx @capgo/cli sign importPrivateKey --key $CAPGO_SIGN_PRIVATE_KEY
```
After doing this, your CI/CD workflow will upload bundles to capgo successfully.
## Ci integration

To automate your work, I recommend you make GitHub action do the job of pushing to our server
Expand Down
77 changes: 77 additions & 0 deletions src/content/docs/docs/cli/migrations/encryption.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: "Encryption"
description: "How to encrypt your data with new encryption"
sidebar:
order: 5
---

This documentation will explain how to encrypt your data with the new encryption system and remove the old one.

Learn more about the new encryption system in the [blog post](/blog/introducing-end-to-end-security-to-capacitor-updater-with-code-signing).

---

First, create a new key pair with the following command:

```bash
npx @capgo/cli key create
```

This command will create a new key pair in your app; it is imperative to store the private key in a safe place. One must never commit the private key to source control nor share it with an untrusted party.

This command will also remove the old key from your Capacitor config, but it will not remove the old key files. The CLI keeps them to allow you to continue sending live updates for the apps that haven't received an app store update and are still using the old plugin. This facilitates the migration.

When you are asked by the migration, "Do you want to setup encryption with the new channel in order to support old apps and facilitate the migration?", please agree. It will add a new "defaultChannel" option to your Capacitor config. This will make your app use the channel "encryption_v2". This will ensure that the new encryption is used only by apps that support it. Apps that have not received an app store update will continue using the previous default channel.

---

Now, you need to build your JS bundle and upload it to the new channel. Please run the following command:


```bash

npx @capgo/cli bundle upload --channel encryption_v2

```

---

Then, run this command to allow apps to self-assign to the channel "encryption_v2".


:::caution
This is necessary for the new "defaultChannel" option to work.
:::


```bash

npx @capgo/cli channel set encryption_v2 --self-assign

```

---

You can now run the app; it will use the new encryption system.

To upload the new JS bundle to the old channel, you only need to run the following command:

```bash
npx @capgo/cli bundle upload --channel production
```

---

You don't need to worry about Capacitor config, it is never uploaded to Capgo.

When all users have updated their apps (it can take up to 3/4 months), you can remove the "defaultChannel" from your Capacitor config.

And then, you can remove the old channel with the following command:

```bash
npx @capgo/cli channel delete encryption_v2
```

---

After deleting the "encryption_v2" channel, all apps that use it as the default will start using the "production" channel.

0 comments on commit 43f8ced

Please sign in to comment.