@icure/api 5.0.24 → 5.0.26

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.
Files changed (40) hide show
  1. package/icc-x-api/filters/HealthcarePartyByTagCodeFilter.d.ts +21 -0
  2. package/icc-x-api/filters/HealthcarePartyByTagCodeFilter.js +24 -0
  3. package/icc-x-api/filters/HealthcarePartyByTagCodeFilter.js.map +1 -0
  4. package/icc-x-api/filters/PatientByHcPartyGenderEducationProfession.js.map +1 -1
  5. package/icc-x-api/filters/filters.d.ts +1 -0
  6. package/icc-x-api/filters/filters.js +1 -0
  7. package/icc-x-api/filters/filters.js.map +1 -1
  8. package/icc-x-api/icc-accesslog-x-api.d.ts +1 -1
  9. package/icc-x-api/icc-accesslog-x-api.js +1 -1
  10. package/icc-x-api/icc-accesslog-x-api.js.map +1 -1
  11. package/icc-x-api/icc-calendar-item-x-api.d.ts +1 -1
  12. package/icc-x-api/icc-calendar-item-x-api.js +1 -1
  13. package/icc-x-api/icc-calendar-item-x-api.js.map +1 -1
  14. package/icc-x-api/icc-contact-x-api.js +1 -1
  15. package/icc-x-api/icc-contact-x-api.js.map +1 -1
  16. package/icc-x-api/icc-crypto-x-api.d.ts +25 -1
  17. package/icc-x-api/icc-crypto-x-api.js +202 -83
  18. package/icc-x-api/icc-crypto-x-api.js.map +1 -1
  19. package/icc-x-api/icc-data-owner-x-api.js.map +1 -1
  20. package/icc-x-api/icc-document-x-api.js +1 -1
  21. package/icc-x-api/icc-document-x-api.js.map +1 -1
  22. package/icc-x-api/icc-form-x-api.js +1 -1
  23. package/icc-x-api/icc-form-x-api.js.map +1 -1
  24. package/icc-x-api/icc-helement-x-api.js +1 -1
  25. package/icc-x-api/icc-helement-x-api.js.map +1 -1
  26. package/icc-x-api/icc-invoice-x-api.js +1 -1
  27. package/icc-x-api/icc-invoice-x-api.js.map +1 -1
  28. package/icc-x-api/icc-maintenance-task-x-api.js +1 -1
  29. package/icc-x-api/icc-maintenance-task-x-api.js.map +1 -1
  30. package/icc-x-api/icc-patient-x-api.js +1 -1
  31. package/icc-x-api/icc-patient-x-api.js.map +1 -1
  32. package/icc-x-api/icc-receipt-x-api.js +1 -1
  33. package/icc-x-api/icc-receipt-x-api.js.map +1 -1
  34. package/icc-x-api/icc-user-x-api.js.map +1 -1
  35. package/icc-x-api/index.js +1 -1
  36. package/icc-x-api/index.js.map +1 -1
  37. package/icc-x-api/utils/functional-util.d.ts +1 -0
  38. package/icc-x-api/utils/functional-util.js +19 -1
  39. package/icc-x-api/utils/functional-util.js.map +1 -1
  40. package/package.json +1 -1
