@capgo/cli 4.2.3 → 5.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -128,8 +128,8 @@ Optionally, you can give:
128
128
  * `--path [/path/to/my/bundle]` to upload a specific folder.
129
129
  * `--channel [test]` to upload to a specific channel.
130
130
  * `--external="https://mydomain.com/myapp.zip"` to link to an external URL instead of upload to Capgo cloud, it should be a zip URL in HTTPS.
131
- * `--key [/path/to/my/private_key]` the path of your private key.
132
- * `--key-data [privateKey]` the private key data, if you want to use inline.
131
+ * `--key [/path/to/my/public_key]` the path of your public key.
132
+ * `--key-data [publicKey]` the public key data, if you want to use inline.
133
133
  * `--no-key` to ignore the signing key and send clear update.
134
134
  * `--bundle [1.0.0]` to set the bundle version number of the file to upload.
135
135
  * `--iv-session-key [key]` to send a custom session key to the cloud.
@@ -217,9 +217,9 @@ The command will print your `ivSessionKey`y and generate an encrypted zip, to us
217
217
 
218
218
  Optionally, you can give:
219
219
 
220
- `--key [/path/to/my/private_key]` the path of your private key.
220
+ `--key [/path/to/my/public_key]` the path of your public key.
221
221
 
222
- `--key-data [privateKey]` the private key data, if you want to use inline. This command is mainly used for test purpose, it will decrypt the zip and print the base64 decrypted session key in the console.
222
+ `--key-data [publicKey]` the public key data, if you want to use inline. This command is mainly used for test purpose, it will decrypt the zip and print the base64 decrypted session key in the console.
223
223
 
224
224
  ### **Zip**
225
225
 
@@ -304,9 +304,9 @@ Optionally, you can give: `--force` to overwrite the existing key. This command
304
304
 
305
305
  Optionally, you can give:
306
306
 
307
- `--key [/path/to/my/private_key]` the path of your private key.
307
+ `--key [/path/to/my/public_key]` the path of your public key.
308
308
 
