@icure/api 5.0.1 → 5.0.4

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.
@@ -326,8 +326,9 @@ export declare class IccCryptoXApi {
326
326
  rawKey: string;
327
327
  }[];
328
328
  }, masterId: string): Promise<Array<string>>;
329
+ getPublicKeyFromPrivateKey(privateKey: JsonWebKey, dataOwner: Patient | Device | HealthcareParty): string;
329
330
  loadKeyPairsAsTextInBrowserLocalStorage(healthcarePartyId: string, privateKey: Uint8Array): Promise<void>;
330
- loadKeyPairsAsJwkInBrowserLocalStorage(healthcarePartyId: string, privKey: JsonWebKey): Promise<void>;
331
+ loadKeyPairsAsJwkInBrowserLocalStorage(healthcarePartyId: string, privateKey: JsonWebKey): Promise<void>;
331
332
  loadKeyPairsInBrowserLocalStorage(healthcarePartyId: string, file: Blob): Promise<void>;
332
333
  saveKeychainInBrowserLocalStorage(id: string, keychain: number): void;
333
334
  saveKeychainInBrowserLocalStorageAsBase64(id: string, keyChainB64: string): void;
@@ -368,9 +369,10 @@ export declare class IccCryptoXApi {
368
369
  * loads the RSA key pair (hcparty) in JWK from local storage, not imported
369
370
  *
370
371
  * @param id doc id - hcpartyId
372
+ * @param publicKeyFingerPrint the 32 last characters of public key this private key is associated with
371
373
  * @returns {Object} it is in JWK - not imported
372
374
  */
373
- loadKeyPairNotImported(id: string): {
375
+ loadKeyPairNotImported(id: string, publicKeyFingerPrint?: string): {
374
376
  publicKey: JsonWebKey;
375
377
  privateKey: JsonWebKey;
376
378
  };
@@ -200,7 +200,7 @@ class IccCryptoXApi {
200
200
  return delegatorAndKeys;
201
201
  }
202
202
  const fingerprint = pk.slice(-32);
203
- const keyPair = (_b = this.rsaKeyPairs[fingerprint]) !== null && _b !== void 0 ? _b : (yield this.cacheKeyPair(this.loadKeyPairNotImported(loggedHcPartyId)));
203
+ const keyPair = (_b = this.rsaKeyPairs[fingerprint]) !== null && _b !== void 0 ? _b : (yield this.cacheKeyPair(this.loadKeyPairNotImported(loggedHcPartyId, fingerprint)));
204
204
  if (!keyPair) {
205
205
  return;
206
206
  }
@@ -918,38 +918,48 @@ class IccCryptoXApi {
918
918
  return Promise.all(decryptPromises).then((genericSecretId) => genericSecretId.filter((id) => !!id));
919
919
  });
920
920
  }
