UNPKG

ic-websocket-js

Version:
95 lines 3.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.randomBigInt = exports.safeExecute = exports.isMessageBodyValid = void 0; const agent_1 = require("@dfinity/agent"); const logger_1 = require("./logger"); const areBuffersEqual = (buf1, buf2) => { return (0, agent_1.compare)(buf1, buf2) === 0; }; const isMessageBodyValid = async (canisterId, path, body, certificate, tree, agent, maxCertificateAgeInMinutes) => { let cert; try { cert = await agent_1.Certificate.create({ certificate, canisterId, rootKey: agent.rootKey, maxAgeInMinutes: maxCertificateAgeInMinutes, }); } catch (error) { logger_1.logger.error("[certification] Error creating certificate:", error); return false; } const hashTree = agent_1.Cbor.decode(tree); const reconstructed = await (0, agent_1.reconstruct)(hashTree); const witnessLookupResult = cert.lookup([ "canister", canisterId.toUint8Array(), "certified_data" ]); const witness = (0, agent_1.lookupResultToBuffer)(witnessLookupResult); if (!witness) { throw new Error("Could not find certified data for this canister in the certificate."); } // First validate that the Tree is as good as the certification. if (!areBuffersEqual(witness, reconstructed)) { logger_1.logger.error("[certification] Witness != Tree passed in ic-certification"); return false; } // Next, calculate the SHA of the content. const sha = await crypto.subtle.digest("SHA-256", body); let treeShaLookupResult = (0, agent_1.lookup_path)(["websocket", path], hashTree); let treeSha = (0, agent_1.lookupResultToBuffer)(treeShaLookupResult); if (!treeSha) { // Allow fallback to index path. treeShaLookupResult = (0, agent_1.lookup_path)(["websocket"], hashTree); treeSha = (0, agent_1.lookupResultToBuffer)(treeShaLookupResult); } if (!treeSha) { // The tree returned in the certification header is wrong. Return false. // We don't throw here, just invalidate the request. logger_1.logger.error(`[certification] Invalid Tree in the header. Does not contain path ${JSON.stringify(path)}`); return false; } return !!treeSha && areBuffersEqual(sha, treeSha); }; exports.isMessageBodyValid = isMessageBodyValid; const safeExecute = async (fn, warnMessage) => { try { return await Promise.resolve(fn()); } catch (error) { logger_1.logger.warn(warnMessage, error); } }; exports.safeExecute = safeExecute; /** * Generates a random unsigned 64-bit integer * @returns {bigint} a random bigint */ const randomBigInt = () => { // determine whether browser crypto is available if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) { const array = new BigUint64Array(1); window.crypto.getRandomValues(array); return array[0]; } // A second check for webcrypto, in case it is loaded under global instead of window if (typeof crypto !== 'undefined' && crypto.getRandomValues) { const array = new BigUint64Array(1); crypto.getRandomValues(array); return array[0]; } // determine whether node crypto is available // @ts-ignore if (typeof crypto !== 'undefined' && crypto.randomBytes) { // @ts-ignore const randomBuffer = crypto.randomBytes(8); const randomHexString = randomBuffer.toString('hex'); return BigInt('0x' + randomHexString); } // TODO: test these fallbacks in a node environment throw new Error('Random UInt64 generation not supported in this environment'); }; exports.randomBigInt = randomBigInt; //# sourceMappingURL=utils.js.map