@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.
- package/icc-x-api/icc-crypto-x-api.d.ts +4 -2
- package/icc-x-api/icc-crypto-x-api.js +68 -46
- package/icc-x-api/icc-crypto-x-api.js.map +1 -1
- package/icc-x-api/icc-helement-x-api.d.ts +1 -1
- package/icc-x-api/icc-helement-x-api.js +27 -22
- package/icc-x-api/icc-helement-x-api.js.map +1 -1
- package/icc-x-api/index.js +2 -1
- package/icc-x-api/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -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,
|
|
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
|
|
923
|
-
|
|
924
|
-
const
|
|
925
|
-
|
|
926
|
-
|
|
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
|
-
|
|
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
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
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) {
|