@@ -415,8 +415,9 @@ class IccCryptoXApi {
415
415
  const { owner: modifiedOwner, aesExchangeKeys } = yield this.getOrCreateHcPartyKeys(owner, ownerId);
416
416
  const importedAESHcPartyKey = yield this.decryptAnyAesExchangeKeyForOwner(aesExchangeKeys, ownerId, ownerId, ownerId, publicKeys);
417
417
  const encryptedDelegation = yield this._AES.encrypt(importedAESHcPartyKey.key, (0, binary_utils_1.string2ua)(createdObject.id + ':' + secretId).buffer, importedAESHcPartyKey.rawKey);
418
- const encryptedSecretForeignKey = parentObject &&
419
- this._AES.encrypt(importedAESHcPartyKey.key, (0, binary_utils_1.string2ua)(createdObject.id + ':' + parentObject.id).buffer, importedAESHcPartyKey.rawKey);
418
+ const encryptedSecretForeignKey = parentObject
419
+ ? yield this._AES.encrypt(importedAESHcPartyKey.key, (0, binary_utils_1.string2ua)(createdObject.id + ':' + parentObject.id).buffer, importedAESHcPartyKey.rawKey)
420
+ : undefined;
420
421
  return {
421
422
  owner: modifiedOwner,
422
423
  delegations: _.fromPairs([
@@ -431,8 +432,8 @@ class IccCryptoXApi {
431
432
  ],
432
433
  ],
433
434
  ]),
434
- cryptedForeignKeys: (encryptedSecretForeignKey &&
435
- _.fromPairs([
435
+ cryptedForeignKeys: (encryptedSecretForeignKey
436
+ ? _.fromPairs([
436
437
  [
437
438
  ownerId,
438
439
  [
@@ -443,8 +444,8 @@ class IccCryptoXApi {
443
444
  },
444
445
  ],
445
446
  ],
446
- ])) ||
447
- {},
447
+ ])
448
+ : _) || {},
448
449
  secretForeignKeys: (secretForeignKeyOfParent && [secretForeignKeyOfParent]) || [],
449
450
  secretId: secretId,
450
451
  };