309
- `--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.
309
+ `--key-data [publicKey]` the public 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.
310
310
  ## Dev contribution
311
311
 
312
312
  1. Install development dependencies
package/dist/index.js CHANGED
@@ -61137,7 +61137,7 @@ var {
61137
61137
  // package.json
61138
61138
  var package_default = {
61139
61139
  name: "@capgo/cli",
61140
- version: "4.2.3",
61140
+ version: "5.0.0-alpha.3",
61141
61141
  description: "A CLI to upload to capgo servers",
61142
61142
  main: "dist/index.js",
61143
61143
  bin: {
@@ -62565,6 +62565,19 @@ async function findMainFile() {
62565
62565
  }
62566
62566
  return mainFile;
62567
62567
  }
62568
+ async function checKOldEncryption() {
62569
+ const config = await getConfig();
62570
+ const { extConfig } = config.app;
62571
+ const hasPrivateKeyInConfig = !!extConfig?.plugins?.CapacitorUpdater?.privateKey;
62572
+ const hasPublicKeyInConfig = !!extConfig?.plugins?.CapacitorUpdater?.publicKey;
62573
+ if (hasPrivateKeyInConfig)
62574
+ f2.warning(`You still have privateKey in the capacitor config, this is deprecated, please remove it`);
62575
+ f2.warning(`Encryption with private will be ignored`);
62576
+ if (!hasPublicKeyInConfig) {
62577
+ f2.warning(`publicKey not found in capacitor config, please run npx @capgo/cli key save`);
62578
+ program.error("");
62579
+ }
62580
+ }
62568
62581
  async function updateOrCreateVersion(supabase, update) {
62569
62582
  return supabase.from("app_versions").upsert(update, { onConflict: "name,app_id" }).eq("app_id", update.app_id).eq("name", update.name);
62570
62583
  }
@@ -63144,16 +63157,14 @@ var import_config2 = __toESM(require_config());
63144
63157
  var import_node_crypto2 = require("node:crypto");
63145
63158
  var import_node_buffer2 = require("node:buffer");
63146
63159
  var algorithm = "aes-128-cbc";
63147
- var oaepHash = "sha256";
63148
63160
  var formatB64 = "base64";
63149
- var padding = import_node_crypto2.constants.RSA_PKCS1_OAEP_PADDING;
63150
- function decryptSource(source, ivSessionKey, privateKey) {
63161
+ var padding = import_node_crypto2.constants.RSA_PKCS1_PADDING;
63162
+ function decryptSource(source, ivSessionKey, key2) {
63151
63163
  const [ivB64, sessionb64Encrypted] = ivSessionKey.split(":");
63152
- const sessionKey = (0, import_node_crypto2.privateDecrypt)(
63164
+ const sessionKey = (0, import_node_crypto2.publicDecrypt)(
63153
63165
  {
63154
- key: privateKey,
63155
- padding,
63156
- oaepHash
63166
+ key: key2,
63167
+ padding
63157
63168
  },
63158
63169
  import_node_buffer2.Buffer.from(sessionb64Encrypted, formatB64)
63159
63170
  );
@@ -63163,17 +63174,16 @@ function decryptSource(source, ivSessionKey, privateKey) {
63163
63174
  const decryptedData = import_node_buffer2.Buffer.concat([decipher.update(source), decipher.final()]);
63164
63175
  return decryptedData;
63165
63176
  }
63166
- function encryptSource(source, publicKey) {
63177
+ function encryptSource(source, key2) {
63167
63178
  const initVector = (0, import_node_crypto2.randomBytes)(16);
63168
63179
  const sessionKey = (0, import_node_crypto2.randomBytes)(16);
63169
63180
  const cipher = (0, import_node_crypto2.createCipheriv)(algorithm, sessionKey, initVector);
63170
63181
  cipher.setAutoPadding(true);
63171
63182
  const ivB64 = initVector.toString(formatB64);
63172
- const sessionb64Encrypted = (0, import_node_crypto2.publicEncrypt)(
63183
+ const sessionb64Encrypted = (0, import_node_crypto2.privateEncrypt)(
63173
63184
  {
63174
- key: publicKey,
63175
- padding,
63176
- oaepHash
63185
+ key: key2,
63186
+ padding
63177
63187
  },
63178
63188
  sessionKey
63179
63189
  ).toString(formatB64);
@@ -63207,18 +63217,28 @@ async function saveKey(options, log = true) {
63207
63217
  oe(`Save keys \u{1F511}`);
63208
63218
  const config = await getConfig();
63209
63219
  const { extConfig } = config.app;
63210
- const keyPath = options.key || baseKey;
63211
- let privateKey = options.keyData || "";
63212
- if (!(0, import_node_fs7.existsSync)(keyPath) && !privateKey) {
63220
+ const keyPath = options.key || baseKeyPub;
63221
+ let publicKey = options.keyData || "";
63222
+ if (!(0, import_node_fs7.existsSync)(keyPath) && !publicKey) {
63213
63223
  if (log) {
63214
- f2.error(`Cannot find public key ${keyPath} or as keyData option or in ${config.app.extConfigFilePath}`);
63224
+ f2.error(`Cannot find a public key at ${keyPath} or as keyData option or in ${config.app.extConfigFilePath}`);
63215
63225
  program.error("");
63216
63226
  } else {
63217
63227
  return false;
63218
63228
  }
63219
63229
  } else if ((0, import_node_fs7.existsSync)(keyPath)) {
63220
63230
  const keyFile = (0, import_node_fs7.readFileSync)(keyPath);
63221
- privateKey = keyFile.toString();
63231
+ publicKey = keyFile.toString();
63232
+ }
63233
+ if (publicKey) {
63234
+ if (!publicKey.startsWith("-----BEGIN RSA PUBLIC KEY-----")) {
63235
+ if (log) {
63236
+ f2.error(`the public key provided is not a valid RSA Public key`);
63237
+ program.error("");
63238
+ } else {
63239
+ return false;
63240
+ }
63241
+ }
63222
63242
  }
63223
63243
  if (extConfig) {
63224
63244
  if (!extConfig.plugins) {
@@ -63229,11 +63249,13 @@ async function saveKey(options, log = true) {
63229
63249
  }
63230
63250
  if (!extConfig.plugins.CapacitorUpdater)
63231
63251
  extConfig.plugins.CapacitorUpdater = {};
63232
- extConfig.plugins.CapacitorUpdater.privateKey = privateKey;
63252
+ if (extConfig.plugins.CapacitorUpdater.privateKey)
63253
+ delete extConfig.plugins.CapacitorUpdater.privateKey;
63254
+ extConfig.plugins.CapacitorUpdater.publicKey = publicKey;
63233
63255
  (0, import_config2.writeConfig)(extConfig, config.app.extConfigFilePath);
63234
63256
  }
63235
63257
  if (log) {
63236
- f2.success(`private key saved into ${config.app.extConfigFilePath} file in local directory`);
63258
+ f2.success(`public key saved into ${config.app.extConfigFilePath} file in local directory`);
63237
63259
  f2.success(`your app will decode the zip archive with this key`);
63238
63260
  }
63239
63261
  return true;
@@ -63274,19 +63296,23 @@ async function createKey(options, log = true) {
63274
63296
  CapacitorUpdater: {}
63275
63297
  };
63276
63298
  }
63277
- extConfig.plugins.CapacitorUpdater.privateKey = privateKey;
63299
+ if (!extConfig.plugins.CapacitorUpdater)
63300
+ extConfig.plugins.CapacitorUpdater = {};
63301
+ if (extConfig.plugins.CapacitorUpdater.privateKey)
63302
+ delete extConfig.plugins.CapacitorUpdater.privateKey;
63303
+ extConfig.plugins.CapacitorUpdater.publicKey = publicKey;
63278
63304
  (0, import_config2.writeConfig)(extConfig, config.app.extConfigFilePath);
63279
63305
  }
63280
63306
  if (log) {
63281
63307
  f2.success("Your RSA key has been generated");
63282
- f2.success(`Public key saved in ${baseKeyPub}`);
63308
+ f2.success(`Private key saved in ${baseKey}`);
63283
63309
  f2.success("This key will be use to encrypt your bundle before sending it to Capgo");
63284
63310
  f2.success("Keep it safe");
63285
63311
  f2.success("Than make it unreadable by Capgo and unmodifiable by anyone");
63286
- f2.success(`Private key saved in ${config.app.extConfigFilePath}`);
63312
+ f2.success(`Public key saved in ${config.app.extConfigFilePath}`);
63287
63313
  f2.success("Your app will be the only one having it");
63288
63314
  f2.success("Only your users can decrypt your update");
63289
- f2.success("Only you can send them an update");
63315
+ f2.success("Only your key can send them an update");
63290
63316
  $e(`Done \u2705`);
63291
63317
  }
63292
63318
  return true;
@@ -63463,7 +63489,7 @@ async function uploadBundle(appid, options, shouldExit = true) {
63463
63489
  oe(`Uploading`);
63464
63490
  await checkLatest();
63465
63491
  let { bundle: bundle2, path: path3, channel: channel2 } = options;
63466
- const { external, key: key2 = false, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options;
63492
+ const { external, key: key2, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options;
63467
63493
  let { minUpdateVersion } = options;
63468
63494
  options.apikey = options.apikey || findSavedKey();
63469
63495
  const snag = useLogSnag();
@@ -63586,11 +63612,14 @@ Trial expires in ${isTrial2} days`);
63586
63612
  s.start(`Calculating checksum`);
