@icure/api 8.0.64 → 8.0.65
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/icc-api/api/internal/IccExchangeDataApi.d.ts +2 -0
- package/icc-api/api/internal/IccExchangeDataApi.js +10 -0
- package/icc-api/api/internal/IccExchangeDataApi.js.map +1 -1
- package/icc-api/iccApi.d.ts +0 -1
- package/icc-api/iccApi.js +0 -1
- package/icc-api/iccApi.js.map +1 -1
- package/icc-api/index.d.ts +0 -1
- package/icc-api/index.js +0 -1
- package/icc-api/index.js.map +1 -1
- package/icc-x-api/crypto/AccessControlSecretUtils.d.ts +4 -13
- package/icc-x-api/crypto/AccessControlSecretUtils.js +19 -29
- package/icc-x-api/crypto/AccessControlSecretUtils.js.map +1 -1
- package/icc-x-api/crypto/BaseExchangeDataManager.d.ts +6 -2
- package/icc-x-api/crypto/BaseExchangeDataManager.js +26 -9
- package/icc-x-api/crypto/BaseExchangeDataManager.js.map +1 -1
- package/icc-x-api/crypto/BaseExchangeKeysManager.d.ts +2 -3
- package/icc-x-api/crypto/BaseExchangeKeysManager.js +8 -16
- package/icc-x-api/crypto/BaseExchangeKeysManager.js.map +1 -1
- package/icc-x-api/crypto/CryptoPrimitives.d.ts +2 -0
- package/icc-x-api/crypto/CryptoPrimitives.js +3 -0
- package/icc-x-api/crypto/CryptoPrimitives.js.map +1 -1
- package/icc-x-api/crypto/DelegationsDeAnonymization.d.ts +3 -3
- package/icc-x-api/crypto/DelegationsDeAnonymization.js +7 -7
- package/icc-x-api/crypto/DelegationsDeAnonymization.js.map +1 -1
- package/icc-x-api/crypto/ExchangeDataManager.d.ts +19 -29
- package/icc-x-api/crypto/ExchangeDataManager.js +200 -225
- package/icc-x-api/crypto/ExchangeDataManager.js.map +1 -1
- package/icc-x-api/crypto/ExchangeDataMapManager.js +6 -4
- package/icc-x-api/crypto/ExchangeDataMapManager.js.map +1 -1
- package/icc-x-api/crypto/ExchangeKeysManager.d.ts +4 -16
- package/icc-x-api/crypto/ExchangeKeysManager.js +44 -41
- package/icc-x-api/crypto/ExchangeKeysManager.js.map +1 -1
- package/icc-x-api/crypto/ExtendedApisUtils.d.ts +47 -25
- package/icc-x-api/crypto/ExtendedApisUtils.js.map +1 -1
- package/icc-x-api/crypto/ExtendedApisUtilsImpl.d.ts +19 -18
- package/icc-x-api/crypto/ExtendedApisUtilsImpl.js +213 -134
- package/icc-x-api/crypto/ExtendedApisUtilsImpl.js.map +1 -1
- package/icc-x-api/crypto/HMACUtils.d.ts +2 -2
- package/icc-x-api/crypto/HMACUtils.js +3 -4
- package/icc-x-api/crypto/HMACUtils.js.map +1 -1
- package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.d.ts +1 -0
- package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.js +5 -0
- package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.js.map +1 -1
- package/icc-x-api/crypto/SecureDelegationsManager.d.ts +0 -1
- package/icc-x-api/crypto/SecureDelegationsManager.js +17 -49
- package/icc-x-api/crypto/SecureDelegationsManager.js.map +1 -1
- package/icc-x-api/crypto/SecurityMetadataDecryptor.d.ts +59 -90
- package/icc-x-api/crypto/SecurityMetadataDecryptor.js +470 -56
- package/icc-x-api/crypto/SecurityMetadataDecryptor.js.map +1 -1
- package/icc-x-api/crypto/ShamirKeysManager.js +1 -1
- package/icc-x-api/crypto/ShamirKeysManager.js.map +1 -1
- package/icc-x-api/crypto/TransferKeysManager.d.ts +1 -3
- package/icc-x-api/crypto/TransferKeysManager.js +2 -4
- package/icc-x-api/crypto/TransferKeysManager.js.map +1 -1
- package/icc-x-api/icc-accesslog-x-api.d.ts +2 -2
- package/icc-x-api/icc-accesslog-x-api.js +7 -3
- package/icc-x-api/icc-accesslog-x-api.js.map +1 -1
- package/icc-x-api/icc-calendar-item-x-api.js +4 -2
- package/icc-x-api/icc-calendar-item-x-api.js.map +1 -1
- package/icc-x-api/icc-contact-x-api.d.ts +0 -1
- package/icc-x-api/icc-contact-x-api.js +33 -48
- package/icc-x-api/icc-contact-x-api.js.map +1 -1
- package/icc-x-api/icc-crypto-x-api.js +1 -1
- package/icc-x-api/icc-crypto-x-api.js.map +1 -1
- package/icc-x-api/icc-document-x-api.d.ts +2 -2
- package/icc-x-api/icc-document-x-api.js +45 -42
- package/icc-x-api/icc-document-x-api.js.map +1 -1
- package/icc-x-api/icc-form-x-api.js +3 -1
- package/icc-x-api/icc-form-x-api.js.map +1 -1
- package/icc-x-api/icc-helement-x-api.js +4 -4
- package/icc-x-api/icc-helement-x-api.js.map +1 -1
- package/icc-x-api/icc-maintenance-task-x-api.js +4 -2
- package/icc-x-api/icc-maintenance-task-x-api.js.map +1 -1
- package/icc-x-api/icc-message-x-api.js +4 -2
- package/icc-x-api/icc-message-x-api.js.map +1 -1
- package/icc-x-api/icc-patient-x-api.js +5 -7
- package/icc-x-api/icc-patient-x-api.js.map +1 -1
- package/icc-x-api/icc-topic-x-api.js +2 -2
- package/icc-x-api/icc-topic-x-api.js.map +1 -1
- package/icc-x-api/index.d.ts +1 -2
- package/icc-x-api/index.js +7 -13
- package/icc-x-api/index.js.map +1 -1
- package/icc-x-api/utils/crypto-utils.d.ts +6 -4
- package/icc-x-api/utils/crypto-utils.js +27 -6
- package/icc-x-api/utils/crypto-utils.js.map +1 -1
- package/icc-x-api/utils/simple-lru-cache.d.ts +19 -0
- package/icc-x-api/utils/simple-lru-cache.js +90 -0
- package/icc-x-api/utils/simple-lru-cache.js.map +1 -0
- package/package.json +4 -2
- package/test/icc-x-api/crud/entities-crud-test-interface.js +0 -8
- package/test/icc-x-api/crud/entities-crud-test-interface.js.map +1 -1
- package/test/icc-x-api/crypto/exchange-data-manager-test.js +74 -92
- package/test/icc-x-api/crypto/exchange-data-manager-test.js.map +1 -1
- package/test/icc-x-api/crypto/legacy-metadata-migration-test.js.map +1 -1
- package/test/icc-x-api/crypto/secure-delegations-manager-test.js +27 -15
- package/test/icc-x-api/crypto/secure-delegations-manager-test.js.map +1 -1
- package/test/utils/FakeEncryptionKeysManager.d.ts +1 -0
- package/test/utils/FakeEncryptionKeysManager.js +11 -0
- package/test/utils/FakeEncryptionKeysManager.js.map +1 -1
- package/test/utils/FakeExchangeDataApi.d.ts +4 -2
- package/test/utils/FakeExchangeDataApi.js +24 -6
- package/test/utils/FakeExchangeDataApi.js.map +1 -1
- package/test/utils/FakeExchangeDataManager.d.ts +10 -10
- package/test/utils/FakeExchangeDataManager.js +12 -22
- package/test/utils/FakeExchangeDataManager.js.map +1 -1
- package/icc-api/api/IccArticleApi.d.ts +0 -72
- package/icc-api/api/IccArticleApi.js +0 -149
- package/icc-api/api/IccArticleApi.js.map +0 -1
- package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.d.ts +0 -33
- package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.js +0 -141
- package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.js.map +0 -1
- package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.d.ts +0 -46
- package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.js +0 -312
- package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.js.map +0 -1
- package/icc-x-api/crypto/UserSignatureKeysManager.d.ts +0 -26
- package/icc-x-api/crypto/UserSignatureKeysManager.js +0 -78
- package/icc-x-api/crypto/UserSignatureKeysManager.js.map +0 -1
- package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.d.ts +0 -1
- package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.js +0 -393
- package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.js.map +0 -1
- package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.d.ts +0 -1
- package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.js +0 -213
- package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.js.map +0 -1
- package/test/icc-x-api/crypto/signature-keys-manager-test.d.ts +0 -1
- package/test/icc-x-api/crypto/signature-keys-manager-test.js +0 -44
- package/test/icc-x-api/crypto/signature-keys-manager-test.js.map +0 -1
- package/test/utils/FakeSignatureKeysManager.d.ts +0 -16
- package/test/utils/FakeSignatureKeysManager.js +0 -54
- package/test/utils/FakeSignatureKeysManager.js.map +0 -1
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
12
|
-
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
13
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
14
|
-
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
15
|
-
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
16
|
-
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
|
|
17
|
-
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
18
|
-
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
19
|
-
function fulfill(value) { resume("next", value); }
|
|
20
|
-
function reject(value) { resume("throw", value); }
|
|
21
|
-
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
22
|
-
};
|
|
23
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.SecureDelegationsSecurityMetadataDecryptor = void 0;
|
|
25
|
-
const SecureDelegation_1 = require("../../icc-api/model/SecureDelegation");
|
|
26
|
-
var AccessLevel = SecureDelegation_1.SecureDelegation.AccessLevelEnum;
|
|
27
|
-
class SecureDelegationsSecurityMetadataDecryptor {
|
|
28
|
-
constructor(exchangeData, exchangeDataMap, secureDelegationsEncryption, dataOwnerApi) {
|
|
29
|
-
this.exchangeData = exchangeData;
|
|
30
|
-
this.exchangeDataMap = exchangeDataMap;
|
|
31
|
-
this.secureDelegationsEncryption = secureDelegationsEncryption;
|
|
32
|
-
this.dataOwnerApi = dataOwnerApi;
|
|
33
|
-
}
|
|
34
|
-
decryptEncryptionKeysOf(typedEntity, dataOwnersHierarchySubset) {
|
|
35
|
-
return this.decryptSecureDelegations(typedEntity, dataOwnersHierarchySubset, (d) => { var _a; return (_a = d.encryptionKeys) !== null && _a !== void 0 ? _a : []; }, (e, k) => this.secureDelegationsEncryption.decryptEncryptionKey(e, k));
|
|
36
|
-
}
|
|
37
|
-
decryptOwningEntityIdsOf(typedEntity, dataOwnersHierarchySubset) {
|
|
38
|
-
return this.decryptSecureDelegations(typedEntity, dataOwnersHierarchySubset, (d) => { var _a; return (_a = d.owningEntityIds) !== null && _a !== void 0 ? _a : []; }, (e, k) => this.secureDelegationsEncryption.decryptOwningEntityId(e, k));
|
|
39
|
-
}
|
|
40
|
-
decryptSecretIdsOf(typedEntity, dataOwnersHierarchySubset) {
|
|
41
|
-
return this.decryptSecureDelegations(typedEntity, dataOwnersHierarchySubset, (d) => { var _a; return (_a = d.secretIds) !== null && _a !== void 0 ? _a : []; }, (e, k) => this.secureDelegationsEncryption.decryptSecretId(e, k));
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Get information for members of secure delegations in the entity. Also provides information for delegations with anonymous delegate and/or
|
|
45
|
-
* delegator if one of the delegation members is the current data owner (or a parent) AND has still access to the exchange data used in the .
|
|
46
|
-
*/
|
|
47
|
-
getDelegationMemberDetails(typedEntity) {
|
|
48
|
-
var _a, _b, _c, _d, _e, _f;
|
|
49
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
const res = {};
|
|
51
|
-
// 1. Add all explicit data owners, keep only delegations with at least an anonymous data owner to check later
|
|
52
|
-
let remainingDelegations = Object.entries((_b = (_a = typedEntity.entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {});
|
|
53
|
-
let updatedRemainingDelegations = [];
|
|
54
|
-
for (const delegationEntry of remainingDelegations) {
|
|
55
|
-
const delegation = delegationEntry[1];
|
|
56
|
-
if (delegation.delegator && delegation.delegate) {
|
|
57
|
-
res[delegationEntry[0]] = {
|
|
58
|
-
delegate: delegation.delegate,
|
|
59
|
-
delegator: delegation.delegator,
|
|
60
|
-
fullyExplicit: true,
|
|
61
|
-
accessLevel: delegation.permissions,
|
|
62
|
-
accessControlSecret: undefined,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
updatedRemainingDelegations.push(delegationEntry);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
remainingDelegations = updatedRemainingDelegations;
|
|
70
|
-
if (!remainingDelegations.length)
|
|
71
|
-
return res;
|
|
72
|
-
updatedRemainingDelegations = [];
|
|
73
|
-
// 2. Attempt to identify the anonymous data owner of remaining delegations by checking if we have the exchange data cached by hash
|
|
74
|
-
// Note: we can find exchange data by hash only if we could successfully decrypt it
|
|
75
|
-
const cachedExchangeData = yield this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash(remainingDelegations.map((d) => d[0]), typedEntity.type, (_c = typedEntity.entity.secretForeignKeys) !== null && _c !== void 0 ? _c : []);
|
|
76
|
-
for (const delegationEntry of remainingDelegations) {
|
|
77
|
-
const exchangeDataOfDelegation = cachedExchangeData[delegationEntry[0]];
|
|
78
|
-
if (exchangeDataOfDelegation) {
|
|
79
|
-
res[delegationEntry[0]] = {
|
|
80
|
-
delegate: exchangeDataOfDelegation.exchangeData.delegate,
|
|
81
|
-
delegator: exchangeDataOfDelegation.exchangeData.delegator,
|
|
82
|
-
fullyExplicit: false,
|
|
83
|
-
accessLevel: delegationEntry[1].permissions,
|
|
84
|
-
accessControlSecret: exchangeDataOfDelegation.accessControlSecret,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
updatedRemainingDelegations.push(delegationEntry);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
remainingDelegations = updatedRemainingDelegations;
|
|
92
|
-
if (!remainingDelegations.length)
|
|
93
|
-
return res;
|
|
94
|
-
updatedRemainingDelegations = [];
|
|
95
|
-
// 3. Attempt to identify the anonymous data owner of remaining delegations between us (or one of our parents) and an anonymous data owner
|
|
96
|
-
const hierarchy = yield this.dataOwnerApi.getCurrentDataOwnerHierarchyIds();
|
|
97
|
-
const allHashes = [
|
|
98
|
-
...remainingDelegations.flatMap(([hash, _]) => hash),
|
|
99
|
-
...Object.keys((_e = (_d = typedEntity.entity.securityMetadata) === null || _d === void 0 ? void 0 : _d.keysEquivalences) !== null && _e !== void 0 ? _e : {}),
|
|
100
|
-
];
|
|
101
|
-
const encryptedExchangeDataIds = (yield this.exchangeDataMap.getExchangeDataMapBatch(allHashes)).reduce((maps, current) => {
|
|
102
|
-
return Object.assign(Object.assign({}, maps), { [current.id]: current });
|
|
103
|
-
}, {});
|
|
104
|
-
for (const [hash, delegation] of remainingDelegations) {
|
|
105
|
-
if (hierarchy.some((x) => x === delegation.delegate || x === delegation.delegator)) {
|
|
106
|
-
const dataId = !!encryptedExchangeDataIds[hash]
|
|
107
|
-
? yield this.secureDelegationsEncryption.decryptExchangeDataId(encryptedExchangeDataIds[hash].encryptedExchangeDataIds)
|
|
108
|
-
: undefined;
|
|
109
|
-
const exchangeDataInfo = dataId
|
|
110
|
-
? yield this.exchangeData.getDecryptionDataKeyById(dataId, typedEntity.type, (_f = typedEntity.entity.secretForeignKeys) !== null && _f !== void 0 ? _f : [], true)
|
|
111
|
-
: undefined;
|
|
112
|
-
if (exchangeDataInfo) {
|
|
113
|
-
res[hash] = {
|
|
114
|
-
delegator: exchangeDataInfo.exchangeData.delegator,
|
|
115
|
-
delegate: exchangeDataInfo.exchangeData.delegate,
|
|
116
|
-
fullyExplicit: false,
|
|
117
|
-
accessLevel: delegation.permissions,
|
|
118
|
-
accessControlSecret: exchangeDataInfo.accessControlSecret,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
updatedRemainingDelegations.push([hash, delegation]);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
updatedRemainingDelegations.push([hash, delegation]);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return Object.assign(Object.assign({}, res), Object.fromEntries(updatedRemainingDelegations.map(([hash, secureDelegation]) => [
|
|
130
|
-
hash,
|
|
131
|
-
{
|
|
132
|
-
delegator: secureDelegation.delegator,
|
|
133
|
-
delegate: secureDelegation.delegate,
|
|
134
|
-
fullyExplicit: false,
|
|
135
|
-
accessLevel: secureDelegation.permissions,
|
|
136
|
-
accessControlSecret: undefined,
|
|
137
|
-
},
|
|
138
|
-
])));
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
hasAnyEncryptionKeys(entity) {
|
|
142
|
-
var _a, _b;
|
|
143
|
-
return Object.values((_b = (_a = entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {}).some((d) => { var _a; return (_a = d.encryptionKeys) === null || _a === void 0 ? void 0 : _a.length; });
|
|
144
|
-
}
|
|
145
|
-
getEntityAccessLevel(typedEntity, dataOwnersHierarchySubset) {
|
|
146
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
147
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
-
if (!dataOwnersHierarchySubset.length)
|
|
149
|
-
throw new Error("`dataOwnersHierarchySubset` can't be empty");
|
|
150
|
-
// If the data owner is explicit all delegations he can access has his id. If the delegator is anonymous all delegations he can access are
|
|
151
|
-
// accessible by hash. No mixed scenario possible.
|
|
152
|
-
let accessibleDelegations = Object.values((_b = (_a = typedEntity.entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {}).filter((secureDelegation) => dataOwnersHierarchySubset.some((dataOwner) => dataOwner === secureDelegation.delegator || dataOwner === secureDelegation.delegate));
|
|
153
|
-
if (!accessibleDelegations.length) {
|
|
154
|
-
const equivalences = (_c = typedEntity.entity.securityMetadata) === null || _c === void 0 ? void 0 : _c.keysEquivalences;
|
|
155
|
-
const availableCanonicalHashes = Array.from(new Set(Object.keys(yield this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash([
|
|
156
|
-
...Object.keys((_e = (_d = typedEntity.entity.securityMetadata) === null || _d === void 0 ? void 0 : _d.secureDelegations) !== null && _e !== void 0 ? _e : {}),
|
|
157
|
-
...Object.keys((_g = (_f = typedEntity.entity.securityMetadata) === null || _f === void 0 ? void 0 : _f.keysEquivalences) !== null && _g !== void 0 ? _g : {}),
|
|
158
|
-
], typedEntity.type, (_h = typedEntity.entity.secretForeignKeys) !== null && _h !== void 0 ? _h : [])).map((hash) => {
|
|
159
|
-
const canonicalEquivalence = equivalences ? equivalences[hash] : undefined;
|
|
160
|
-
return canonicalEquivalence ? canonicalEquivalence : hash;
|
|
161
|
-
})));
|
|
162
|
-
accessibleDelegations = availableCanonicalHashes.map((hash) => { var _a, _b; return ((_b = (_a = typedEntity.entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {})[hash]; });
|
|
163
|
-
}
|
|
164
|
-
const permissions = accessibleDelegations.map((secureDelegation) => secureDelegation.permissions);
|
|
165
|
-
let maxLevel = undefined;
|
|
166
|
-
for (const permission of permissions) {
|
|
167
|
-
if (permission === AccessLevel.WRITE) {
|
|
168
|
-
return AccessLevel.WRITE;
|
|
169
|
-
}
|
|
170
|
-
if (permission === AccessLevel.READ) {
|
|
171
|
-
maxLevel = AccessLevel.READ;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return maxLevel;
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
decryptSecureDelegations(typedEntity, dataOwnersHierarchySubset, getDataToDecrypt, decryptDataWithKey) {
|
|
178
|
-
if (!dataOwnersHierarchySubset.length)
|
|
179
|
-
throw new Error("`dataOwnersHierarchySubset` can't be empty");
|
|
180
|
-
const self = this;
|
|
181
|
-
function getFirstDecryptedExchangeDataIdForHash(hashes, encryptedExchangeDataIdsByDelegationKey) {
|
|
182
|
-
var _a;
|
|
183
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
184
|
-
for (const hash of new Set(hashes)) {
|
|
185
|
-
const decryptedExchangeDataId = !!encryptedExchangeDataIdsByDelegationKey[hash]
|
|
186
|
-
? yield self.secureDelegationsEncryption.decryptExchangeDataId((_a = encryptedExchangeDataIdsByDelegationKey[hash]) === null || _a === void 0 ? void 0 : _a.encryptedExchangeDataIds)
|
|
187
|
-
: undefined;
|
|
188
|
-
if (!!decryptedExchangeDataId)
|
|
189
|
-
return decryptedExchangeDataId;
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
function decrypt(delegation, exchangeDataDetails) {
|
|
194
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
195
|
-
if (!exchangeDataDetails.exchangeKey)
|
|
196
|
-
return [];
|
|
197
|
-
const dataToDecrypt = getDataToDecrypt(delegation);
|
|
198
|
-
if (!dataToDecrypt.length)
|
|
199
|
-
return [];
|
|
200
|
-
if (!dataOwnersHierarchySubset.some((x) => x === exchangeDataDetails.exchangeData.delegator || x === exchangeDataDetails.exchangeData.delegate))
|
|
201
|
-
return [];
|
|
202
|
-
const dataOwnersWithAccess = [exchangeDataDetails.exchangeData.delegator, exchangeDataDetails.exchangeData.delegate];
|
|
203
|
-
const res = [];
|
|
204
|
-
for (const curr of dataToDecrypt) {
|
|
205
|
-
res.push({ decrypted: yield decryptDataWithKey(curr, exchangeDataDetails.exchangeKey), dataOwnersWithAccess });
|
|
206
|
-
}
|
|
207
|
-
return res;
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
function generator() {
|
|
211
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
212
|
-
return __asyncGenerator(this, arguments, function* generator_1() {
|
|
213
|
-
let remainingDelegations = Object.entries((_b = (_a = typedEntity.entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {}).map(([canonicalHash, delegation]) => {
|
|
214
|
-
var _a, _b;
|
|
215
|
-
return ({
|
|
216
|
-
delegation,
|
|
217
|
-
hashes: [
|
|
218
|
-
canonicalHash,
|
|
219
|
-
...Object.entries((_b = (_a = typedEntity.entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.keysEquivalences) !== null && _b !== void 0 ? _b : {})
|
|
220
|
-
.filter((x) => x[1] == canonicalHash)
|
|
221
|
-
.map((x) => x[0]),
|
|
222
|
-
],
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
/*
|
|
226
|
-
* Generate from least expensive to most (in terms of time to decrypt). 1 and 2a have equivalent costs.
|
|
227
|
-
* 1) Secure delegations with cached exchange data by hash
|
|
228
|
-
* 2) Secure delegations with cached exchange data by id for explicit->explicit delegations where delegator and/or delegate is me or parent
|
|
229
|
-
* 3) Non cached secure delegations for explicit->explicit delegations where delegator and/or delegate is me or parent (half of old 3)
|
|
230
|
-
* 4) Decrypt secure delegation id for explicit->anonymous or anonymous->explicit where explicit is me or parent (2b and half of old3)
|
|
231
|
-
*/
|
|
232
|
-
// Step 1) Secure delegations with cached exchange data by hash
|
|
233
|
-
if (!remainingDelegations.length)
|
|
234
|
-
return yield __await(void 0);
|
|
235
|
-
const cachedDataByHash = yield __await(self.exchangeData.getCachedDecryptionDataKeyByAccessControlHash([
|
|
236
|
-
...Object.keys((_d = (_c = typedEntity.entity.securityMetadata) === null || _c === void 0 ? void 0 : _c.secureDelegations) !== null && _d !== void 0 ? _d : {}),
|
|
237
|
-
...Object.keys((_f = (_e = typedEntity.entity.securityMetadata) === null || _e === void 0 ? void 0 : _e.keysEquivalences) !== null && _f !== void 0 ? _f : {}),
|
|
238
|
-
], typedEntity.type, (_g = typedEntity.entity.secretForeignKeys) !== null && _g !== void 0 ? _g : []));
|
|
239
|
-
let updatedRemainingDelegations = [];
|
|
240
|
-
for (const decryptionDetails of remainingDelegations) {
|
|
241
|
-
const exchangeDataDetails = decryptionDetails.hashes.map((h) => cachedDataByHash === null || cachedDataByHash === void 0 ? void 0 : cachedDataByHash[h]).find((x) => !!x);
|
|
242
|
-
if (exchangeDataDetails) {
|
|
243
|
-
for (const decrypted of yield __await(decrypt(decryptionDetails.delegation, exchangeDataDetails)))
|
|
244
|
-
yield yield __await(decrypted);
|
|
245
|
-
}
|
|
246
|
-
else if ((!!decryptionDetails.delegation.delegate || !!decryptionDetails.delegation.delegator) &&
|
|
247
|
-
dataOwnersHierarchySubset.some((x) => x === decryptionDetails.delegation.delegate || x === decryptionDetails.delegation.delegator)) {
|
|
248
|
-
updatedRemainingDelegations.push(decryptionDetails);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
remainingDelegations = updatedRemainingDelegations;
|
|
252
|
-
updatedRemainingDelegations = [];
|
|
253
|
-
// Step 2) Secure delegations with cached exchange data by id for explicit->explicit delegations where delegator and/or delegate is me or parent
|
|
254
|
-
if (!remainingDelegations.length)
|
|
255
|
-
return yield __await(void 0);
|
|
256
|
-
for (const decryptionDetails of remainingDelegations) {
|
|
257
|
-
const exchangeDataDetails = decryptionDetails.delegation.exchangeDataId
|
|
258
|
-
? yield __await(self.exchangeData.getDecryptionDataKeyById(decryptionDetails.delegation.exchangeDataId, typedEntity.type, (_h = typedEntity.entity.secretForeignKeys) !== null && _h !== void 0 ? _h : [], false))
|
|
259
|
-
: undefined;
|
|
260
|
-
if (!!exchangeDataDetails) {
|
|
261
|
-
for (const decrypted of yield __await(decrypt(decryptionDetails.delegation, exchangeDataDetails)))
|
|
262
|
-
yield yield __await(decrypted);
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
updatedRemainingDelegations.push(decryptionDetails);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
remainingDelegations = updatedRemainingDelegations;
|
|
269
|
-
updatedRemainingDelegations = [];
|
|
270
|
-
// Step 3) Non cached secure delegations for explicit->explicit delegations where delegator and/or delegate is me or parent
|
|
271
|
-
if (!remainingDelegations.length)
|
|
272
|
-
return yield __await(void 0);
|
|
273
|
-
for (const decryptionDetails of remainingDelegations) {
|
|
274
|
-
const exchangeDataDetails = decryptionDetails.delegation.exchangeDataId
|
|
275
|
-
? yield __await(self.exchangeData.getDecryptionDataKeyById(decryptionDetails.delegation.exchangeDataId, typedEntity.type, (_j = typedEntity.entity.secretForeignKeys) !== null && _j !== void 0 ? _j : [], true))
|
|
276
|
-
: undefined;
|
|
277
|
-
if (!!exchangeDataDetails) {
|
|
278
|
-
for (const decrypted of yield __await(decrypt(decryptionDetails.delegation, exchangeDataDetails)))
|
|
279
|
-
yield yield __await(decrypted);
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
updatedRemainingDelegations.push(decryptionDetails);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
remainingDelegations = updatedRemainingDelegations;
|
|
286
|
-
// Step 4) Decrypt secure delegation id for explicit->anonymous or anonymous->explicit where explicit is me or parent
|
|
287
|
-
if (!remainingDelegations.length)
|
|
288
|
-
return yield __await(void 0);
|
|
289
|
-
const allHashes = [
|
|
290
|
-
...remainingDelegations.flatMap((x) => x.hashes),
|
|
291
|
-
...Object.keys((_l = (_k = typedEntity.entity.securityMetadata) === null || _k === void 0 ? void 0 : _k.keysEquivalences) !== null && _l !== void 0 ? _l : {}),
|
|
292
|
-
];
|
|
293
|
-
const encryptedExchangeDataIdsByDelegationKey = (yield __await(self.exchangeDataMap.getExchangeDataMapBatch(allHashes))).reduce((maps, current) => {
|
|
294
|
-
return Object.assign(Object.assign({}, maps), { [current.id]: current });
|
|
295
|
-
}, {});
|
|
296
|
-
for (const decryptionDetails of remainingDelegations) {
|
|
297
|
-
const decryptedExchangeDataId = yield __await(getFirstDecryptedExchangeDataIdForHash(decryptionDetails.hashes, encryptedExchangeDataIdsByDelegationKey));
|
|
298
|
-
if (decryptedExchangeDataId) {
|
|
299
|
-
const exchangeDataDetails = yield __await(self.exchangeData.getDecryptionDataKeyById(decryptedExchangeDataId, typedEntity.type, (_m = typedEntity.entity.secretForeignKeys) !== null && _m !== void 0 ? _m : [], true));
|
|
300
|
-
if (exchangeDataDetails) {
|
|
301
|
-
for (const decrypted of yield __await(decrypt(decryptionDetails.delegation, exchangeDataDetails)))
|
|
302
|
-
yield yield __await(decrypted);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
return generator();
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
exports.SecureDelegationsSecurityMetadataDecryptor = SecureDelegationsSecurityMetadataDecryptor;
|
|
312
|
-
//# sourceMappingURL=SecureDelegationsSecurityMetadataDecryptor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SecureDelegationsSecurityMetadataDecryptor.js","sourceRoot":"","sources":["../../../icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.ts"],"names":[],"mappings":"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","sourcesContent":["import { SecurityMetadataDecryptor } from './SecurityMetadataDecryptor'\nimport { SecureDelegation } from '../../icc-api/model/SecureDelegation'\nimport { ExchangeDataManager } from './ExchangeDataManager'\nimport { EncryptedEntityWithType } from '../utils/EntityWithDelegationTypeName'\nimport { ExchangeData } from '../../icc-api/model/internal/ExchangeData'\nimport { SecureDelegationsEncryption } from './SecureDelegationsEncryption'\nimport AccessLevel = SecureDelegation.AccessLevelEnum\nimport { EncryptedEntity, EncryptedEntityStub } from '../../icc-api/model/models'\nimport { IccDataOwnerXApi } from '../icc-data-owner-x-api'\nimport { ExchangeDataMapManager } from './ExchangeDataMapManager'\nimport { ExchangeDataMap } from '../../icc-api/model/internal/ExchangeDataMap'\nimport AccessLevelEnum = SecureDelegation.AccessLevelEnum\n\ntype DelegationDecryptionDetails = {\n delegation: SecureDelegation\n hashes: string[]\n}\n\nexport type DelegationMembersDetails = {\n delegator: string | undefined\n delegate: string | undefined\n fullyExplicit: boolean\n accessControlSecret: string | undefined\n accessLevel: AccessLevelEnum\n}\n\nexport class SecureDelegationsSecurityMetadataDecryptor implements SecurityMetadataDecryptor {\n constructor(\n private readonly exchangeData: ExchangeDataManager,\n private readonly exchangeDataMap: ExchangeDataMapManager,\n private readonly secureDelegationsEncryption: SecureDelegationsEncryption,\n private readonly dataOwnerApi: IccDataOwnerXApi\n ) {}\n\n decryptEncryptionKeysOf(\n typedEntity: EncryptedEntityWithType,\n dataOwnersHierarchySubset: string[]\n ): AsyncGenerator<{ decrypted: string; dataOwnersWithAccess: string[] }, void, never> {\n return this.decryptSecureDelegations(\n typedEntity,\n dataOwnersHierarchySubset,\n (d) => d.encryptionKeys ?? [],\n (e, k) => this.secureDelegationsEncryption.decryptEncryptionKey(e, k)\n )\n }\n\n decryptOwningEntityIdsOf(\n typedEntity: EncryptedEntityWithType,\n dataOwnersHierarchySubset: string[]\n ): AsyncGenerator<{ decrypted: string; dataOwnersWithAccess: string[] }, void, never> {\n return this.decryptSecureDelegations(\n typedEntity,\n dataOwnersHierarchySubset,\n (d) => d.owningEntityIds ?? [],\n (e, k) => this.secureDelegationsEncryption.decryptOwningEntityId(e, k)\n )\n }\n\n decryptSecretIdsOf(\n typedEntity: EncryptedEntityWithType,\n dataOwnersHierarchySubset: string[]\n ): AsyncGenerator<{ decrypted: string; dataOwnersWithAccess: string[] }, void, never> {\n return this.decryptSecureDelegations(\n typedEntity,\n dataOwnersHierarchySubset,\n (d) => d.secretIds ?? [],\n (e, k) => this.secureDelegationsEncryption.decryptSecretId(e, k)\n )\n }\n\n /**\n * Get information for members of secure delegations in the entity. Also provides information for delegations with anonymous delegate and/or\n * delegator if one of the delegation members is the current data owner (or a parent) AND has still access to the exchange data used in the .\n */\n async getDelegationMemberDetails(typedEntity: EncryptedEntityWithType): Promise<{\n [delegationKey: string]: DelegationMembersDetails\n }> {\n const res: { [delegationKey: string]: DelegationMembersDetails } = {}\n // 1. Add all explicit data owners, keep only delegations with at least an anonymous data owner to check later\n let remainingDelegations = Object.entries(typedEntity.entity.securityMetadata?.secureDelegations ?? {})\n let updatedRemainingDelegations: [string, SecureDelegation][] = []\n for (const delegationEntry of remainingDelegations) {\n const delegation = delegationEntry[1]\n if (delegation.delegator && delegation.delegate) {\n res[delegationEntry[0]] = {\n delegate: delegation.delegate,\n delegator: delegation.delegator,\n fullyExplicit: true,\n accessLevel: delegation.permissions,\n accessControlSecret: undefined,\n }\n } else {\n updatedRemainingDelegations.push(delegationEntry)\n }\n }\n remainingDelegations = updatedRemainingDelegations\n if (!remainingDelegations.length) return res\n updatedRemainingDelegations = []\n // 2. Attempt to identify the anonymous data owner of remaining delegations by checking if we have the exchange data cached by hash\n // Note: we can find exchange data by hash only if we could successfully decrypt it\n const cachedExchangeData = await this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash(\n remainingDelegations.map((d) => d[0]),\n typedEntity.type,\n typedEntity.entity.secretForeignKeys ?? []\n )\n for (const delegationEntry of remainingDelegations) {\n const exchangeDataOfDelegation = cachedExchangeData[delegationEntry[0]]\n if (exchangeDataOfDelegation) {\n res[delegationEntry[0]] = {\n delegate: exchangeDataOfDelegation.exchangeData.delegate,\n delegator: exchangeDataOfDelegation.exchangeData.delegator,\n fullyExplicit: false,\n accessLevel: delegationEntry[1].permissions,\n accessControlSecret: exchangeDataOfDelegation.accessControlSecret,\n }\n } else {\n updatedRemainingDelegations.push(delegationEntry)\n }\n }\n remainingDelegations = updatedRemainingDelegations\n if (!remainingDelegations.length) return res\n updatedRemainingDelegations = []\n // 3. Attempt to identify the anonymous data owner of remaining delegations between us (or one of our parents) and an anonymous data owner\n const hierarchy = await this.dataOwnerApi.getCurrentDataOwnerHierarchyIds()\n const allHashes = [\n ...remainingDelegations.flatMap(([hash, _]) => hash),\n ...Object.keys(typedEntity.entity.securityMetadata?.keysEquivalences ?? {}),\n ]\n const encryptedExchangeDataIds = (await this.exchangeDataMap.getExchangeDataMapBatch(allHashes)).reduce((maps, current) => {\n return {\n ...maps,\n [current.id]: current,\n }\n }, {} as { [hash: string]: ExchangeDataMap })\n for (const [hash, delegation] of remainingDelegations) {\n if (hierarchy.some((x) => x === delegation.delegate || x === delegation.delegator)) {\n const dataId = !!encryptedExchangeDataIds[hash]\n ? await this.secureDelegationsEncryption.decryptExchangeDataId(encryptedExchangeDataIds[hash].encryptedExchangeDataIds)\n : undefined\n const exchangeDataInfo = dataId\n ? await this.exchangeData.getDecryptionDataKeyById(dataId, typedEntity.type, typedEntity.entity.secretForeignKeys ?? [], true)\n : undefined\n if (exchangeDataInfo) {\n res[hash] = {\n delegator: exchangeDataInfo.exchangeData.delegator,\n delegate: exchangeDataInfo.exchangeData.delegate,\n fullyExplicit: false,\n accessLevel: delegation.permissions,\n accessControlSecret: exchangeDataInfo.accessControlSecret,\n }\n } else {\n updatedRemainingDelegations.push([hash, delegation])\n }\n } else {\n updatedRemainingDelegations.push([hash, delegation])\n }\n }\n return {\n ...res,\n ...Object.fromEntries(\n updatedRemainingDelegations.map(([hash, secureDelegation]) => [\n hash,\n {\n delegator: secureDelegation.delegator,\n delegate: secureDelegation.delegate,\n fullyExplicit: false,\n accessLevel: secureDelegation.permissions,\n accessControlSecret: undefined,\n },\n ])\n ),\n }\n }\n\n hasAnyEncryptionKeys(entity: EncryptedEntity | EncryptedEntityStub): boolean {\n return Object.values(entity.securityMetadata?.secureDelegations ?? {}).some((d) => d.encryptionKeys?.length)\n }\n\n async getEntityAccessLevel(typedEntity: EncryptedEntityWithType, dataOwnersHierarchySubset: string[]): Promise<AccessLevel | undefined> {\n if (!dataOwnersHierarchySubset.length) throw new Error(\"`dataOwnersHierarchySubset` can't be empty\")\n // If the data owner is explicit all delegations he can access has his id. If the delegator is anonymous all delegations he can access are\n // accessible by hash. No mixed scenario possible.\n let accessibleDelegations: SecureDelegation[] = Object.values(typedEntity.entity.securityMetadata?.secureDelegations ?? {}).filter(\n (secureDelegation) =>\n dataOwnersHierarchySubset.some((dataOwner) => dataOwner === secureDelegation.delegator || dataOwner === secureDelegation.delegate)\n )\n if (!accessibleDelegations.length) {\n const equivalences = typedEntity.entity.securityMetadata?.keysEquivalences\n const availableCanonicalHashes = Array.from(\n new Set(\n Object.keys(\n await this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash(\n [\n ...Object.keys(typedEntity.entity.securityMetadata?.secureDelegations ?? {}),\n ...Object.keys(typedEntity.entity.securityMetadata?.keysEquivalences ?? {}),\n ],\n typedEntity.type,\n typedEntity.entity.secretForeignKeys ?? []\n )\n ).map((hash) => {\n const canonicalEquivalence = equivalences ? equivalences[hash] : undefined\n return canonicalEquivalence ? canonicalEquivalence : hash\n })\n )\n )\n accessibleDelegations = availableCanonicalHashes.map((hash) => (typedEntity.entity.securityMetadata?.secureDelegations ?? {})[hash])\n }\n\n const permissions = accessibleDelegations.map((secureDelegation) => secureDelegation.permissions)\n let maxLevel: AccessLevel | undefined = undefined\n for (const permission of permissions) {\n if (permission === AccessLevel.WRITE) {\n return AccessLevel.WRITE\n }\n if (permission === AccessLevel.READ) {\n maxLevel = AccessLevel.READ\n }\n }\n return maxLevel\n }\n\n private decryptSecureDelegations(\n typedEntity: EncryptedEntityWithType,\n dataOwnersHierarchySubset: string[],\n getDataToDecrypt: (delegation: SecureDelegation) => string[],\n decryptDataWithKey: (encryptedData: string, key: CryptoKey) => Promise<string>\n ): AsyncGenerator<{ decrypted: string; dataOwnersWithAccess: string[] }, void, never> {\n if (!dataOwnersHierarchySubset.length) throw new Error(\"`dataOwnersHierarchySubset` can't be empty\")\n const self = this\n\n async function getFirstDecryptedExchangeDataIdForHash(\n hashes: string[],\n encryptedExchangeDataIdsByDelegationKey: { [hash: string]: ExchangeDataMap }\n ): Promise<string | undefined> {\n for (const hash of new Set(hashes)) {\n const decryptedExchangeDataId = !!encryptedExchangeDataIdsByDelegationKey[hash]\n ? await self.secureDelegationsEncryption.decryptExchangeDataId(encryptedExchangeDataIdsByDelegationKey[hash]?.encryptedExchangeDataIds)\n : undefined\n if (!!decryptedExchangeDataId) return decryptedExchangeDataId\n }\n }\n\n async function decrypt(\n delegation: SecureDelegation,\n exchangeDataDetails: { exchangeData: ExchangeData; exchangeKey: CryptoKey | undefined }\n ): Promise<{ decrypted: string; dataOwnersWithAccess: string[] }[]> {\n if (!exchangeDataDetails.exchangeKey) return []\n const dataToDecrypt = getDataToDecrypt(delegation)\n if (!dataToDecrypt.length) return []\n if (!dataOwnersHierarchySubset.some((x) => x === exchangeDataDetails.exchangeData.delegator || x === exchangeDataDetails.exchangeData.delegate))\n return []\n const dataOwnersWithAccess = [exchangeDataDetails.exchangeData.delegator, exchangeDataDetails.exchangeData.delegate]\n const res = []\n for (const curr of dataToDecrypt) {\n res.push({ decrypted: await decryptDataWithKey(curr, exchangeDataDetails.exchangeKey), dataOwnersWithAccess })\n }\n return res\n }\n\n async function* generator(): AsyncGenerator<{ decrypted: string; dataOwnersWithAccess: string[] }, void, never> {\n let remainingDelegations: DelegationDecryptionDetails[] = Object.entries(typedEntity.entity.securityMetadata?.secureDelegations ?? {}).map(\n ([canonicalHash, delegation]) => ({\n delegation,\n hashes: [\n canonicalHash,\n ...Object.entries(typedEntity.entity.securityMetadata?.keysEquivalences ?? {})\n .filter((x) => x[1] == canonicalHash)\n .map((x) => x[0]),\n ],\n })\n )\n\n /*\n * Generate from least expensive to most (in terms of time to decrypt). 1 and 2a have equivalent costs.\n * 1) Secure delegations with cached exchange data by hash\n * 2) Secure delegations with cached exchange data by id for explicit->explicit delegations where delegator and/or delegate is me or parent\n * 3) Non cached secure delegations for explicit->explicit delegations where delegator and/or delegate is me or parent (half of old 3)\n * 4) Decrypt secure delegation id for explicit->anonymous or anonymous->explicit where explicit is me or parent (2b and half of old3)\n */\n\n // Step 1) Secure delegations with cached exchange data by hash\n if (!remainingDelegations.length) return\n const cachedDataByHash = await self.exchangeData.getCachedDecryptionDataKeyByAccessControlHash(\n [\n ...Object.keys(typedEntity.entity.securityMetadata?.secureDelegations ?? {}),\n ...Object.keys(typedEntity.entity.securityMetadata?.keysEquivalences ?? {}),\n ],\n typedEntity.type,\n typedEntity.entity.secretForeignKeys ?? []\n )\n let updatedRemainingDelegations: DelegationDecryptionDetails[] = []\n for (const decryptionDetails of remainingDelegations) {\n const exchangeDataDetails = decryptionDetails.hashes.map((h) => cachedDataByHash?.[h]).find((x) => !!x)\n if (exchangeDataDetails) {\n for (const decrypted of await decrypt(decryptionDetails.delegation, exchangeDataDetails)) yield decrypted\n } else if (\n (!!decryptionDetails.delegation.delegate || !!decryptionDetails.delegation.delegator) &&\n dataOwnersHierarchySubset.some((x) => x === decryptionDetails.delegation.delegate || x === decryptionDetails.delegation.delegator)\n ) {\n updatedRemainingDelegations.push(decryptionDetails)\n }\n }\n remainingDelegations = updatedRemainingDelegations\n updatedRemainingDelegations = []\n\n // Step 2) Secure delegations with cached exchange data by id for explicit->explicit delegations where delegator and/or delegate is me or parent\n if (!remainingDelegations.length) return\n for (const decryptionDetails of remainingDelegations) {\n const exchangeDataDetails = decryptionDetails.delegation.exchangeDataId\n ? await self.exchangeData.getDecryptionDataKeyById(\n decryptionDetails.delegation.exchangeDataId,\n typedEntity.type,\n typedEntity.entity.secretForeignKeys ?? [],\n false\n )\n : undefined\n if (!!exchangeDataDetails) {\n for (const decrypted of await decrypt(decryptionDetails.delegation, exchangeDataDetails)) yield decrypted\n } else {\n updatedRemainingDelegations.push(decryptionDetails)\n }\n }\n remainingDelegations = updatedRemainingDelegations\n updatedRemainingDelegations = []\n\n // Step 3) Non cached secure delegations for explicit->explicit delegations where delegator and/or delegate is me or parent\n if (!remainingDelegations.length) return\n for (const decryptionDetails of remainingDelegations) {\n const exchangeDataDetails = decryptionDetails.delegation.exchangeDataId\n ? await self.exchangeData.getDecryptionDataKeyById(\n decryptionDetails.delegation.exchangeDataId,\n typedEntity.type,\n typedEntity.entity.secretForeignKeys ?? [],\n true\n )\n : undefined\n if (!!exchangeDataDetails) {\n for (const decrypted of await decrypt(decryptionDetails.delegation, exchangeDataDetails)) yield decrypted\n } else {\n updatedRemainingDelegations.push(decryptionDetails)\n }\n }\n remainingDelegations = updatedRemainingDelegations\n\n // Step 4) Decrypt secure delegation id for explicit->anonymous or anonymous->explicit where explicit is me or parent\n if (!remainingDelegations.length) return\n const allHashes = [\n ...remainingDelegations.flatMap((x) => x.hashes),\n ...Object.keys(typedEntity.entity.securityMetadata?.keysEquivalences ?? {}),\n ]\n const encryptedExchangeDataIdsByDelegationKey = (await self.exchangeDataMap.getExchangeDataMapBatch(allHashes)).reduce((maps, current) => {\n return {\n ...maps,\n [current.id]: current,\n }\n }, {} as { [hash: string]: ExchangeDataMap })\n for (const decryptionDetails of remainingDelegations) {\n const decryptedExchangeDataId = await getFirstDecryptedExchangeDataIdForHash(\n decryptionDetails.hashes,\n encryptedExchangeDataIdsByDelegationKey\n )\n if (decryptedExchangeDataId) {\n const exchangeDataDetails = await self.exchangeData.getDecryptionDataKeyById(\n decryptedExchangeDataId,\n typedEntity.type,\n typedEntity.entity.secretForeignKeys ?? [],\n true\n )\n if (exchangeDataDetails) {\n for (const decrypted of await decrypt(decryptionDetails.delegation, exchangeDataDetails)) yield decrypted\n }\n }\n }\n }\n\n return generator()\n }\n}\n"]}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { IcureStorageFacade } from '../storage/IcureStorageFacade';
|
|
2
|
-
import { IccDataOwnerXApi } from '../icc-data-owner-x-api';
|
|
3
|
-
import { CryptoPrimitives } from './CryptoPrimitives';
|
|
4
|
-
import { KeyPair } from './RSA';
|
|
5
|
-
export declare class UserSignatureKeysManager {
|
|
6
|
-
private readonly iCureStorage;
|
|
7
|
-
private readonly dataOwnerApi;
|
|
8
|
-
private readonly primitives;
|
|
9
|
-
constructor(iCureStorage: IcureStorageFacade, dataOwnerApi: IccDataOwnerXApi, primitives: CryptoPrimitives);
|
|
10
|
-
private signatureKeysCache;
|
|
11
|
-
private verificationKeysCache;
|
|
12
|
-
/**
|
|
13
|
-
* Get a key which can be used to sign data in order to allow verification of the data authenticity in the future.
|
|
14
|
-
*/
|
|
15
|
-
getOrCreateSignatureKeyPair(): Promise<{
|
|
16
|
-
fingerprint: string;
|
|
17
|
-
keyPair: KeyPair<CryptoKey>;
|
|
18
|
-
}>;
|
|
19
|
-
/**
|
|
20
|
-
* Get all available keys which can be used to verify the authenticity of a signature which should have been created
|
|
21
|
-
* by the current data owner.
|
|
22
|
-
* @param fingerprint v2 fingerprint of the key to retrieve.
|
|
23
|
-
* @return all available verification keys by fingerprint.
|
|
24
|
-
*/
|
|
25
|
-
getSignatureVerificationKey(fingerprint: string): Promise<CryptoKey | undefined>;
|
|
26
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.UserSignatureKeysManager = void 0;
|
|
13
|
-
const utils_1 = require("../utils");
|
|
14
|
-
const utils_2 = require("./utils");
|
|
15
|
-
class UserSignatureKeysManager {
|
|
16
|
-
constructor(iCureStorage, dataOwnerApi, primitives) {
|
|
17
|
-
this.iCureStorage = iCureStorage;
|
|
18
|
-
this.dataOwnerApi = dataOwnerApi;
|
|
19
|
-
this.primitives = primitives;
|
|
20
|
-
this.signatureKeysCache = undefined;
|
|
21
|
-
this.verificationKeysCache = new Map();
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Get a key which can be used to sign data in order to allow verification of the data authenticity in the future.
|
|
25
|
-
*/
|
|
26
|
-
getOrCreateSignatureKeyPair() {
|
|
27
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
-
if (this.signatureKeysCache)
|
|
29
|
-
return this.signatureKeysCache;
|
|
30
|
-
const dataOwnerId = yield this.dataOwnerApi.getCurrentDataOwnerId();
|
|
31
|
-
const existing = yield this.iCureStorage.loadSignatureKey(dataOwnerId);
|
|
32
|
-
if (existing) {
|
|
33
|
-
const fingerprint = (0, utils_2.fingerprintV1)((0, utils_1.jwk2spki)(existing.publicKey));
|
|
34
|
-
this.signatureKeysCache = {
|
|
35
|
-
fingerprint,
|
|
36
|
-
keyPair: {
|
|
37
|
-
privateKey: yield this.primitives.RSA.importSignatureKey('jwk', existing.privateKey),
|
|
38
|
-
publicKey: yield this.primitives.RSA.importVerificationKey('jwk', existing.publicKey),
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
return this.signatureKeysCache;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
const generatedPair = yield this.primitives.RSA.generateSignatureKeyPair();
|
|
45
|
-
const exportedPub = (0, utils_1.ua2hex)(yield this.primitives.RSA.exportKey(generatedPair.publicKey, 'spki'));
|
|
46
|
-
(0, utils_2.checkStandardPublicKeyTail)(exportedPub);
|
|
47
|
-
const fpV2 = (0, utils_2.fingerprintV2)(exportedPub);
|
|
48
|
-
// For consistency with encryption keys we use fpv1 when saving
|
|
49
|
-
yield this.iCureStorage.saveSignatureKeyPair(dataOwnerId, (0, utils_2.fingerprintV1)(exportedPub), yield this.primitives.RSA.exportKeys(generatedPair, 'jwk', 'jwk'));
|
|
50
|
-
this.verificationKeysCache.set(fpV2, generatedPair.publicKey);
|
|
51
|
-
this.signatureKeysCache = { fingerprint: fpV2, keyPair: generatedPair };
|
|
52
|
-
return this.signatureKeysCache;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Get all available keys which can be used to verify the authenticity of a signature which should have been created
|
|
58
|
-
* by the current data owner.
|
|
59
|
-
* @param fingerprint v2 fingerprint of the key to retrieve.
|
|
60
|
-
* @return all available verification keys by fingerprint.
|
|
61
|
-
*/
|
|
62
|
-
getSignatureVerificationKey(fingerprint) {
|
|
63
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
const cached = this.verificationKeysCache.get(fingerprint);
|
|
65
|
-
if (cached)
|
|
66
|
-
return cached;
|
|
67
|
-
// For consistency with encryption keys we use fpv1 when saving
|
|
68
|
-
const loaded = yield this.iCureStorage.loadSignatureVerificationKey(yield this.dataOwnerApi.getCurrentDataOwnerId(), (0, utils_2.fingerprintV2ToStandardV1)(fingerprint));
|
|
69
|
-
if (loaded) {
|
|
70
|
-
const imported = yield this.primitives.RSA.importVerificationKey('jwk', loaded);
|
|
71
|
-
this.verificationKeysCache.set(fingerprint, imported);
|
|
72
|
-
return imported;
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.UserSignatureKeysManager = UserSignatureKeysManager;
|
|
78
|
-
//# sourceMappingURL=UserSignatureKeysManager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UserSignatureKeysManager.js","sourceRoot":"","sources":["../../../icc-x-api/crypto/UserSignatureKeysManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { IcureStorageFacade } from '../storage/IcureStorageFacade'\nimport { IccDataOwnerXApi } from '../icc-data-owner-x-api'\nimport { CryptoPrimitives } from './CryptoPrimitives'\nimport { hex2ua, jwk2spki, ua2hex } from '../utils'\nimport { KeyPair } from './RSA'\nimport { checkStandardPublicKeyTail, fingerprintV1, fingerprintV2, fingerprintV2ToStandardV1 } from './utils'\n\nexport class UserSignatureKeysManager {\n constructor(\n private readonly iCureStorage: IcureStorageFacade,\n private readonly dataOwnerApi: IccDataOwnerXApi,\n private readonly primitives: CryptoPrimitives\n ) {}\n\n private signatureKeysCache:\n | {\n fingerprint: string\n keyPair: KeyPair<CryptoKey>\n }\n | undefined = undefined\n private verificationKeysCache = new Map<string, CryptoKey>()\n\n /**\n * Get a key which can be used to sign data in order to allow verification of the data authenticity in the future.\n */\n async getOrCreateSignatureKeyPair(): Promise<{\n fingerprint: string\n keyPair: KeyPair<CryptoKey>\n }> {\n if (this.signatureKeysCache) return this.signatureKeysCache\n const dataOwnerId = await this.dataOwnerApi.getCurrentDataOwnerId()\n const existing = await this.iCureStorage.loadSignatureKey(dataOwnerId)\n if (existing) {\n const fingerprint = fingerprintV1(jwk2spki(existing.publicKey))\n this.signatureKeysCache = {\n fingerprint,\n keyPair: {\n privateKey: await this.primitives.RSA.importSignatureKey('jwk', existing.privateKey),\n publicKey: await this.primitives.RSA.importVerificationKey('jwk', existing.publicKey),\n },\n }\n return this.signatureKeysCache\n } else {\n const generatedPair = await this.primitives.RSA.generateSignatureKeyPair()\n const exportedPub = ua2hex(await this.primitives.RSA.exportKey(generatedPair.publicKey, 'spki'))\n checkStandardPublicKeyTail(exportedPub)\n const fpV2 = fingerprintV2(exportedPub)\n // For consistency with encryption keys we use fpv1 when saving\n await this.iCureStorage.saveSignatureKeyPair(\n dataOwnerId,\n fingerprintV1(exportedPub),\n await this.primitives.RSA.exportKeys(generatedPair, 'jwk', 'jwk')\n )\n this.verificationKeysCache.set(fpV2, generatedPair.publicKey)\n this.signatureKeysCache = { fingerprint: fpV2, keyPair: generatedPair }\n return this.signatureKeysCache\n }\n }\n\n /**\n * Get all available keys which can be used to verify the authenticity of a signature which should have been created\n * by the current data owner.\n * @param fingerprint v2 fingerprint of the key to retrieve.\n * @return all available verification keys by fingerprint.\n */\n async getSignatureVerificationKey(fingerprint: string): Promise<CryptoKey | undefined> {\n const cached = this.verificationKeysCache.get(fingerprint)\n if (cached) return cached\n // For consistency with encryption keys we use fpv1 when saving\n const loaded = await this.iCureStorage.loadSignatureVerificationKey(\n await this.dataOwnerApi.getCurrentDataOwnerId(),\n fingerprintV2ToStandardV1(fingerprint)\n )\n if (loaded) {\n const imported = await this.primitives.RSA.importVerificationKey('jwk', loaded)\n this.verificationKeysCache.set(fingerprint, imported)\n return imported\n }\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|