@@ -670,50 +671,46 @@ class IccCryptoXApi {
670
671
  return __awaiter(this, arguments, void 0, function* () {
671
672
  this.throwDetailedExceptionForInvalidParameter('modifiedObject.id', modifiedObject.id, 'appendEncryptionKeys', arguments); //modifiedObject should never be null
672
673
  this.throwDetailedExceptionForInvalidParameter('secretEncryptionKeyOfObject', secretEncryptionKeyOfObject, 'appendEncryptionKeys', arguments);
673
- return this.getDataOwner(ownerId)
674
- .then(({ dataOwner: owner }) => __awaiter(this, void 0, void 0, function* () {
675
- const publicKeys = yield this.getPublicKeys();
676
- const { owner: modifiedOwner, aesExchangeKeys } = yield this.getOrCreateHcPartyKeys(owner, delegateId);
677
- const importedAESHcPartyKey = yield this.decryptAnyAesExchangeKeyForOwner(aesExchangeKeys, ownerId, ownerId, delegateId, publicKeys);
678
- return {
679
- previousDecryptedEncryptionKeys: yield Promise.all(((modifiedObject.encryptionKeys || {})[delegateId] || []).map((d) => (d.key &&
680
- d.owner === ownerId &&
681
- this._AES.decrypt(importedAESHcPartyKey.key, (0, binary_utils_1.hex2ua)(d.key), importedAESHcPartyKey.rawKey).catch(() => {
682
- console.log(`Cannot decrypt encryption key from ${d.owner} to ${d.delegatedTo} for object with id ${modifiedObject.id}:`, modifiedObject);
683
- return Promise.resolve();
684
- })) ||
685
- Promise.resolve())),
686
- encryptedEncryptionKey: yield this._AES.encrypt(importedAESHcPartyKey.key, (0, binary_utils_1.string2ua)(modifiedObject.id + ':' + secretEncryptionKeyOfObject)),
687
- };
688
- }))
689
- .then(({ previousDecryptedEncryptionKeys, encryptedEncryptionKey }) => {
690
- //try to limit the extent of the modifications to the delegations by preserving the redundant encryption keys already present and removing duplicates
691
- //For delegate delegateId, we create:
692
- // 1. an array of objects { d : {owner,delegatedTo,encrypted(key)}} with one object for the existing encryption keys and the new key concatenated
693
- // 2. an array of objects { k : decrypted(key)} with one object for the existing delegations and the new key concatenated
694
- // We merge them to get one array of objects: { d: {owner,delegatedTo,encrypted(key)}, k: decrypted(key)}
695
- const encryptionKeysCryptedDecrypted = _.merge(((modifiedObject.encryptionKeys || {})[delegateId] || []).map((d) => ({
696
- d,
697
- })), (previousDecryptedEncryptionKeys || []).map((dd) => (dd ? (0, binary_utils_1.ua2string)(dd) : null)).map((k) => ({ k })))
698
- .filter(({ d, k }) => !!k || d.owner !== ownerId) //Only keep the ones created by us that can still be decrypted
699
- .map(({ d, k }) => ({ d, k: k || this.randomUuid() }))
700
- .concat([
701
- {
702
- d: {
703
- owner: ownerId,
704
- delegatedTo: delegateId,
705
- key: (0, binary_utils_1.ua2hex)(encryptedEncryptionKey),
706
- },
707
- k: modifiedObject.id + ':' + secretEncryptionKeyOfObject,
674
+ const owner = (yield this.getDataOwner(ownerId)).dataOwner;
675
+ const publicKeys = yield this.getPublicKeys();
676
+ const { owner: modifiedOwner, aesExchangeKeys } = yield this.getOrCreateHcPartyKeys(owner, delegateId);
677
+ modifiedObject = (modifiedObject === null || modifiedObject === void 0 ? void 0 : modifiedObject.id) === owner.id ? modifiedOwner : modifiedObject;
678
+ const importedAESHcPartyKey = yield this.decryptAnyAesExchangeKeyForOwner(aesExchangeKeys, ownerId, ownerId, delegateId, publicKeys);
679
+ const previousDecryptedEncryptionKeys = yield Promise.all(((modifiedObject.encryptionKeys || {})[delegateId] || []).map((d) => (d.key &&
680
+ d.owner === ownerId &&
681
+ this._AES.decrypt(importedAESHcPartyKey.key, (0, binary_utils_1.hex2ua)(d.key), importedAESHcPartyKey.rawKey).catch(() => {
682
+ console.log(`Cannot decrypt encryption key from ${d.owner} to ${d.delegatedTo} for object with id ${modifiedObject.id}:`, modifiedObject);
683
+ return Promise.resolve();
684
+ })) ||
685
+ Promise.resolve()));
686
+ const encryptedEncryptionKey = yield this._AES.encrypt(importedAESHcPartyKey.key, (0, binary_utils_1.string2ua)(modifiedObject.id + ':' + secretEncryptionKeyOfObject));
687
+ //try to limit the extent of the modifications to the delegations by preserving the redundant encryption keys already present and removing duplicates
688
+ //For delegate delegateId, we create:
689
+ // 1. an array of objects { d : {owner,delegatedTo,encrypted(key)}} with one object for the existing encryption keys and the new key concatenated
690
+ // 2. an array of objects { k : decrypted(key)} with one object for the existing delegations and the new key concatenated
691
+ // We merge them to get one array of objects: { d: {owner,delegatedTo,encrypted(key)}, k: decrypted(key)}
692
+ const encryptionKeysCryptedDecrypted = _.merge(((modifiedObject.encryptionKeys || {})[delegateId] || []).map((d) => ({
693
+ d,
694
+ })), (previousDecryptedEncryptionKeys || []).map((dd) => (dd ? (0, binary_utils_1.ua2string)(dd) : null)).map((k) => ({ k })))
695
+ .filter(({ d, k }) => !!k || d.owner !== ownerId) //Only keep the ones created by us that can still be decrypted
696
+ .map(({ d, k }) => ({ d, k: k || this.randomUuid() }))
697
+ .concat([
698
+ {
699
+ d: {
700
+ owner: ownerId,
701
+ delegatedTo: delegateId,
702
+ key: (0, binary_utils_1.ua2hex)(encryptedEncryptionKey),
708
703
  },
709
- ]);
710
- const allEncryptionKeys = _.cloneDeep(modifiedObject.encryptionKeys);
711
- allEncryptionKeys[delegateId] = _.uniqBy(encryptionKeysCryptedDecrypted, (x) => x.k).map((x) => x.d);
712
- return {
713
- encryptionKeys: allEncryptionKeys,
714
- secretId: secretEncryptionKeyOfObject,
715
- };
716
- });
704
+ k: modifiedObject.id + ':' + secretEncryptionKeyOfObject,
705
+ },
706
+ ]);
707
+ const allEncryptionKeys = _.cloneDeep(modifiedObject.encryptionKeys || {});
708
+ allEncryptionKeys[delegateId] = _.uniqBy(encryptionKeysCryptedDecrypted, (x) => x.k).map((x) => x.d);
709
+ return {
710
+ modifiedObject: modifiedObject,
711
+ encryptionKeys: allEncryptionKeys,
712
+ secretId: secretEncryptionKeyOfObject,
713
+ };
717
714
  });
718
715
  }
719
716
  /**
@@ -731,25 +728,18 @@ class IccCryptoXApi {
731
728
  addDelegationsAndEncryptionKeys(
732
729
  //TODO: suggested name: updateChildGenericDelegationsFromDelegatorToDelegate
733
730
  parent, child, ownerId, delegateId, secretDelegationKey, secretEncryptionKey) {
734
- if (parent)
735
- this.throwDetailedExceptionForInvalidParameter('parent.id', parent.id, 'addDelegationsAndEncryptionKeys', arguments);
736
- this.throwDetailedExceptionForInvalidParameter('child.id', child.id, 'addDelegationsAndEncryptionKeys', arguments);
737
- return (secretDelegationKey
738
- ? this.extendedDelegationsAndCryptedForeignKeys(child, parent, ownerId, delegateId, secretDelegationKey)
739
- : Promise.resolve({ modifiedObject: child, delegations: {}, cryptedForeignKeys: {}, secretId: null }))
740
- .then((extendedChildObjectSPKsAndCFKs) => secretEncryptionKey
741
- ? this.appendEncryptionKeys(extendedChildObjectSPKsAndCFKs.modifiedObject, ownerId, delegateId, secretEncryptionKey).then(
742
- //TODO: extendedDelegationsAndCryptedForeignKeys and appendEncryptionKeys can be done in parallel
743
- (extendedChildObjectEKs) => ({
744
- extendedSPKsAndCFKs: extendedChildObjectSPKsAndCFKs,
745
- extendedEKs: extendedChildObjectEKs,
746
- }))
747
- : Promise.resolve({
748
- extendedSPKsAndCFKs: extendedChildObjectSPKsAndCFKs,
749
- extendedEKs: { encryptionKeys: {} },
750
- }))
751
- .then(({ extendedSPKsAndCFKs: extendedChildObjectSPKsAndCFKs, extendedEKs: extendedChildObjectEKs }) => {
752
- return _.assign(extendedChildObjectSPKsAndCFKs.modifiedObject, {
731
+ return __awaiter(this, arguments, void 0, function* () {
732
+ if (parent)
733
+ this.throwDetailedExceptionForInvalidParameter('parent.id', parent.id, 'addDelegationsAndEncryptionKeys', arguments);
734
+ this.throwDetailedExceptionForInvalidParameter('child.id', child.id, 'addDelegationsAndEncryptionKeys', arguments);
735
+ const extendedChildObjectSPKsAndCFKs = secretDelegationKey
736
+ ? yield this.extendedDelegationsAndCryptedForeignKeys(child, parent, ownerId, delegateId, secretDelegationKey)
737
+ : { modifiedObject: child, delegations: {}, cryptedForeignKeys: {}, secretId: null };
738
+ const extendedChildObjectEKs = secretEncryptionKey
739
+ ? yield this.appendEncryptionKeys(extendedChildObjectSPKsAndCFKs.modifiedObject, ownerId, delegateId, secretEncryptionKey)
740
+ : { encryptionKeys: {}, modifiedObject: extendedChildObjectSPKsAndCFKs.modifiedObject };
741
+ const latestObject = extendedChildObjectEKs.modifiedObject;
742
+ return _.assign(latestObject, {
753
743
  // Conservative version ... We might want to be more aggressive with the deduplication of keys
754
744
  // For each delegate, we are going to concatenate to the src (the new delegations), the object in dest (the current delegations)
755
745
  // for which we do not find an equivalent delegation (same delegator, same delegate)
@@ -890,7 +880,14 @@ class IccCryptoXApi {
890
880
  });
891
881
  return this.decryptKeyInDelegationLikes(delegations[dataOwnerId], collatedAesKeysFromDelegatorToHcpartyId, objectId);
892
882
  })
893
- : Promise.resolve([])).then((extractedKeys) => __awaiter(this, void 0, void 0, function* () {
883
+ : Promise.resolve([]))
884
+ .then((extractedKeys) => __awaiter(this, void 0, void 0, function* () {
885
+ if (extractedKeys.length == 0) {
886
+ return yield this._extractDelegationsKeysUsingDataOwnerDelegateAesExchangeKeys(hcp, delegations, objectId);
887
+ }
888
+ return extractedKeys;
889
+ }))
890
+ .then((extractedKeys) => __awaiter(this, void 0, void 0, function* () {
894
891
  var _a;
895
892
  const parentExtractedKeys = hcp.parentId
896
893
  ? yield this.extractKeysFromDelegationsForHcpHierarchy(hcp.parentId, objectId, delegations)
@@ -902,6 +899,56 @@ class IccCryptoXApi {
902
899
  throw e;
903
900
  });
904
901
  }
902
+ /**
903
+ * This method covers the use case when a DataOwner found back access to its data, and needs to use the delegations of its delegates instead
904
+ * of its own ones
905
+ *
906
+ * @param dataOwner The current data owner from whom we want to decrypt the aesExchangeKeys
907
+ * @param delegations The object delegations to decrypt
908
+ * @param objectId The object to decrypt id
909
+ * @private
910
+ */
911
+ _extractDelegationsKeysUsingDataOwnerDelegateAesExchangeKeys(dataOwner, delegations, objectId) {
912
+ return __awaiter(this, void 0, void 0, function* () {
913
+ // Find other keys through aesExchangeKeys
914
+ const dataOwnerPubKeys = yield this.getPublicKeys();
915
+ const keysToDecrypt = (0, utils_1.fold)(Object.entries(dataOwner.aesExchangeKeys), {}, (acc, [pub, aesForPub]) => {
916
+ Object.entries(aesForPub).forEach(([delegateId, aesKeys]) => {
917
+ if (delegateId != dataOwner.id) {
918
+ const aesAcc = {};
919
+ Object.entries(aesKeys)
920
+ .filter(([encrPubKey]) => dataOwnerPubKeys.some((pubKey) => pubKey.slice(-32) == encrPubKey))
921
+ .forEach(([pubKeyFingerprint, aesEncr]) => {
922
+ aesAcc[pubKeyFingerprint] = aesEncr;
923
+ });
924
+ if (acc[delegateId] == undefined) {
925
+ acc[delegateId] = {};
926
+ }
927
+ acc[delegateId][pub] = aesAcc;
928
+ }
929
+ });
930
+ return acc;
931
+ });
932
+ const decryptedAndImportedAesHcPartyKeys = yield (0, utils_1.foldAsync)(Object.entries(keysToDecrypt), [], (delKeysAcc, [delegateId, keysForDelegate]) => __awaiter(this, void 0, void 0, function* () {
933
+ try {
934
+ delKeysAcc.push(yield this.decryptAnyAesExchangeKeyForOwner(keysForDelegate, dataOwner.id, dataOwner.id, delegateId, dataOwnerPubKeys));
935
+ }
936
+ catch (e) {
937
+ console.log(`Could not decrypt aesExchangeKeys for delegate ${delegateId}`);
938
+ }
939
+ return delKeysAcc;
940
+ }));
941
+ const collatedAesKeysFromDelegatorToHcpartyId = decryptedAndImportedAesHcPartyKeys.reduce((map, k) => { var _a; return (Object.assign(Object.assign({}, map), { [k.delegatorId]: ((_a = map[k.delegatorId]) !== null && _a !== void 0 ? _a : []).concat([k]) })); }, {});
942
+ const delegateIdsWithNewExtractedAesKeys = Object.keys(keysToDecrypt);
943
+ const delegationsToDecrypt = (0, utils_1.fold)(Object.entries(delegations), [], (acc, [delegateId, del]) => {
944
+ if (delegateIdsWithNewExtractedAesKeys.find((id) => id == delegateId) != undefined) {
945
+ acc.push(...delegations[delegateId]);
946
+ }
947
+ return acc;
948
+ });
949
+ return this.decryptKeyInDelegationLikes(delegationsToDecrypt, collatedAesKeysFromDelegatorToHcpartyId, objectId);
950
+ });
951
+ }
905
952
  /**
906
953
  * Gets an array of generic secret IDs decrypted from a list of generic delegations (SPKs, CFKs, EKs) `delegationsArray`
907
954
  * If a particular generic delegation thows an exception when decrypted, the return value for it's secret ID will be 'false' and a message is logged to console
@@ -997,7 +1044,7 @@ class IccCryptoXApi {
997
1044
  }
998
1045
  const publicKey = this.getPublicKeyFromPrivateKey(privateKey, dataOwner);
999
1046
  const keyPair = yield this._RSA.importKeyPair('jwk', privateKey, 'jwk', (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(publicKey)));
1000
- this.rsaKeyPairs[healthcarePartyId] = keyPair;
1047
+ this.rsaKeyPairs[publicKey.slice(-32)] = keyPair;
1001
1048
  const exportedKeyPair = yield this._RSA.exportKeys(keyPair, 'jwk', 'jwk');
1002
1049
  return this.storeKeyPair(`${healthcarePartyId}.${publicKey.slice(-32)}`, exportedKeyPair);
1003
1050
  });
@@ -1217,6 +1264,66 @@ class IccCryptoXApi {
1217
1264
  }
1218
1265
  });
1219
1266
  }
1267
+ /**
1268
+ * When a user lost his keys, people to whom he shared information may call this method to give access back to him, re-encrypting their common
1269
+ * AES key using the new user public key.
1270
+ *
1271
+ * @param delegateUser Delegate Data Owner User, in charge of giving access back to the person who previously gave him some access
1272
+ * @param ownerId Id of the data owner to which we would like to give access back
1273
+ * @param ownerNewPublicKey New Data Owner Public Key we want to use to re-encrypt previously created AES key
1274
+ *
1275
+ * @return The DataOwner, updated by the delegateUser to add the new encrypted AES Key using the new provided public key
1276
+ */
1277
+ giveAccessBackTo(delegateUser, ownerId, ownerNewPublicKey) {
1278
+ var _a, _b, _c, _d;
1279
+ return __awaiter(this, void 0, void 0, function* () {
1280
+ const delegateId = (_b = (_a = delegateUser.healthcarePartyId) !== null && _a !== void 0 ? _a : delegateUser.patientId) !== null && _b !== void 0 ? _b : delegateUser.deviceId;
1281
+ if (!delegateId) {
1282
+ throw new Error(`DelegateUser ${delegateUser.id} must be a data Owner`);
1283
+ }
1284
+ const delegatePublicKeys = yield this.getPublicKeys();
1285
+ const newPubKeyCryptoKey = yield this._RSA.importKey('jwk', (0, utils_1.spkiToJwk)((0, binary_utils_1.hex2ua)(ownerNewPublicKey)), ['encrypt']);
1286
+ const dataOwnerToUpdate = yield this.getDataOwner(ownerId);
1287
+ const newAesExchangeKeys = yield (0, utils_1.foldAsync)(Object.entries((_c = dataOwnerToUpdate.dataOwner.aesExchangeKeys) !== null && _c !== void 0 ? _c : {}), (_d = dataOwnerToUpdate.dataOwner.aesExchangeKeys) !== null && _d !== void 0 ? _d : {}, (pubAcc, [pubKey, newAesExcKeys]) => __awaiter(this, void 0, void 0, function* () {
1288
+ var _e;
1289
+ const existingKeys = (_e = pubAcc[pubKey]) !== null && _e !== void 0 ? _e : {};
1290
+ pubAcc[pubKey] = yield (0, utils_1.foldAsync)(Object.entries(newAesExcKeys), existingKeys, (delAcc, [delId, delKeys]) => __awaiter(this, void 0, void 0, function* () {
1291
+ if (delId == delegateId && pubKey != ownerNewPublicKey) {
1292
+ // Add the AES Key encrypted with the new public key in the aesExchangeKeys
1293
+ try {
1294
+ // First, we decrypt it using the delegate RSA Public Key
1295
+ const encrAesKeyInfo = yield this.decryptHcPartyKey(delegateId, dataOwnerToUpdate.dataOwner.id, delegateId, pubKey, delKeys, delegatePublicKeys).then((delegatorAndKeys) => __awaiter(this, void 0, void 0, function* () {
1296
+ // Then, we encrypt it using the owner new RSA Public Key (provided in argument)
1297
+ return yield this.encryptAesKeyOnlyForProvidedKeys(delegatorAndKeys === null || delegatorAndKeys === void 0 ? void 0 : delegatorAndKeys.rawKey, dataOwnerToUpdate, [newPubKeyCryptoKey])
1298
+ .then((encrAes) => Object.values(encrAes)[0])
1299
+ .then((encrAesInfo) => {
1300
+ return { pubKeyUsedToEncryptAes: Object.keys(encrAesInfo)[0], encryptedAes: Object.values(encrAesInfo)[0] };
1301
+ });
1302
+ }));
1303
+ delKeys[encrAesKeyInfo.pubKeyUsedToEncryptAes] = encrAesKeyInfo.encryptedAes;
1304
+ }
1305
+ catch (e) {
1306
+ console.log(`${delegateId} could not re-encrypt AES Key of ${dataOwnerToUpdate.dataOwner.id}`);
1307
+ }
1308
+ finally {
1309
+ delAcc[delId] = delKeys;
1310
+ }
1311
+ }
1312
+ else {
1313
+ // Otherwise, we don't transform the aesExchangeKeys for this delegate
1314
+ delAcc[delId] = delKeys;
1315
+ }
1316
+ return delAcc;
1317
+ }));
1318
+ return pubAcc;
1319
+ }));
1320
+ // After adding the potential new aesExchangeKeys, we save the updated data owner
1321
+ return this._saveDataOwner({
1322
+ type: dataOwnerToUpdate.type,
1323
+ dataOwner: Object.assign(Object.assign({}, dataOwnerToUpdate.dataOwner), { aesExchangeKeys: newAesExchangeKeys }),
1324
+ });
1325
+ });
1326
+ }
1220
1327
  addNewKeyPairForOwnerId(maintenanceTasksApi, user, ownerId, generateTransferKey = true) {
1221
1328
  return __awaiter(this, void 0, void 0, function* () {
1222
1329
  return this.addNewKeyPairForOwner(maintenanceTasksApi, user, yield this.getDataOwner(ownerId), generateTransferKey);
@@ -1234,7 +1341,22 @@ class IccCryptoXApi {
1234
1341
  }).then((dataOwnerWithUpdatedAesKeys) => generateTransferKey
1235
1342
  ? this.createOrUpdateTransferKeysFor(dataOwnerWithUpdatedAesKeys, gen, { pubKey: publicKey, privKey: privateKey })
1236
1343
  : dataOwnerWithUpdatedAesKeys);
1237
- const modifiedDataOwnerAndType = ownerType === 'hcp'
1344
+ const modifiedDataOwnerAndType = yield this._saveDataOwner({ type: ownerType, dataOwner: ownerToUpdate });
1345
+ const sentMaintenanceTasks = yield this.sendMaintenanceTasks(maintenanceTasksApi, user, modifiedDataOwnerAndType.dataOwner, publicKey);
1346
+ return {
1347
+ dataOwner: sentMaintenanceTasks.length
1348
+ ? yield this.retrieveDataOwnerInfoAfterPotentialUpdate(modifiedDataOwnerAndType.dataOwner)
1349
+ : modifiedDataOwnerAndType.dataOwner,
1350
+ publicKey: publicKeyHex,
1351
+ privateKey: (0, binary_utils_1.ua2hex)((yield this.RSA.exportKey(privateKey, 'pkcs8'))),
1352
+ };
1353
+ });
1354
+ }
1355
+ _saveDataOwner(dataOwner) {
1356
+ return __awaiter(this, void 0, void 0, function* () {
1357
+ const ownerType = dataOwner.type;
1358
+ const ownerToUpdate = dataOwner.dataOwner;
1359
+ return ownerType === 'hcp'
1238
1360
  ? yield (this.dataOwnerCache[ownerToUpdate.id] = this.hcpartyBaseApi
1239
1361
  .modifyHealthcareParty(ownerToUpdate)
1240
1362
  .then((x) => ({ type: 'hcp', dataOwner: x })))
@@ -1245,14 +1367,6 @@ class IccCryptoXApi {
1245
1367
  : yield (this.dataOwnerCache[ownerToUpdate.id] = this.deviceBaseApi
1246
1368
  .updateDevice(ownerToUpdate)
1247
1369
  .then((x) => ({ type: 'device', dataOwner: x })));
1248
- const sentMaintenanceTasks = yield this.sendMaintenanceTasks(maintenanceTasksApi, user, modifiedDataOwnerAndType.dataOwner, publicKey);
1249
- return {
1250
- dataOwner: sentMaintenanceTasks.length
1251
- ? yield this.retrieveDataOwnerInfoAfterPotentialUpdate(modifiedDataOwnerAndType.dataOwner)
1252
- : modifiedDataOwnerAndType.dataOwner,
1253
- publicKey: publicKeyHex,
1254
- privateKey: (0, binary_utils_1.ua2hex)((yield this.RSA.exportKey(privateKey, 'pkcs8'))),
1255
- };
1256
1370
  });
1257
1371
  }
1258
1372
  createOrUpdateAesExchangeKeysFor(cdo, decryptedAesExchangeKey, keyToEncrypt) {
@@ -1285,11 +1399,16 @@ class IccCryptoXApi {
1285
1399
  encryptAesKeyFor(aesKey, dataOwner, doNewPublicKey) {
1286
1400
  return __awaiter(this, void 0, void 0, function* () {
1287
1401
  const dataOwnerAllPubKeys = [doNewPublicKey].concat(yield this.getDataOwnerPublicKeys(dataOwner));
1288
- const encrAes = {};
1289
- for (const pubKey of dataOwnerAllPubKeys) {
1402
+ return this.encryptAesKeyOnlyForProvidedKeys(aesKey, dataOwner, dataOwnerAllPubKeys);
1403
+ });
1404
+ }
1405
+ encryptAesKeyOnlyForProvidedKeys(aesKey, dataOwner, dataOwnerPubKeys) {
1406
+ return __awaiter(this, void 0, void 0, function* () {
1407
+ const encryptedAesForDataOwner = yield (0, utils_1.foldAsync)(dataOwnerPubKeys, {}, (encrAes, pubKey) => __awaiter(this, void 0, void 0, function* () {
1290
1408
  encrAes[(0, binary_utils_1.ua2hex)(yield this.RSA.exportKey(pubKey, 'spki')).slice(-32)] = (0, binary_utils_1.ua2hex)(yield this._RSA.encrypt(pubKey, (0, binary_utils_1.hex2ua)(aesKey)));
1291
- }
1292
- return { [dataOwner.id]: encrAes };
1409
+ return encrAes;
1410
+ }));
1411
+ return { [dataOwner.id]: encryptedAesForDataOwner };
1293
1412
  });
1294
1413
  }
1295
1414
  retrieveDataOwnerInfoAfterPotentialUpdate(dataOwnerToUpdate) {