63587
63613
  checksum = await (0, import_checksum2.checksum)(zipped, "crc32");
63588
63614
  s.stop(`Checksum: ${checksum}`);
63589
- if (key2 || (0, import_node_fs8.existsSync)(baseKeyPub)) {
63590
- const publicKey = typeof key2 === "string" ? key2 : baseKeyPub;
63615
+ if (key2 === false) {
63616
+ f2.info(`Encryption ignored`);
63617
+ } else if (key2 || (0, import_node_fs8.existsSync)(baseKey)) {
63618
+ await checKOldEncryption();
63619
+ const privateKey = typeof key2 === "string" ? key2 : baseKey;
63591
63620
  let keyData = options.keyData || "";
63592
- if (!keyData && !(0, import_node_fs8.existsSync)(publicKey)) {
63593
- f2.error(`Cannot find public key ${publicKey}`);
63621
+ if (!keyData && !(0, import_node_fs8.existsSync)(privateKey)) {
63622
+ f2.error(`Cannot find private key ${privateKey}`);
63594
63623
  if (import_ci_info.default.isCI)
63595
63624
  program.error("");
63596
63625
  const res2 = await se({ message: "Do you want to use our public key ?" });
@@ -63611,7 +63640,7 @@ Trial expires in ${isTrial2} days`);
63611
63640
  notify: false
63612
63641
  }).catch();
63613
63642
  if (!keyData) {
63614
- const keyFile = (0, import_node_fs8.readFileSync)(publicKey);
63643
+ const keyFile = (0, import_node_fs8.readFileSync)(privateKey);
63615
63644
  keyData = keyFile.toString();
63616
63645
  }
63617
63646
  f2.info(`Encrypting your bundle`);
@@ -64415,23 +64444,29 @@ async function decryptZip(zipPath, ivsessionKey, options) {
64415
64444
  }
64416
64445
  const config = await getConfig();
64417
64446
  const { extConfig } = config.app;
64418
- if (!options.key && !(0, import_node_fs12.existsSync)(baseKey) && !extConfig.plugins?.CapacitorUpdater?.privateKey) {
64419
- f2.error(`Private Key not found at the path ${baseKey} or in ${config.app.extConfigFilePath}`);
64447
+ await checKOldEncryption();
64448
+ if (!options.key && !(0, import_node_fs12.existsSync)(baseKeyPub) && !extConfig.plugins?.CapacitorUpdater?.publicKey) {
64449
+ f2.error(`Public key not found at the path ${baseKeyPub} or in ${config.app.extConfigFilePath}`);
64420
64450
  program.error("");
64421
64451
  }
64422
- const keyPath = options.key || baseKey;
64423
- let privateKey = extConfig?.plugins?.CapacitorUpdater?.privateKey;
64424
- if (!(0, import_node_fs12.existsSync)(keyPath) && !privateKey) {
64425
- f2.error(`Cannot find public key ${keyPath} or as keyData option or in ${config.app.extConfigFilePath}`);
64452
+ const keyPath = options.key || baseKeyPub;
64453
+ let publicKey = extConfig?.plugins?.CapacitorUpdater?.publicKey;
64454
+ if (!(0, import_node_fs12.existsSync)(keyPath) && !publicKey) {
64455
+ f2.error(`Cannot find a public key at ${keyPath} or as keyData option or in ${config.app.extConfigFilePath}`);
64426
64456
  program.error("");
64427
64457
  } else if ((0, import_node_fs12.existsSync)(keyPath)) {
64428
64458
  const keyFile = (0, import_node_fs12.readFileSync)(keyPath);
64429
- privateKey = keyFile.toString();
64459
+ publicKey = keyFile.toString();
64460
+ }
64461
+ if (publicKey && !publicKey.startsWith("-----BEGIN RSA PUBLIC KEY-----")) {
64462
+ f2.error(`the public key provided is not a valid RSA Public key`);
64463
+ program.error("");
64430
64464
  }
64431
64465
  const zipFile = (0, import_node_fs12.readFileSync)(zipPath);
64432
- const decodedZip = decryptSource(zipFile, ivsessionKey, options.keyData ?? privateKey ?? "");
64466
+ const decodedZip = decryptSource(zipFile, ivsessionKey, options.keyData ?? publicKey ?? "");
64433
64467
  (0, import_node_fs12.writeFileSync)(`${zipPath}_decrypted.zip`, decodedZip);
64434
- $e(`Decrypted zip file at ${zipPath}_decrypted.zip`);
64468
+ f2.success(`Decrypted zip file at ${zipPath}_decrypted.zip`);
64469
+ $e(`Done \u2705`);
64435
64470
  import_node_process19.default.exit();
64436
64471
  }
64437
64472
 
@@ -64443,30 +64478,35 @@ async function encryptZip(zipPath, options) {
64443
64478
  oe(`Encryption`);
64444
64479
  await checkLatest();
64445
64480
  const localConfig = await getLocalConfig();
64481
+ await checKOldEncryption();
64446
64482
  if (!(0, import_node_fs13.existsSync)(zipPath)) {
64447
64483
  f2.error(`Error: Zip not found at the path ${zipPath}`);
64448
64484
  program.error("");
64449
64485
  }
64450
- const keyPath = options.key || baseKeyPub;
64451
- let publicKey = options.keyData || "";
64452
- if (!(0, import_node_fs13.existsSync)(keyPath) && !publicKey) {
64453
- f2.warning(`Cannot find public key ${keyPath} or as keyData option`);
64486
+ const keyPath = options.key || baseKey;
64487
+ let privateKey = options.keyData || "";
64488
+ if (!(0, import_node_fs13.existsSync)(keyPath) && !privateKey) {
64489
+ f2.warning(`Cannot find a private key at ${keyPath} or as a keyData option`);
64454
64490
  if (import_ci_info2.default.isCI) {
64455
- f2.error(`Error: Missing public key`);
64491
+ f2.error(`Error: Missing key`);
64456
64492
  program.error("");
64457
64493
  }
64458
- const res = await se({ message: "Do you want to use our public key ?" });
64494
+ const res = await se({ message: `Do you want to use our private key?` });
64459
64495
  if (!res) {
64460
- f2.error(`Error: Missing public key`);
64496
+ f2.error(`Error: Missing private key`);
64461
64497
  program.error("");
64462
64498
  }
64463
- publicKey = localConfig.signKey || "";
64499
+ privateKey = localConfig.signKey || "";
64464
64500
  } else if ((0, import_node_fs13.existsSync)(keyPath)) {
64465
64501
  const keyFile = (0, import_node_fs13.readFileSync)(keyPath);
64466
- publicKey = keyFile.toString();
64502
+ privateKey = keyFile.toString();
64503
+ }
64504
+ if (privateKey && !privateKey.startsWith("-----BEGIN RSA PRIVATE KEY-----")) {
64505
+ f2.error(`the private key provided is not a valid RSA Private key`);
64506
+ program.error("");
64467
64507
  }
64468
64508
  const zipFile = (0, import_node_fs13.readFileSync)(zipPath);
64469
- const encodedZip = encryptSource(zipFile, publicKey);
64509
+ const encodedZip = encryptSource(zipFile, privateKey);
64470
64510
  f2.success(`ivSessionKey: ${encodedZip.ivSessionKey}`);
64471
64511
  (0, import_node_fs13.writeFileSync)(`${zipPath}_encrypted.zip`, encodedZip.encryptedData);
64472
64512
  f2.success(`Encrypted zip saved at ${zipPath}_encrypted.zip`);
@@ -65124,7 +65164,7 @@ bundle.command("delete [bundleId] [appId]").alias("d").description("Delete a bun
65124
65164
  bundle.command("list [appId]").alias("l").description("List bundle in Capgo Cloud").action(listBundle).option("-a, --apikey <apikey>", "apikey to link to your account");
65125
65165
  bundle.command("unlink [appId]").description("Unlink a bundle in Capgo Cloud").action(listBundle).option("-a, --apikey <apikey>", "apikey to link to your account").option("-b, --bundle <bundle>", "bundle version number of the bundle to unlink");
65126
65166
  bundle.command("cleanup [appId]").alias("c").action(cleanupBundle).description("Cleanup bundle in Capgo Cloud").option("-b, --bundle <bundle>", "bundle version number of the app to delete").option("-a, --apikey <apikey>", "apikey to link to your account").option("-k, --keep <keep>", "number of version to keep").option("-f, --force", "force removal");
65127
- bundle.command("decrypt [zipPath] [sessionKey]").description("Decrypt a signed zip bundle").action(decryptZip).option("--key <key>", "custom path for private signing key").option("--key-data <keyData>", "base64 private signing key");
65167
+ bundle.command("decrypt [zipPath] [sessionKey]").description("Decrypt a signed zip bundle").action(decryptZip).option("--key <key>", "custom path for public signing key").option("--key-data <keyData>", "base64 public signing key");
65128
65168
  bundle.command("encrypt [zipPath]").description("Encrypt a zip bundle").action(encryptZip).option("--key <key>", "custom path for private signing key").option("--key-data <keyData>", "base64 private signing key");
65129
65169
  bundle.command("zip [appId]").description("Zip a bundle").action(zipBundle).option("-p, --path <path>", "path of the folder to upload").option("-b, --bundle <bundle>", "bundle version number to name the zip file").option("-n, --name <name>", "name of the zip file").option("-j, --json", "output in JSON").option("--no-code-check", "Ignore checking if notifyAppReady() is called in soure code and index present in root folder");
65130
65170
  var channel = program.command("channel").description("Manage channel");
@@ -65134,7 +65174,7 @@ channel.command("list [appId]").alias("l").description("List channel").action(li
65134
65174
  channel.command("currentBundle [channel] [appId]").description("Get current bundle for specific channel in Capgo Cloud").action(currentBundle).option("-c, --channel <channel>", "channel to get the current bundle from").option("-a, --apikey <apikey>", "apikey to link to your account").option("--quiet", "only print the bundle version");
65135
65175
  channel.command("set [channelId] [appId]").alias("s").description("Set channel").action(setChannel).option("-a, --apikey <apikey>", "apikey to link to your account").option("-b, --bundle <bundle>", "bundle version number of the file to set").option("-s, --state <state>", "set the state of the channel, default or normal").option("--latest", "get the latest version key in the package.json to set it to the channel").option("--downgrade", "Allow to downgrade to version under native one").option("--no-downgrade", "Disable downgrade to version under native one").option("--upgrade", "Allow to upgrade to version above native one").option("--no-upgrade", "Disable upgrade to version above native one").option("--ios", "Allow sending update to ios devices").option("--no-ios", "Disable sending update to ios devices").option("--android", "Allow sending update to android devices").option("--no-android", "Disable sending update to android devices").option("--self-assign", "Allow to device to self assign to this channel").option("--no-self-assign", "Disable devices to self assign to this channel").option("--disable-auto-update <disableAutoUpdate>", "Disable auto update strategy for this channel.The possible options are: major, minor, metadata, none");
65136
65176
  var key = program.command("key").description("Manage key");
65137
- key.command("save").description("Save base64 signing key in capacitor config, usefull for CI").action(saveKeyCommand).option("-f, --force", "force generate a new one").option("--key", "key path to save in capacitor config").option("--key-data", "key data to save in capacitor config");
65177
+ key.command("save").description("Save base64 signing key in capacitor config, useful for CI").action(saveKeyCommand).option("-f, --force", "force generate a new one").option("--key", "key path to save in capacitor config").option("--key-data <keyData>", "key data to save in capacitor config");
65138
65178
  key.command("create").description("Create a new signing key").action(createKeyCommand).option("-f, --force", "force generate a new one");
65139
65179
  program.command("upload [appId]").alias("u").description("(Deprecated) Upload a new bundle to Capgo Cloud").action(uploadDeprecatedCommand).option("-a, --apikey <apikey>", "apikey to link to your account").option("-p, --path <path>", "path of the folder to upload").option("-c, --channel <channel>", "channel to link to").option("-e, --external <url>", "link to external url intead of upload to Capgo Cloud").option("--key <key>", "custom path for public signing key").option("--key-data <keyData>", "base64 public signing key").option("--bundle-url", "prints bundle url into stdout").option("--no-key", "ignore signing key and send clear update").option("--display-iv-session", "Show in the console the iv and session key used to encrypt the update").option("-b, --bundle <bundle>", "bundle version number of the file to upload").option(
65140
65180
  "--min-update-version <minUpdateVersion>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/cli",
3
- "version": "4.2.3",
3
+ "version": "5.0.0-alpha.3",
4
4
  "description": "A CLI to upload to capgo servers",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/api/crypto.ts CHANGED
@@ -3,30 +3,31 @@ import {
3
3
  createCipheriv,
4
4
  createDecipheriv,
5
5
  generateKeyPairSync,
6
- privateDecrypt,
7
- publicEncrypt,
6
+ privateEncrypt,
7
+ publicDecrypt,
8
8
  randomBytes,
9
9
  } from 'node:crypto'
10
10
  import { Buffer } from 'node:buffer'
11
11
 
12
12
  const algorithm = 'aes-128-cbc'
13
- const oaepHash = 'sha256'
14
13
  const formatB64 = 'base64'
15
- const padding = constants.RSA_PKCS1_OAEP_PADDING
14
+ const padding = constants.RSA_PKCS1_PADDING
16
15
 
17
- export function decryptSource(source: Buffer, ivSessionKey: string, privateKey: string): Buffer {
16
+ export function decryptSource(source: Buffer, ivSessionKey: string, key: string): Buffer {
17
+ // console.log('decryptKeyType - ', decryptKeyType);
18
+ // console.log(key);
18
19
  // console.log('\nivSessionKey', ivSessionKey)
19
20
  const [ivB64, sessionb64Encrypted] = ivSessionKey.split(':')
20
21
  // console.log('\nsessionb64Encrypted', sessionb64Encrypted)
21
22
  // console.log('\nivB64', ivB64)
22
- const sessionKey = privateDecrypt(
23
+ const sessionKey = publicDecrypt(
23
24
  {
24
- key: privateKey,
25
+ key,
25
26
  padding,
26
- oaepHash,
27
27
  },
28
28
  Buffer.from(sessionb64Encrypted, formatB64),
29
29
  )
30
+
30
31
  // ivB64 to uft-8
31
32
  const initVector = Buffer.from(ivB64, formatB64)
32
33
  // console.log('\nSessionB64', sessionB64)
@@ -41,7 +42,10 @@ export interface Encoded {
41
42
  ivSessionKey: string
42
43
  encryptedData: Buffer
43
44
  }
44
- export function encryptSource(source: Buffer, publicKey: string): Encoded {
45
+ export function encryptSource(source: Buffer, key: string): Encoded {
46
+ // console.log('decryptKeyType - ', decryptKeyType);
47
+ // console.log(key);
48
+
45
49
  // encrypt zip with key
46
50
  const initVector = randomBytes(16)
47
51
  const sessionKey = randomBytes(16)
@@ -54,14 +58,15 @@ export function encryptSource(source: Buffer, publicKey: string): Encoded {
54
58
  // console.log('\nsessionB64', sessionB64)
55
59
  const ivB64 = initVector.toString(formatB64)
56
60
  // console.log('\nivB64', ivB64)
57
- const sessionb64Encrypted = publicEncrypt(
61
+
62
+ const sessionb64Encrypted = privateEncrypt(
58
63
  {
59
- key: publicKey,
64
+ key,
60
65
  padding,
61
- oaepHash,
62
66
  },
63
67
  sessionKey,
64
68
  ).toString(formatB64)
69
+
65
70
  // console.log('\nsessionb64Encrypted', sessionb64Encrypted)
66
71
  const ivSessionKey = `${ivB64}:${sessionb64Encrypted}`
67
72
  // console.log('\nivSessionKey', sessionKey)
@@ -3,7 +3,7 @@ import process from 'node:process'
3
3
  import { program } from 'commander'
4
4
  import * as p from '@clack/prompts'
5
5
  import { decryptSource } from '../api/crypto'
6
- import { baseKey, getConfig } from '../utils'
6
+ import { baseKeyPub, checKOldEncryption, getConfig } from '../utils'
7
7
  import { checkLatest } from '../api/update'
8
8
 
9
9
  interface Options {
@@ -23,32 +23,43 @@ export async function decryptZip(zipPath: string, ivsessionKey: string, options:
23
23
 
24
24
  const config = await getConfig()
25
25
  const { extConfig } = config.app
26
+ // console.log('config - ', config)
27
+ // console.log('extConfig - ', extConfig)
26
28
 
27
- if (!options.key && !existsSync(baseKey) && !extConfig.plugins?.CapacitorUpdater?.privateKey) {
28
- p.log.error(`Private Key not found at the path ${baseKey} or in ${config.app.extConfigFilePath}`)
29
+ await checKOldEncryption()
30
+ // console.log(`There ${hasPrivateKeyInConfig ? 'IS' : 'IS NOT'} a privateKey in the config`);
31
+
32
+ if (!options.key && !existsSync(baseKeyPub) && !extConfig.plugins?.CapacitorUpdater?.publicKey) {
33
+ p.log.error(`Public key not found at the path ${baseKeyPub} or in ${config.app.extConfigFilePath}`)
29
34
  program.error('')
30
35
  }
31
- const keyPath = options.key || baseKey
32
- // check if publicKey exist
36
+ const keyPath = options.key || baseKeyPub
37
+ // check if private exist
33
38
 
34
- let privateKey = extConfig?.plugins?.CapacitorUpdater?.privateKey
39
+ let publicKey = extConfig?.plugins?.CapacitorUpdater?.publicKey
35
40
 
36
- if (!existsSync(keyPath) && !privateKey) {
37
- p.log.error(`Cannot find public key ${keyPath} or as keyData option or in ${config.app.extConfigFilePath}`)
41
+ if (!existsSync(keyPath) && !publicKey) {
42
+ p.log.error(`Cannot find a public key at ${keyPath} or as keyData option or in ${config.app.extConfigFilePath}`)
38
43
  program.error('')
39
44
  }
40
45
  else if (existsSync(keyPath)) {
41
46
  // open with fs publicKey path
42
47
  const keyFile = readFileSync(keyPath)
43
- privateKey = keyFile.toString()
48
+ publicKey = keyFile.toString()
49
+ }
50
+
51
+ // let's doublecheck and make sure the key we are using is the right type based on the decryption strategy
52
+ if (publicKey && !publicKey.startsWith('-----BEGIN RSA PUBLIC KEY-----')) {
53
+ p.log.error(`the public key provided is not a valid RSA Public key`)
54
+ program.error('')
44
55
  }
45
- // console.log('privateKey', privateKey)
46
56
 
47
57
  const zipFile = readFileSync(zipPath)
48
58
 
49
- const decodedZip = decryptSource(zipFile, ivsessionKey, options.keyData ?? privateKey ?? '')
59
+ const decodedZip = decryptSource(zipFile, ivsessionKey, options.keyData ?? publicKey ?? '')
50
60
  // write decodedZip in a file
51
61
  writeFileSync(`${zipPath}_decrypted.zip`, decodedZip)
52
- p.outro(`Decrypted zip file at ${zipPath}_decrypted.zip`)
62
+ p.log.success(`Decrypted zip file at ${zipPath}_decrypted.zip`)
63
+ p.outro(`Done ✅`)
53
64
  process.exit()
54
65
  }
@@ -5,7 +5,7 @@ import ciDetect from 'ci-info'
5
5
  import * as p from '@clack/prompts'
6
6
  import { checkLatest } from '../api/update'
7
7
  import { encryptSource } from '../api/crypto'
8
- import { baseKeyPub, getLocalConfig } from '../utils'
8
+ import { baseKey, checKOldEncryption, getLocalConfig } from '../utils'
9
9
 
10
10
  interface Options {
11
11
  key?: string
@@ -17,40 +17,49 @@ export async function encryptZip(zipPath: string, options: Options) {
17
17
 
18
18
  await checkLatest()
19
19
  const localConfig = await getLocalConfig()
20
+ // console.log('localConfig - ', localConfig)
21
+ // console.log('config - ', config)
20
22
 
21
- // write in file .capgo the apikey in home directory
23
+ await checKOldEncryption()
22
24
 
23
25
  if (!existsSync(zipPath)) {
24
26
  p.log.error(`Error: Zip not found at the path ${zipPath}`)
25
27
  program.error('')
26
28
  }
27
29
 
28
- const keyPath = options.key || baseKeyPub
29
- // check if publicKey exist
30
+ const keyPath = options.key || baseKey
31
+ // check if privateKey exist
30
32
 
31
- let publicKey = options.keyData || ''
33
+ let privateKey = options.keyData || ''
32
34
 
33
- if (!existsSync(keyPath) && !publicKey) {
34
- p.log.warning(`Cannot find public key ${keyPath} or as keyData option`)
35
+ if (!existsSync(keyPath) && !privateKey) {
36
+ p.log.warning(`Cannot find a private key at ${keyPath} or as a keyData option`)
35
37
  if (ciDetect.isCI) {
36
- p.log.error(`Error: Missing public key`)
38
+ p.log.error(`Error: Missing key`)
37
39
  program.error('')
38
40
  }
39
- const res = await p.confirm({ message: 'Do you want to use our public key ?' })
41
+ const res = await p.confirm({ message: `Do you want to use our private key?` })
40
42
  if (!res) {
41
- p.log.error(`Error: Missing public key`)
43
+ p.log.error(`Error: Missing private key`)
42
44
  program.error('')
43
45
  }
44
- publicKey = localConfig.signKey || ''
46
+
47
+ privateKey = localConfig.signKey || ''
45
48
  }
46
49
  else if (existsSync(keyPath)) {
47
- // open with fs publicKey path
50
+ // open with fs key path
48
51
  const keyFile = readFileSync(keyPath)
49
- publicKey = keyFile.toString()
52
+ privateKey = keyFile.toString()
53
+ }
54
+
55
+ // let's doublecheck and make sure the key we are using is the right type based on the decryption strategy
56
+ if (privateKey && !privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----')) {
57
+ p.log.error(`the private key provided is not a valid RSA Private key`)
58
+ program.error('')
50
59
  }
51
60
 
52
61
  const zipFile = readFileSync(zipPath)
53
- const encodedZip = encryptSource(zipFile, publicKey)
62
+ const encodedZip = encryptSource(zipFile, privateKey)
54
63
  p.log.success(`ivSessionKey: ${encodedZip.ivSessionKey}`)
55
64
  // write decodedZip in a file
56
65
  writeFileSync(`${zipPath}_encrypted.zip`, encodedZip.encryptedData)
@@ -16,7 +16,8 @@ import type {
16
16
  } from '../utils'
17
17
  import {
18
18
  OrganizationPerm,
19
- baseKeyPub,
19
+ baseKey,
20
+ checKOldEncryption,
20
21
  checkCompatibility,
21
22
  checkPlanValid,
22
23
  convertAppName,
@@ -60,7 +61,7 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
60
61
  p.intro(`Uploading`)
61
62
  await checkLatest()
62
63
  let { bundle, path, channel } = options
63
- const { external, key = false, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options
64
+ const { external, key, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options
64
65
  let { minUpdateVersion } = options
65
66
  options.apikey = options.apikey || findSavedKey()
66
67
  const snag = useLogSnag()
@@ -227,12 +228,16 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
227
228
  s.start(`Calculating checksum`)
228
229
  checksum = await getChecksum(zipped, 'crc32')
229
230
  s.stop(`Checksum: ${checksum}`)
230
- if (key || existsSync(baseKeyPub)) {
231
- const publicKey = typeof key === 'string' ? key : baseKeyPub
231
+ if (key === false) {
232
+ p.log.info(`Encryption ignored`)
233
+ }
234
+ else if (key || existsSync(baseKey)) {
235
+ await checKOldEncryption()
236
+ const privateKey = typeof key === 'string' ? key : baseKey
232
237
  let keyData = options.keyData || ''
233
- // check if publicKey exist
234
- if (!keyData && !existsSync(publicKey)) {
235
- p.log.error(`Cannot find public key ${publicKey}`)
238
+ // check if privateKey exist
239
+ if (!keyData && !existsSync(privateKey)) {
240
+ p.log.error(`Cannot find private key ${privateKey}`)
236
241
  if (ciDetect.isCI)
237
242
  program.error('')
238
243
 
@@ -253,9 +258,9 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
253
258
  },
254
259
  notify: false,
255
260
  }).catch()
256
- // open with fs publicKey path
261
+ // open with fs privateKey path
257
262
  if (!keyData) {
258
- const keyFile = readFileSync(publicKey)
263
+ const keyFile = readFileSync(privateKey)
259
264
  keyData = keyFile.toString()
260
265
  }
261
266
  // encrypt
package/src/index.ts CHANGED
@@ -169,8 +169,8 @@ bundle
169
169
  .command('decrypt [zipPath] [sessionKey]')
170
170
  .description('Decrypt a signed zip bundle')
171
171
  .action(decryptZip)
172
- .option('--key <key>', 'custom path for private signing key')
173
- .option('--key-data <keyData>', 'base64 private signing key')
172
+ .option('--key <key>', 'custom path for public signing key')
173
+ .option('--key-data <keyData>', 'base64 public signing key')
174
174
 
175
175
  bundle
176
176
  .command('encrypt [zipPath]')
@@ -250,11 +250,11 @@ const key = program
250
250
 
251
251
  key
252
252
  .command('save')
253
- .description('Save base64 signing key in capacitor config, usefull for CI')
253
+ .description('Save base64 signing key in capacitor config, useful for CI')
254
254
  .action(saveKeyCommand)
255
255
  .option('-f, --force', 'force generate a new one')
256
256
  .option('--key', 'key path to save in capacitor config')
257
- .option('--key-data', 'key data to save in capacitor config')
257
+ .option('--key-data <keyData>', 'key data to save in capacitor config')
258
258
 
259
259
  key
260
260
  .command('create')