diff options
author | RaindropsSys <raindrops@equestria.dev> | 2023-11-17 23:25:29 +0100 |
---|---|---|
committer | RaindropsSys <raindrops@equestria.dev> | 2023-11-17 23:25:29 +0100 |
commit | 953ddd82e48dd206cef5ac94456549aed13b3ad5 (patch) | |
tree | 8f003106ee2e7f422e5a22d2ee04d0db302e66c0 /includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/olmlib.js | |
parent | 62a9199846b0c07c03218703b33e8385764f42d9 (diff) | |
download | pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.gz pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.bz2 pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.zip |
Updated 30 files and deleted 2976 files (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/olmlib.js')
-rw-r--r-- | includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/olmlib.js | 467 |
1 files changed, 0 insertions, 467 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/olmlib.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/olmlib.js deleted file mode 100644 index 0b5b14c..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/olmlib.js +++ /dev/null @@ -1,467 +0,0 @@ -"use strict"; - -var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.OLM_ALGORITHM = exports.MEGOLM_BACKUP_ALGORITHM = exports.MEGOLM_ALGORITHM = void 0; -exports.decodeBase64 = decodeBase64; -exports.encodeBase64 = encodeBase64; -exports.encodeUnpaddedBase64 = encodeUnpaddedBase64; -exports.encryptMessageForDevice = encryptMessageForDevice; -exports.ensureOlmSessionsForDevices = ensureOlmSessionsForDevices; -exports.getExistingOlmSessions = getExistingOlmSessions; -exports.isOlmEncrypted = isOlmEncrypted; -exports.pkSign = pkSign; -exports.pkVerify = pkVerify; -exports.verifySignature = verifySignature; -var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); -var _anotherJson = _interopRequireDefault(require("another-json")); -var _logger = require("../logger"); -var _event = require("../@types/event"); -var _utils = require("../utils"); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } -var Algorithm; -/** - * matrix algorithm tag for olm - */ -(function (Algorithm) { - Algorithm["Olm"] = "m.olm.v1.curve25519-aes-sha2"; - Algorithm["Megolm"] = "m.megolm.v1.aes-sha2"; - Algorithm["MegolmBackup"] = "m.megolm_backup.v1.curve25519-aes-sha2"; -})(Algorithm || (Algorithm = {})); -const OLM_ALGORITHM = Algorithm.Olm; - -/** - * matrix algorithm tag for megolm - */ -exports.OLM_ALGORITHM = OLM_ALGORITHM; -const MEGOLM_ALGORITHM = Algorithm.Megolm; - -/** - * matrix algorithm tag for megolm backups - */ -exports.MEGOLM_ALGORITHM = MEGOLM_ALGORITHM; -const MEGOLM_BACKUP_ALGORITHM = Algorithm.MegolmBackup; -exports.MEGOLM_BACKUP_ALGORITHM = MEGOLM_BACKUP_ALGORITHM; -/** - * Encrypt an event payload for an Olm device - * - * @param resultsObject - The `ciphertext` property - * of the m.room.encrypted event to which to add our result - * - * @param olmDevice - olm.js wrapper - * @param payloadFields - fields to include in the encrypted payload - * - * Returns a promise which resolves (to undefined) when the payload - * has been encrypted into `resultsObject` - */ -async function encryptMessageForDevice(resultsObject, ourUserId, ourDeviceId, olmDevice, recipientUserId, recipientDevice, payloadFields) { - const deviceKey = recipientDevice.getIdentityKey(); - const sessionId = await olmDevice.getSessionIdForDevice(deviceKey); - if (sessionId === null) { - // If we don't have a session for a device then - // we can't encrypt a message for it. - _logger.logger.log(`[olmlib.encryptMessageForDevice] Unable to find Olm session for device ` + `${recipientUserId}:${recipientDevice.deviceId}`); - return; - } - _logger.logger.log(`[olmlib.encryptMessageForDevice] Using Olm session ${sessionId} for device ` + `${recipientUserId}:${recipientDevice.deviceId}`); - const payload = _objectSpread({ - sender: ourUserId, - // TODO this appears to no longer be used whatsoever - sender_device: ourDeviceId, - // Include the Ed25519 key so that the recipient knows what - // device this message came from. - // We don't need to include the curve25519 key since the - // recipient will already know this from the olm headers. - // When combined with the device keys retrieved from the - // homeserver signed by the ed25519 key this proves that - // the curve25519 key and the ed25519 key are owned by - // the same device. - keys: { - ed25519: olmDevice.deviceEd25519Key - }, - // include the recipient device details in the payload, - // to avoid unknown key attacks, per - // https://github.com/vector-im/vector-web/issues/2483 - recipient: recipientUserId, - recipient_keys: { - ed25519: recipientDevice.getFingerprint() - } - }, payloadFields); - - // TODO: technically, a bunch of that stuff only needs to be included for - // pre-key messages: after that, both sides know exactly which devices are - // involved in the session. If we're looking to reduce data transfer in the - // future, we could elide them for subsequent messages. - - resultsObject[deviceKey] = await olmDevice.encryptMessage(deviceKey, sessionId, JSON.stringify(payload)); -} -/** - * Get the existing olm sessions for the given devices, and the devices that - * don't have olm sessions. - * - * - * - * @param devicesByUser - map from userid to list of devices to ensure sessions for - * - * @returns resolves to an array. The first element of the array is a - * a map of user IDs to arrays of deviceInfo, representing the devices that - * don't have established olm sessions. The second element of the array is - * a map from userId to deviceId to {@link OlmSessionResult} - */ -async function getExistingOlmSessions(olmDevice, baseApis, devicesByUser) { - // map user Id → DeviceInfo[] - const devicesWithoutSession = new _utils.MapWithDefault(() => []); - // map user Id → device Id → IExistingOlmSession - const sessions = new _utils.MapWithDefault(() => new Map()); - const promises = []; - for (const [userId, devices] of Object.entries(devicesByUser)) { - for (const deviceInfo of devices) { - const deviceId = deviceInfo.deviceId; - const key = deviceInfo.getIdentityKey(); - promises.push((async () => { - const sessionId = await olmDevice.getSessionIdForDevice(key, true); - if (sessionId === null) { - devicesWithoutSession.getOrCreate(userId).push(deviceInfo); - } else { - sessions.getOrCreate(userId).set(deviceId, { - device: deviceInfo, - sessionId: sessionId - }); - } - })()); - } - } - await Promise.all(promises); - return [devicesWithoutSession, sessions]; -} - -/** - * Try to make sure we have established olm sessions for the given devices. - * - * @param devicesByUser - map from userid to list of devices to ensure sessions for - * - * @param force - If true, establish a new session even if one - * already exists. - * - * @param otkTimeout - The timeout in milliseconds when requesting - * one-time keys for establishing new olm sessions. - * - * @param failedServers - An array to fill with remote servers that - * failed to respond to one-time-key requests. - * - * @param log - A possibly customised log - * - * @returns resolves once the sessions are complete, to - * an Object mapping from userId to deviceId to - * {@link OlmSessionResult} - */ -async function ensureOlmSessionsForDevices(olmDevice, baseApis, devicesByUser, force = false, otkTimeout, failedServers, log = _logger.logger) { - const devicesWithoutSession = [ - // [userId, deviceId], ... - ]; - // map user Id → device Id → IExistingOlmSession - const result = new Map(); - // map device key → resolve session fn - const resolveSession = new Map(); - - // Mark all sessions this task intends to update as in progress. It is - // important to do this for all devices this task cares about in a single - // synchronous operation, as otherwise it is possible to have deadlocks - // where multiple tasks wait indefinitely on another task to update some set - // of common devices. - for (const devices of devicesByUser.values()) { - for (const deviceInfo of devices) { - const key = deviceInfo.getIdentityKey(); - if (key === olmDevice.deviceCurve25519Key) { - // We don't start sessions with ourself, so there's no need to - // mark it in progress. - continue; - } - if (!olmDevice.sessionsInProgress[key]) { - // pre-emptively mark the session as in-progress to avoid race - // conditions. If we find that we already have a session, then - // we'll resolve - olmDevice.sessionsInProgress[key] = new Promise(resolve => { - resolveSession.set(key, v => { - delete olmDevice.sessionsInProgress[key]; - resolve(v); - }); - }); - } - } - } - for (const [userId, devices] of devicesByUser) { - const resultDevices = new Map(); - result.set(userId, resultDevices); - for (const deviceInfo of devices) { - const deviceId = deviceInfo.deviceId; - const key = deviceInfo.getIdentityKey(); - if (key === olmDevice.deviceCurve25519Key) { - // We should never be trying to start a session with ourself. - // Apart from talking to yourself being the first sign of madness, - // olm sessions can't do this because they get confused when - // they get a message and see that the 'other side' has started a - // new chain when this side has an active sender chain. - // If you see this message being logged in the wild, we should find - // the thing that is trying to send Olm messages to itself and fix it. - log.info("Attempted to start session with ourself! Ignoring"); - // We must fill in the section in the return value though, as callers - // expect it to be there. - resultDevices.set(deviceId, { - device: deviceInfo, - sessionId: null - }); - continue; - } - const forWhom = `for ${key} (${userId}:${deviceId})`; - const sessionId = await olmDevice.getSessionIdForDevice(key, !!resolveSession.get(key), log); - const resolveSessionFn = resolveSession.get(key); - if (sessionId !== null && resolveSessionFn) { - // we found a session, but we had marked the session as - // in-progress, so resolve it now, which will unmark it and - // unblock anything that was waiting - resolveSessionFn(); - } - if (sessionId === null || force) { - if (force) { - log.info(`Forcing new Olm session ${forWhom}`); - } else { - log.info(`Making new Olm session ${forWhom}`); - } - devicesWithoutSession.push([userId, deviceId]); - } - resultDevices.set(deviceId, { - device: deviceInfo, - sessionId: sessionId - }); - } - } - if (devicesWithoutSession.length === 0) { - return result; - } - const oneTimeKeyAlgorithm = "signed_curve25519"; - let res; - let taskDetail = `one-time keys for ${devicesWithoutSession.length} devices`; - try { - log.debug(`Claiming ${taskDetail}`); - res = await baseApis.claimOneTimeKeys(devicesWithoutSession, oneTimeKeyAlgorithm, otkTimeout); - log.debug(`Claimed ${taskDetail}`); - } catch (e) { - for (const resolver of resolveSession.values()) { - resolver(); - } - log.log(`Failed to claim ${taskDetail}`, e, devicesWithoutSession); - throw e; - } - if (failedServers && "failures" in res) { - failedServers.push(...Object.keys(res.failures)); - } - const otkResult = res.one_time_keys || {}; - const promises = []; - for (const [userId, devices] of devicesByUser) { - const userRes = otkResult[userId] || {}; - for (const deviceInfo of devices) { - var _result$get, _result$get$get; - const deviceId = deviceInfo.deviceId; - const key = deviceInfo.getIdentityKey(); - if (key === olmDevice.deviceCurve25519Key) { - // We've already logged about this above. Skip here too - // otherwise we'll log saying there are no one-time keys - // which will be confusing. - continue; - } - if ((_result$get = result.get(userId)) !== null && _result$get !== void 0 && (_result$get$get = _result$get.get(deviceId)) !== null && _result$get$get !== void 0 && _result$get$get.sessionId && !force) { - // we already have a result for this device - continue; - } - const deviceRes = userRes[deviceId] || {}; - let oneTimeKey = null; - for (const keyId in deviceRes) { - if (keyId.indexOf(oneTimeKeyAlgorithm + ":") === 0) { - oneTimeKey = deviceRes[keyId]; - } - } - if (!oneTimeKey) { - var _resolveSession$get; - log.warn(`No one-time keys (alg=${oneTimeKeyAlgorithm}) ` + `for device ${userId}:${deviceId}`); - (_resolveSession$get = resolveSession.get(key)) === null || _resolveSession$get === void 0 ? void 0 : _resolveSession$get(); - continue; - } - promises.push(_verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo).then(sid => { - var _resolveSession$get2, _result$get2; - (_resolveSession$get2 = resolveSession.get(key)) === null || _resolveSession$get2 === void 0 ? void 0 : _resolveSession$get2(sid !== null && sid !== void 0 ? sid : undefined); - const deviceInfo = (_result$get2 = result.get(userId)) === null || _result$get2 === void 0 ? void 0 : _result$get2.get(deviceId); - if (deviceInfo) deviceInfo.sessionId = sid; - }, e => { - var _resolveSession$get3; - (_resolveSession$get3 = resolveSession.get(key)) === null || _resolveSession$get3 === void 0 ? void 0 : _resolveSession$get3(); - throw e; - })); - } - } - taskDetail = `Olm sessions for ${promises.length} devices`; - log.debug(`Starting ${taskDetail}`); - await Promise.all(promises); - log.debug(`Started ${taskDetail}`); - return result; -} -async function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) { - const deviceId = deviceInfo.deviceId; - try { - await verifySignature(olmDevice, oneTimeKey, userId, deviceId, deviceInfo.getFingerprint()); - } catch (e) { - _logger.logger.error("Unable to verify signature on one-time key for device " + userId + ":" + deviceId + ":", e); - return null; - } - let sid; - try { - sid = await olmDevice.createOutboundSession(deviceInfo.getIdentityKey(), oneTimeKey.key); - } catch (e) { - // possibly a bad key - _logger.logger.error("Error starting olm session with device " + userId + ":" + deviceId + ": " + e); - return null; - } - _logger.logger.log("Started new olm sessionid " + sid + " for device " + userId + ":" + deviceId); - return sid; -} -/** - * Verify the signature on an object - * - * @param olmDevice - olm wrapper to use for verify op - * - * @param obj - object to check signature on. - * - * @param signingUserId - ID of the user whose signature should be checked - * - * @param signingDeviceId - ID of the device whose signature should be checked - * - * @param signingKey - base64-ed ed25519 public key - * - * Returns a promise which resolves (to undefined) if the the signature is good, - * or rejects with an Error if it is bad. - */ -async function verifySignature(olmDevice, obj, signingUserId, signingDeviceId, signingKey) { - const signKeyId = "ed25519:" + signingDeviceId; - const signatures = obj.signatures || {}; - const userSigs = signatures[signingUserId] || {}; - const signature = userSigs[signKeyId]; - if (!signature) { - throw Error("No signature"); - } - - // prepare the canonical json: remove unsigned and signatures, and stringify with anotherjson - const mangledObj = Object.assign({}, obj); - if ("unsigned" in mangledObj) { - delete mangledObj.unsigned; - } - delete mangledObj.signatures; - const json = _anotherJson.default.stringify(mangledObj); - olmDevice.verifySignature(signingKey, json, signature); -} - -/** - * Sign a JSON object using public key cryptography - * @param obj - Object to sign. The object will be modified to include - * the new signature - * @param key - the signing object or the private key - * seed - * @param userId - The user ID who owns the signing key - * @param pubKey - The public key (ignored if key is a seed) - * @returns the signature for the object - */ -function pkSign(obj, key, userId, pubKey) { - let createdKey = false; - if (key instanceof Uint8Array) { - const keyObj = new global.Olm.PkSigning(); - pubKey = keyObj.init_with_seed(key); - key = keyObj; - createdKey = true; - } - const sigs = obj.signatures || {}; - delete obj.signatures; - const unsigned = obj.unsigned; - if (obj.unsigned) delete obj.unsigned; - try { - const mysigs = sigs[userId] || {}; - sigs[userId] = mysigs; - return mysigs["ed25519:" + pubKey] = key.sign(_anotherJson.default.stringify(obj)); - } finally { - obj.signatures = sigs; - if (unsigned) obj.unsigned = unsigned; - if (createdKey) { - key.free(); - } - } -} - -/** - * Verify a signed JSON object - * @param obj - Object to verify - * @param pubKey - The public key to use to verify - * @param userId - The user ID who signed the object - */ -function pkVerify(obj, pubKey, userId) { - const keyId = "ed25519:" + pubKey; - if (!(obj.signatures && obj.signatures[userId] && obj.signatures[userId][keyId])) { - throw new Error("No signature"); - } - const signature = obj.signatures[userId][keyId]; - const util = new global.Olm.Utility(); - const sigs = obj.signatures; - delete obj.signatures; - const unsigned = obj.unsigned; - if (obj.unsigned) delete obj.unsigned; - try { - util.ed25519_verify(pubKey, _anotherJson.default.stringify(obj), signature); - } finally { - obj.signatures = sigs; - if (unsigned) obj.unsigned = unsigned; - util.free(); - } -} - -/** - * Check that an event was encrypted using olm. - */ -function isOlmEncrypted(event) { - if (!event.getSenderKey()) { - _logger.logger.error("Event has no sender key (not encrypted?)"); - return false; - } - if (event.getWireType() !== _event.EventType.RoomMessageEncrypted || !["m.olm.v1.curve25519-aes-sha2"].includes(event.getWireContent().algorithm)) { - _logger.logger.error("Event was not encrypted using an appropriate algorithm"); - return false; - } - return true; -} - -/** - * Encode a typed array of uint8 as base64. - * @param uint8Array - The data to encode. - * @returns The base64. - */ -function encodeBase64(uint8Array) { - return Buffer.from(uint8Array).toString("base64"); -} - -/** - * Encode a typed array of uint8 as unpadded base64. - * @param uint8Array - The data to encode. - * @returns The unpadded base64. - */ -function encodeUnpaddedBase64(uint8Array) { - return encodeBase64(uint8Array).replace(/=+$/g, ""); -} - -/** - * Decode a base64 string to a typed array of uint8. - * @param base64 - The base64 to decode. - * @returns The decoded data. - */ -function decodeBase64(base64) { - return Buffer.from(base64, "base64"); -} -//# sourceMappingURL=olmlib.js.map
\ No newline at end of file |