"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseExchangeDataManager = void 0;
const ExchangeData_1 = require("../../icc-api/model/internal/ExchangeData");
const XHR_1 = require("../../icc-api/api/XHR");
const utils_1 = require("../utils");
const collection_utils_1 = require("../utils/collection-utils");
const utils_2 = require("./utils");
var XHRError = XHR_1.XHR.XHRError;
/**
 * @internal this class is intended for internal use only and may be modified without notice
 * Functions to create and get exchange data.
 * The methods of this api require to pass the appropriate keys for encryption/decryption manually.
 */
class BaseExchangeDataManager {
    constructor(api, dataOwnerApi, primitives, selfRequiresAnonymousDelegations, doNotUseBulkGet) {
        this.api = api;
        this.dataOwnerApi = dataOwnerApi;
        this.primitives = primitives;
        this.selfRequiresAnonymousDelegations = selfRequiresAnonymousDelegations;
        this.doNotUseBulkGet = doNotUseBulkGet;
    }
    /**
     * Get all the exchange data where the current data owner is the delegator or the delegate. However, some data owners, generally HCPs, may have a
     * prohibitively high amount of exchange data. If the crypto strategies specify that the current data owner requires anonymous delegation this
     * method returns all the exchange data found for the data owner, else the method returns undefined.
     * @return all the exchange data for the current data owner or undefined if the crypto strategies don't allow to retrieve all data for the current
     * data owner.
     */
    getAllExchangeDataForCurrentDataOwnerIfAllowed() {
        return __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            if (!this.selfRequiresAnonymousDelegations)
                return undefined;
            const dataOwnerId = yield this.dataOwnerApi.getCurrentDataOwnerId();
            let latestResult = yield this.api.getExchangeDataByParticipant(dataOwnerId, undefined, 1000);
            const allRetrieved = (_a = latestResult.rows) !== null && _a !== void 0 ? _a : [];
            while ((_b = latestResult.nextKeyPair) === null || _b === void 0 ? void 0 : _b.startKeyDocId) {
                latestResult = yield this.api.getExchangeDataByParticipant(dataOwnerId, latestResult.nextKeyPair.startKeyDocId, 1000);
                if (latestResult.rows)
                    allRetrieved.push(...latestResult.rows);
            }
            return allRetrieved;
        });
    }
    /**
     * Get all exchange data for the provided delegator-delegate pair.
     * @param delegatorId id of a delegator data owner.
     * @param delegateId id of a delegate data owner.
     * @return all exchange data for the provided delegator-delegate pair.
     */
    getExchangeDataByDelegatorDelegatePair(delegatorId, delegateId) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.api.getExchangeDataByDelegatorDelegate(delegatorId, delegateId);
        });
    }
    /**
     * Get the exchange data with the provided id.
     * @param exchangeDataId id of the exchange data.
     * @return the exchange data with the provided id or undefined if no exchange data with such id could be found.
     */
    getExchangeDataById(exchangeDataId) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.api.getExchangeDataById(exchangeDataId).catch((e) => {
                if (e instanceof XHRError && e.statusCode === 404) {
                    return undefined;
                }
                else
                    throw e;
            });
        });
    }
    getExchangeDataByIds(exchangeDataIds) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.doNotUseBulkGet) {
                const res = [];
                for (const exchangeDataId of exchangeDataIds) {
                    const curr = yield this.api.getExchangeDataById(exchangeDataId).catch((e) => {
                        if (e instanceof XHRError && (e.statusCode === 404 || e.statusCode === 403)) {
                            return undefined;
                        }
                        else
                            throw e;
                    });
                    if (curr)
                        res.push(curr);
                }
                return res;
            }
            else {
                return yield this.api.getExchangeDataByIds({ ids: exchangeDataIds });
            }
        });
    }
    /**
     * Verifies the authenticity of the exchange data by checking the signature.
     * Note that all exchange data created by data owners other than the current data owner (including members of his hierarchy)
     * will always be unverified.
     * @param data collects the following information about the exchange data being verified:
     * - exchangeData the exchange data to verify.
     * - decryptedAccessControlSecret the access control secret decrypted from the exchange data.
     * - decryptedExchangeKey the exchange key decrypted from the exchange data.
     * - decryptedSharedSignatureKey the shared signature key decrypted from the exchange data.
     * @param verificationKeys verification keys for delegator signature by fingerprint.
     * @param verifyAsDelegator if true the method will also verify that the hmac key used for the signature was created by the delegator of the
     * exchange data. If true and the data was not created by the current data owner this method will return false.
     * @return the exchange data which could be verified given his signature and the available verification keys.
     * @throws if any of the provided exchange data has been created by a data owner other than the current data owner.
     */
    verifyExchangeData(data, verificationKeys, verifyAsDelegator) {
        return __awaiter(this, void 0, void 0, function* () {
            if (verifyAsDelegator && data.exchangeData.delegator !== (yield this.dataOwnerApi.getCurrentDataOwnerId()))
                return false;
            if (verifyAsDelegator && !(yield this.verifyDelegatorSignature(data.exchangeData, data.decryptedSharedSignatureKey, verificationKeys)))
                return false;
            const sharedSignatureData = yield this.bytesToSignForSharedSignature({
                decryptedAccessControlSecret: data.decryptedAccessControlSecret,
                decryptedExchangeKey: data.decryptedExchangeKey,
                delegator: data.exchangeData.delegator,
                delegate: data.exchangeData.delegate,
                publicKeysFingerprintsV2: [
                    ...new Set([
                        ...Object.keys(data.exchangeData.exchangeKey),
                        ...Object.keys(data.exchangeData.accessControlSecret),
                        ...Object.keys(data.exchangeData.sharedSignatureKey),
                    ]),
                ],
            });
            return yield this.verifyDataWithSharedKey(sharedSignatureData, data.decryptedSharedSignatureKey, data.exchangeData.sharedSignature);
        });
    }
    /**
     * Extracts and decrypts the access control secret from the provided exchange data.
     * These need to be hashed together with the entity class and confidentiality level in order to get the actual access control key
     * which will be sent to the server.
     * @param exchangeData the exchange data from which to extract access control secrets.
     * @param decryptionKeys rsa key pairs to use for decryption of the access control secret.
     * @return an object composed of:
     * - successfulDecryptions: array of all successfully decrypted access control keys
     * - failedDecryptions: array containing all exchange data for which the access control key could not be decrypted (using the provided keys).
     */
    tryDecryptAccessControlSecret(exchangeData, decryptionKeys) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.tryDecryptExchangeData(exchangeData, decryptionKeys, (ed) => ed.accessControlSecret, (d) => this.importAccessControlSecret(new Uint8Array(d).buffer));
        });
    }
    /**
     * Extract and decrypts the exchange keys from the provided exchange data.
     * @param exchangeData the exchange data from which to extract exchange keys.
     * @param decryptionKeys rsa key pairs to use for the decryption of the exchange keys.
     * @return an object composed of:
     * - successfulDecryptions: array containing the successfully decrypted exchange keys.
     * - failedDecryptions: array containing all exchange data for which the access control key could not be decrypted (using the provided keys).
     */
    tryDecryptExchangeKeys(exchangeData, decryptionKeys) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.tryDecryptExchangeData(exchangeData, decryptionKeys, (ed) => ed.exchangeKey, (d) => this.importExchangeKey(new Uint8Array(d).buffer));
        });
    }
    /**
     * Extract and decrypts the shared signature key from the provided exchange data.
     * @param exchangeData the exchange data from which to extract exchange keys.
     * @param decryptionKeys rsa key pairs to use for the decryption of the exchange keys.
     * @return an object composed of:
     * - successfulDecryptions: array containing the successfully decrypted exchange keys.
     * - failedDecryptions: array containing all exchange data for which the access control key could not be decrypted (using the provided keys).
     */
    tryDecryptSharedSignatureKeys(exchangeData, decryptionKeys) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.tryDecryptExchangeData(exchangeData, decryptionKeys, (ed) => ed.sharedSignatureKey, (d) => this.importSharedSignatureKey(new Uint8Array(d).buffer));
        });
    }
    tryDecryptExchangeData(exchangeData, decryptionKeys, encryptedDataSelector, unmarshalDecrypted) {
        return __awaiter(this, void 0, void 0, function* () {
            const successfulDecryptions = [];
            const failedDecryptions = [];
            for (const ed of exchangeData) {
                try {
                    const decrypted = yield this.tryDecrypt(encryptedDataSelector(ed), decryptionKeys);
                    if (decrypted) {
                        successfulDecryptions.push(yield unmarshalDecrypted(decrypted));
                    }
                    else {
                        failedDecryptions.push(ed);
                    }
                }
                catch (e) {
                    failedDecryptions.push(ed);
                }
            }
            return { successfulDecryptions, failedDecryptions };
        });
    }
    tryDecrypt(encryptedData, decryptionKeys) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a;
            const decryptionKeysWithV2Fp = Object.keys(decryptionKeys).reduce((prev, fp) => {
                return Object.assign(Object.assign({}, prev), { [(0, utils_2.fingerprintIsV1)(fp) ? (0, utils_2.fingerprintV1toV2)(fp) : fp]: decryptionKeys[fp] });
            }, {});
            for (const [fp, encrypted] of Object.entries(encryptedData)) {
                try {
                    const key = (_a = decryptionKeysWithV2Fp[fp]) === null || _a === void 0 ? void 0 : _a.privateKey;
                    if (key)
                        return yield this.primitives.RSA.decrypt(key, (0, utils_1.b64_2ua)(encrypted));
                }
                catch (e) {
                    // Try with another key
                }
            }
        });
    }
    /**
     * Creates exchange data from the current data owner to the provided delegate, uploading the newly created exchange data to the cloud.
     * This assumes that the keys have been verified.
     * @param delegateId id of the delegate for the new exchange data.
     * @param signatureKeys private keys to use for signing the created data.
     * @param encryptionKeys public keys to use for the encryption of the exchange data (from delegator and delegate).
     * @param optionalAttributes optional precalculated attributes for the creation of data
     * @return the newly created exchange data, and its decrypted exchange key and access control secret.
     */
    createExchangeData(delegateId_1, signatureKeys_1, encryptionKeys_1) {
        return __awaiter(this, arguments, void 0, function* (delegateId, signatureKeys, encryptionKeys, optionalAttributes = {}) {
            var _a;
            if (!Object.keys(encryptionKeys).length) {
                throw new Error('Must specify at least one encryption key ');
            }
            const exchangeKey = yield this.generateExchangeKey();
            const accessControlSecret = yield this.generateAccessControlSecret();
            const sharedSignatureKey = yield this.generateSharedSignatureKey();
            const encryptedExchangeKey = yield this.encryptDataWithKeys(exchangeKey.rawBytes, encryptionKeys);
            const encryptedAccessControlSecret = yield this.encryptDataWithKeys(accessControlSecret.rawBytes, encryptionKeys);
            const encryptedSharedSignatureKey = yield this.encryptDataWithKeys(sharedSignatureKey.rawBytes, encryptionKeys);
            const baseExchangeData = {
                id: (_a = optionalAttributes.id) !== null && _a !== void 0 ? _a : this.primitives.randomUuid(),
                delegator: yield this.dataOwnerApi.getCurrentDataOwnerId(),
                delegate: delegateId,
                exchangeKey: encryptedExchangeKey,
                accessControlSecret: encryptedAccessControlSecret,
                sharedSignatureKey: encryptedSharedSignatureKey,
            };
            const sharedSignature = yield this.signDataWithSharedKey(yield this.bytesToSignForSharedSignature({
                delegate: baseExchangeData.delegate,
                delegator: baseExchangeData.delegator,
                decryptedAccessControlSecret: accessControlSecret.secret,
                decryptedExchangeKey: exchangeKey.key,
                publicKeysFingerprintsV2: Object.keys(encryptionKeys).map(utils_2.fingerprintV1toV2),
            }), sharedSignatureKey.key);
            const delegatorSignature = yield this.signDataWithDelegatorKeys(yield this.bytesToSignForDelegatorSignature({
                sharedSignatureKey: sharedSignatureKey.key,
            }), signatureKeys);
            const exchangeData = new ExchangeData_1.ExchangeData(Object.assign(Object.assign({}, baseExchangeData), { delegatorSignature, sharedSignature }));
            return {
                exchangeData: yield this.api.createExchangeData(exchangeData),
                exchangeKey: exchangeKey.key,
                accessControlSecret: accessControlSecret.secret,
                sharedSignatureKey: sharedSignatureKey.key,
            };
        });
    }
    tryRawDecryptExchangeData(exchangeData, decryptionKeys) {
        return __awaiter(this, void 0, void 0, function* () {
            const rawExchangeKey = yield this.tryDecrypt(exchangeData.exchangeKey, decryptionKeys);
            const rawAccessControlSecret = yield this.tryDecrypt(exchangeData.accessControlSecret, decryptionKeys);
            const rawSharedSignatureKey = yield this.tryDecrypt(exchangeData.sharedSignatureKey, decryptionKeys);
            if (!rawExchangeKey || !rawAccessControlSecret || !rawSharedSignatureKey)
                return undefined;
            return { rawExchangeKey, rawAccessControlSecret, rawSharedSignatureKey };
        });
    }
    /**
     * Updates existing exchange data and uploads it to the cloud in order to share it also with additional public keys, useful for example in cases
     * where one of the data owners involved in the exchange data has lost one of his keys.
     * If the content of the exchange data could not be decrypted using the provided keys the method will not update anything and will return undefined.
     * This method assumes that the new encryption keys have been verified.
     * @param exchangeData exchange data to update.
     * @param decryptionKeys keys to use to extract the content of the exchange data which will be shared with the new keys.
     * @param newEncryptionKeys new keys to add to the exchange data.
     * @return the updated exchange data, and its decrypted exchange key and access control secret, or undefined if the exchange data content could not
     * be decrypted and the exchange data could not be updated.
     */
    tryUpdateExchangeData(exchangeData, decryptionKeys, newEncryptionKeys) {
        return __awaiter(this, void 0, void 0, function* () {
            const rawExchangeKey = yield this.tryDecrypt(exchangeData.exchangeKey, decryptionKeys);
            const rawAccessControlSecret = yield this.tryDecrypt(exchangeData.accessControlSecret, decryptionKeys);
            const rawSharedSignatureKey = yield this.tryDecrypt(exchangeData.sharedSignatureKey, decryptionKeys);
            if (!rawExchangeKey || !rawAccessControlSecret || !rawSharedSignatureKey)
                return undefined;
            return yield this.updateExchangeDataWithRawDecryptedContent({
                exchangeData: exchangeData,
                newEncryptionKeys: newEncryptionKeys,
                rawExchangeKey: rawExchangeKey,
                rawAccessControlSecret: rawAccessControlSecret,
                rawSharedSignatureKey: rawSharedSignatureKey,
                newDelegatorSignatureKeys: {},
            });
        });
    }
    /**
     * Same as [tryUpdateExchangeData] but the decrypted content is already provided.
     */
    updateExchangeDataWithRawDecryptedContent(_a) {
        return __awaiter(this, arguments, void 0, function* ({ exchangeData, newEncryptionKeys, rawExchangeKey, rawAccessControlSecret, rawSharedSignatureKey, newDelegatorSignatureKeys, }) {
            var _b;
            const self = yield this.dataOwnerApi.getCurrentDataOwnerId();
            const exchangeKey = yield this.importExchangeKey(new Uint8Array(rawExchangeKey).buffer);
            const accessControlSecret = yield this.importAccessControlSecret(new Uint8Array(rawAccessControlSecret).buffer);
            const sharedSignatureKey = yield this.importSharedSignatureKey(new Uint8Array(rawSharedSignatureKey).buffer);
            const existingExchangeKeyEntries = new Set(Object.keys(exchangeData.exchangeKey));
            const existingAcsEntries = new Set(Object.keys(exchangeData.accessControlSecret));
            const existingSharedSignatureKeyEntries = new Set(Object.keys(exchangeData.sharedSignatureKey));
            const missingEntries = Object.keys(newEncryptionKeys).filter((fp) => !existingAcsEntries.has(fp) || !existingExchangeKeyEntries.has(fp) || !existingSharedSignatureKeyEntries.has(fp));
            const existingDelegatorSignatureEntries = new Set(Object.keys((_b = exchangeData.delegatorSignature) !== null && _b !== void 0 ? _b : {}));
            const missingDelegatorSignatureEntries = exchangeData.delegator == self ? Object.keys(newDelegatorSignatureKeys).filter((fp) => !existingDelegatorSignatureEntries.has(fp)) : [];
            if (!missingEntries.length && !missingDelegatorSignatureEntries.length)
                return { exchangeData, exchangeKey, accessControlSecret };
            const encryptionKeysForMissingEntries = missingEntries.reduce((obj, fp) => {
                obj[fp] = newEncryptionKeys[fp];
                return obj;
            }, {});
            const updatedExchangeData = (0, collection_utils_1.cloneDeep)(exchangeData);
            updatedExchangeData.exchangeKey = Object.assign(Object.assign({}, exchangeData.exchangeKey), (yield this.encryptDataWithKeys(rawExchangeKey, encryptionKeysForMissingEntries)));
            updatedExchangeData.accessControlSecret = Object.assign(Object.assign({}, exchangeData.accessControlSecret), (yield this.encryptDataWithKeys(rawAccessControlSecret, encryptionKeysForMissingEntries)));
            updatedExchangeData.sharedSignatureKey = Object.assign(Object.assign({}, exchangeData.sharedSignatureKey), (yield this.encryptDataWithKeys(rawSharedSignatureKey, encryptionKeysForMissingEntries)));
            const isVerified = yield this.verifyExchangeData({
                exchangeData,
                decryptedAccessControlSecret: accessControlSecret,
                decryptedExchangeKey: exchangeKey,
                decryptedSharedSignatureKey: sharedSignatureKey,
            }, {}, false);
            if (isVerified) {
                updatedExchangeData.sharedSignature = yield this.signDataWithSharedKey(yield this.bytesToSignForSharedSignature({
                    delegate: updatedExchangeData.delegate,
                    delegator: updatedExchangeData.delegator,
                    decryptedAccessControlSecret: accessControlSecret,
                    decryptedExchangeKey: exchangeKey,
                    publicKeysFingerprintsV2: Object.keys(updatedExchangeData.exchangeKey),
                }), sharedSignatureKey);
            }
            if (missingDelegatorSignatureEntries.length > 0) {
                const bytesToSign = yield this.bytesToSignForDelegatorSignature({ sharedSignatureKey });
                const newSigned = yield this.signDataWithDelegatorKeys(bytesToSign, missingDelegatorSignatureEntries.reduce((obj, fp) => {
                    obj[fp] = newDelegatorSignatureKeys[fp];
                    return obj;
                }, {}));
                updatedExchangeData.delegatorSignature = Object.assign(Object.assign({}, updatedExchangeData.delegatorSignature), newSigned);
            }
            return { exchangeData: yield this.api.modifyExchangeData(new ExchangeData_1.ExchangeData(updatedExchangeData)), exchangeKey, accessControlSecret };
        });
    }
    bytesToSignForSharedSignature(data) {
        return __awaiter(this, void 0, void 0, function* () {
            // Use array of array to ensure that order is preserved regardless of how the specific js implementation orders
            // the keys of an object
            const signObject = [
                ['delegator', data.delegator],
                ['delegate', data.delegate],
                ['exchangeKey', (0, utils_1.ua2hex)(yield this.primitives.AES.exportKey(data.decryptedExchangeKey, 'raw'))],
                ['accessControlSecret', data.decryptedAccessControlSecret],
                ['publicKeysFingerprints', data.publicKeysFingerprintsV2.sort()],
            ];
            const signJson = JSON.stringify(signObject);
            return (0, utils_1.ua2ab)((0, utils_1.utf8_2ua)(signJson));
        });
    }
    bytesToSignForDelegatorSignature(data) {
        return __awaiter(this, void 0, void 0, function* () {
            return this.primitives.sha256(yield this.primitives.HMAC.exportKey(data.sharedSignatureKey));
        });
    }
    // Generates a new exchange key
    generateExchangeKey() {
        return __awaiter(this, void 0, void 0, function* () {
            const rawBytes = (0, utils_1.ua2ab)(this.primitives.randomBytes(32));
            return {
                key: yield this.importExchangeKey(rawBytes),
                rawBytes,
            };
        });
    }
    importExchangeKey(decryptedBytes) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.primitives.AES.importKey('raw', decryptedBytes);
        });
    }
    exportExchangeKey(key) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.primitives.AES.exportKey(key, 'raw');
        });
    }
    generateSharedSignatureKey() {
        return __awaiter(this, void 0, void 0, function* () {
            const key = yield this.primitives.HMAC.generateKey();
            return { key, rawBytes: yield this.primitives.HMAC.exportKey(key) };
        });
    }
    importSharedSignatureKey(decryptedBytes) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.primitives.HMAC.importKey(decryptedBytes);
        });
    }
    exportSharedSignatureKey(key) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.primitives.HMAC.exportKey(key);
        });
    }
    // Generates a new access control secret
    generateAccessControlSecret() {
        return __awaiter(this, void 0, void 0, function* () {
            const rawBytes = (0, utils_1.ua2ab)(this.primitives.randomBytes(16));
            return {
                secret: yield this.importAccessControlSecret(rawBytes),
                rawBytes,
            };
        });
    }
    importAccessControlSecret(decryptedBytes) {
        return Promise.resolve((0, utils_1.ua2hex)(decryptedBytes));
    }
    exportAccessControlSecret(secret) {
        return Promise.resolve((0, utils_1.ua2ab)((0, utils_1.hex2ua)(secret)));
    }
    encryptDataWithKeys(rawData, keys) {
        return __awaiter(this, void 0, void 0, function* () {
            const res = {};
            for (const [fp, key] of Object.entries(keys)) {
                res[(0, utils_2.fingerprintIsV1)(fp) ? (0, utils_2.fingerprintV1toV2)(fp) : fp] = (0, utils_1.ua2b64)(yield this.primitives.RSA.encrypt(key, new Uint8Array(rawData)));
            }
            return res;
        });
    }
    extractHmacFromRsaPrivate(privateRsaKey) {
        return __awaiter(this, void 0, void 0, function* () {
            if (privateRsaKey.algorithm.name != 'RSA-OAEP' && !privateRsaKey.usages.includes('decrypt')) {
                throw new Error('Internal error: got unexpected key for signature/verification');
            }
            const keyBytes = yield this.primitives.RSA.exportKey(privateRsaKey, 'pkcs8');
            const keyAsHmacBytes = yield this.primitives.sha512(keyBytes);
            return yield this.primitives.HMAC.importKey(keyAsHmacBytes, false);
        });
    }
    signDataWithDelegatorKeys(rawData, keys) {
        return __awaiter(this, void 0, void 0, function* () {
            const res = {};
            for (const [fp, key] of Object.entries(keys)) {
                res[(0, utils_2.fingerprintV1toV2)(fp)] = (0, utils_1.ua2b64)(yield this.primitives.HMAC.sign(yield this.extractHmacFromRsaPrivate(key), new Uint8Array(rawData).buffer));
            }
            return res;
        });
    }
    verifyDelegatorSignature(exchangeData, decryptedSharedSignatureKey, verificationKeys) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a;
            const delegatorSignatureData = yield this.bytesToSignForDelegatorSignature({
                sharedSignatureKey: decryptedSharedSignatureKey,
            });
            const keysByV2Fp = Object.fromEntries(Object.entries(verificationKeys).map(([fp, key]) => [(0, utils_2.fingerprintV1toV2)(fp), key]));
            for (const [fp, signature] of Object.entries((_a = exchangeData.delegatorSignature) !== null && _a !== void 0 ? _a : {})) {
                const verificationKey = keysByV2Fp[fp];
                if (verificationKey &&
                    (yield this.primitives.HMAC.verify(yield this.extractHmacFromRsaPrivate(verificationKey), delegatorSignatureData, (0, utils_1.ua2ab)((0, utils_1.b64_2ua)(signature)))))
                    return true;
            }
            return false;
        });
    }
    signDataWithSharedKey(rawData, key) {
        return __awaiter(this, void 0, void 0, function* () {
            return (0, utils_1.ua2b64)(yield this.primitives.HMAC.sign(key, new Uint8Array(rawData).buffer));
        });
    }
    verifyDataWithSharedKey(rawData, key, signature) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.primitives.HMAC.verify(key, new Uint8Array(rawData).buffer, (0, utils_1.ua2ab)((0, utils_1.b64_2ua)(signature)));
        });
    }
}
exports.BaseExchangeDataManager = BaseExchangeDataManager;
//# sourceMappingURL=BaseExchangeDataManager.js.map