921
+ getPublicKeyFromPrivateKey(privateKey, dataOwner) {
922
+ var _a;
923
+ if (!privateKey.n || !privateKey.e) {
924
+ throw new Error('No public key can be deduced from incomplete private key');
925
+ }
926
+ const publicKeyFromPrivateKey = (0, utils_1.jwk2spki)(privateKey);
927
+ const publicKeys = [dataOwner.publicKey].concat(Object.keys((_a = dataOwner.aesExchangeKeys) !== null && _a !== void 0 ? _a : {})).filter((x) => !!x);
928
+ if (!publicKeys.length) {
929
+ throw new Error('No public key has been defined for hcp');
930
+ }
931
+ const publicKey = publicKeys.find((it) => it === publicKeyFromPrivateKey);
932
+ if (!publicKey) {
933
+ throw new Error('No public key can be found for this private key');
934
+ }
935
+ return publicKey;
936
+ }
921
937
  loadKeyPairsAsTextInBrowserLocalStorage(healthcarePartyId, privateKey) {
922
- return this.getDataOwner(healthcarePartyId)
923
- .then(({ dataOwner }) => __awaiter(this, void 0, void 0, function* () {
924
- const publicKey = yield dataOwner.publicKey;
925
- if (!publicKey) {
926
- throw new Error('No public key has been defined for hcp');
927
- }
928
- return this._RSA.importKeyPair('jwk', (0, utils_1.pkcs8ToJwk)(privateKey), 'jwk', (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(publicKey)));
929
- }))
930
- .then((keyPair) => {
938
+ return __awaiter(this, void 0, void 0, function* () {
939
+ const { dataOwner } = yield this.getDataOwner(healthcarePartyId);
940
+ const privateKeyInJwk = (0, utils_1.pkcs8ToJwk)(privateKey);
941
+ const publicKey = this.getPublicKeyFromPrivateKey(privateKeyInJwk, dataOwner);
942
+ const keyPair = yield this._RSA.importKeyPair('jwk', privateKeyInJwk, 'jwk', (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(publicKey)));
931
943
  this.rsaKeyPairs[healthcarePartyId] = keyPair;
932
- return this._RSA.exportKeys(keyPair, 'jwk', 'jwk');
933
- })
934
- .then((exportedKeyPair) => {
935
- return this.storeKeyPair(healthcarePartyId, exportedKeyPair);
944
+ const exportedKeyPair = yield this._RSA.exportKeys(keyPair, 'jwk', 'jwk');
945
+ return this.storeKeyPair(`${healthcarePartyId}.${publicKey.slice(-32)}`, exportedKeyPair);
936
946
  });
937
947
  }
938
- // noinspection JSUnusedGlobalSymbols
939
- loadKeyPairsAsJwkInBrowserLocalStorage(healthcarePartyId, privKey) {
940
- return this.getDataOwner(healthcarePartyId)
941
- .then(({ dataOwner }) => {
942
- const pubKey = (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(dataOwner.publicKey));
943
- privKey.n = pubKey.n;
944
- privKey.e = pubKey.e;
945
- return this._RSA.importKeyPair('jwk', privKey, 'jwk', pubKey);
946
- })
947
- .then((keyPair) => {
948
+ loadKeyPairsAsJwkInBrowserLocalStorage(healthcarePartyId, privateKey) {
949
+ return __awaiter(this, void 0, void 0, function* () {
950
+ const { dataOwner } = yield this.getDataOwner(healthcarePartyId);
951
+ if ((!privateKey.n || !privateKey.e) && dataOwner.publicKey) {
952
+ //Fallback on default publicKey
953
+ console.warn('An incomplete key has been completed using the default public key of the data owner');
954
+ const publicKeyInJwk = (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(dataOwner.publicKey));
955
+ privateKey.n = publicKeyInJwk.n;
956
+ privateKey.e = publicKeyInJwk.e;
957
+ }
958
+ const publicKey = this.getPublicKeyFromPrivateKey(privateKey, dataOwner);
959
+ const keyPair = yield this._RSA.importKeyPair('jwk', privateKey, 'jwk', (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(publicKey)));
948
960
  this.rsaKeyPairs[healthcarePartyId] = keyPair;
949
- return this._RSA.exportKeys(keyPair, 'jwk', 'jwk');
950
- })
951
- .then((exportedKeyPair) => {
952
- return this.storeKeyPair(healthcarePartyId, exportedKeyPair);
961
+ const exportedKeyPair = yield this._RSA.exportKeys(keyPair, 'jwk', 'jwk');
962
+ return this.storeKeyPair(`${healthcarePartyId}.${publicKey.slice(-32)}`, exportedKeyPair);
953
963
  });
954
964
  }
955
965
  // noinspection JSUnusedGlobalSymbols
@@ -1116,15 +1126,21 @@ class IccCryptoXApi {
1116
1126
  * loads the RSA key pair (hcparty) in JWK from local storage, not imported
1117
1127
  *
1118
1128
  * @param id doc id - hcpartyId
1129
+ * @param publicKeyFingerPrint the 32 last characters of public key this private key is associated with
1119
1130
  * @returns {Object} it is in JWK - not imported
1120
1131
  */
1121
- loadKeyPairNotImported(id) {
1132
+ loadKeyPairNotImported(id, publicKeyFingerPrint) {
1133
+ var _a;
1122
1134
  if (typeof Storage === 'undefined') {
1123
1135
  console.log('Your browser does not support HTML5 Browser Local Storage !');
1124
1136
  throw 'Your browser does not support HTML5 Browser Local Storage !';
1125
1137
  }
1126
1138
  //TODO decryption
1127
- return JSON.parse(localStorage.getItem(this.rsaLocalStoreIdPrefix + id) || '{}');
1139
+ const item = (_a = (publicKeyFingerPrint && localStorage.getItem(this.rsaLocalStoreIdPrefix + id + '.' + publicKeyFingerPrint))) !== null && _a !== void 0 ? _a : localStorage.getItem(this.rsaLocalStoreIdPrefix + id);
1140
+ if (!item) {
1141
+ console.warn(`No key can be found in local storage for id ${id} and publicKeyFingerPrint ${publicKeyFingerPrint}`);
1142
+ }
1143
+ return JSON.parse(item);
1128
1144
  }
1129
1145
  /**
1130
1146
  * Loads and imports the RSA key pair (hcparty) from local storage
@@ -1415,22 +1431,28 @@ class IccCryptoXApi {
1415
1431
  }
1416
1432
  // noinspection JSUnusedGlobalSymbols
1417
1433
  checkPrivateKeyValidity(dataOwner) {
1418
- return new Promise((resolve) => {
1419
- this._RSA
1420
- .importKey('jwk', (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(dataOwner.publicKey)), ['encrypt'])
1421
- .then((k) => this._RSA.encrypt(k, (0, binary_utils_1.utf8_2ua)('shibboleth')))
1422
- .then((cipher) => {
1423
- const kp = this.loadKeyPairNotImported(dataOwner.id);
1424
- return this._RSA
1425
- .importKeyPair('jwk', kp.privateKey, 'jwk', kp.publicKey)
1426
- .then((ikp) => this._RSA.decrypt(ikp.privateKey, new Uint8Array(cipher)));
1427
- })
1428
- .then((plainText) => {
1429
- const pt = (0, binary_utils_1.ua2utf8)(plainText);
1430
- console.log(pt);
1431
- resolve(pt === 'shibboleth');
1432
- })
1433
- .catch(() => resolve(false));
1434
+ var _a;
1435
+ return __awaiter(this, void 0, void 0, function* () {
1436
+ const publicKeys = Array.from(new Set([dataOwner.publicKey].concat(Object.keys((_a = dataOwner.aesExchangeKeys) !== null && _a !== void 0 ? _a : {})).filter((x) => !!x)));
1437
+ return yield publicKeys.reduce((pres, publicKey) => __awaiter(this, void 0, void 0, function* () {
1438
+ const res = yield pres;
1439
+ if (res) {
1440
+ return true;
1441
+ }
1442
+ try {
1443
+ const k = yield this._RSA.importKey('jwk', (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(publicKey)), ['encrypt']);
1444
+ const cipher = yield this._RSA.encrypt(k, (0, binary_utils_1.utf8_2ua)('shibboleth'));
1445
+ const kp = this.loadKeyPairNotImported(dataOwner.id, publicKey.slice(-32));
1446
+ const plainText = yield this._RSA
1447
+ .importKeyPair('jwk', kp.privateKey, 'jwk', kp.publicKey)
1448
+ .then((ikp) => this._RSA.decrypt(ikp.privateKey, new Uint8Array(cipher)))
1449
+ .then((x) => (0, binary_utils_1.ua2utf8)(x));
1450
+ return plainText === 'shibboleth';
1451
+ }
1452
+ catch (e) {
1453
+ return false;
1454
+ }
1455
+ }), Promise.resolve(false));
1434
1456
  });
1435
1457
  }
1436
1458
  throwDetailedExceptionForInvalidParameter(argName, argValue, methodName, methodArgs) {