diff options
author | RaindropsSys <contact@minteck.org> | 2023-04-24 14:03:36 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-04-24 14:03:36 +0200 |
commit | 633c92eae865e957121e08de634aeee11a8b3992 (patch) | |
tree | 09d881bee1dae0b6eee49db1dfaf0f500240606c /includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/dehydration.js | |
parent | c4657e4509733699c0f26a3c900bab47e915d5a0 (diff) | |
download | pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.tar.gz pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.tar.bz2 pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.zip |
Updated 18 files, added 1692 files and deleted includes/system/compare.inc (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/dehydration.js')
-rw-r--r-- | includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/dehydration.js | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/dehydration.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/dehydration.js new file mode 100644 index 0000000..2a00aa7 --- /dev/null +++ b/includes/external/matrix/node_modules/matrix-js-sdk/lib/crypto/dehydration.js @@ -0,0 +1,238 @@ +"use strict"; + +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DehydrationManager = exports.DEHYDRATION_ALGORITHM = void 0; +var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); +var _anotherJson = _interopRequireDefault(require("another-json")); +var _olmlib = require("./olmlib"); +var _indexeddbCryptoStore = require("../crypto/store/indexeddb-crypto-store"); +var _aes = require("./aes"); +var _logger = require("../logger"); +var _httpApi = require("../http-api"); +/* +Copyright 2020-2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +const DEHYDRATION_ALGORITHM = "org.matrix.msc2697.v1.olm.libolm_pickle"; +exports.DEHYDRATION_ALGORITHM = DEHYDRATION_ALGORITHM; +const oneweek = 7 * 24 * 60 * 60 * 1000; +class DehydrationManager { + constructor(crypto) { + this.crypto = crypto; + (0, _defineProperty2.default)(this, "inProgress", false); + (0, _defineProperty2.default)(this, "timeoutId", void 0); + (0, _defineProperty2.default)(this, "key", void 0); + (0, _defineProperty2.default)(this, "keyInfo", void 0); + (0, _defineProperty2.default)(this, "deviceDisplayName", void 0); + this.getDehydrationKeyFromCache(); + } + getDehydrationKeyFromCache() { + return this.crypto.cryptoStore.doTxn("readonly", [_indexeddbCryptoStore.IndexedDBCryptoStore.STORE_ACCOUNT], txn => { + this.crypto.cryptoStore.getSecretStorePrivateKey(txn, async result => { + if (result) { + const { + key, + keyInfo, + deviceDisplayName, + time + } = result; + const pickleKey = Buffer.from(this.crypto.olmDevice.pickleKey); + const decrypted = await (0, _aes.decryptAES)(key, pickleKey, DEHYDRATION_ALGORITHM); + this.key = (0, _olmlib.decodeBase64)(decrypted); + this.keyInfo = keyInfo; + this.deviceDisplayName = deviceDisplayName; + const now = Date.now(); + const delay = Math.max(1, time + oneweek - now); + this.timeoutId = global.setTimeout(this.dehydrateDevice.bind(this), delay); + } + }, "dehydration"); + }); + } + + /** set the key, and queue periodic dehydration to the server in the background */ + async setKeyAndQueueDehydration(key, keyInfo = {}, deviceDisplayName) { + const matches = await this.setKey(key, keyInfo, deviceDisplayName); + if (!matches) { + // start dehydration in the background + this.dehydrateDevice(); + } + } + async setKey(key, keyInfo = {}, deviceDisplayName) { + if (!key) { + // unsetting the key -- cancel any pending dehydration task + if (this.timeoutId) { + global.clearTimeout(this.timeoutId); + this.timeoutId = undefined; + } + // clear storage + await this.crypto.cryptoStore.doTxn("readwrite", [_indexeddbCryptoStore.IndexedDBCryptoStore.STORE_ACCOUNT], txn => { + this.crypto.cryptoStore.storeSecretStorePrivateKey(txn, "dehydration", null); + }); + this.key = undefined; + this.keyInfo = undefined; + return; + } + + // Check to see if it's the same key as before. If it's different, + // dehydrate a new device. If it's the same, we can keep the same + // device. (Assume that keyInfo and deviceDisplayName will be the + // same if the key is the same.) + let matches = !!this.key && key.length == this.key.length; + for (let i = 0; matches && i < key.length; i++) { + if (key[i] != this.key[i]) { + matches = false; + } + } + if (!matches) { + this.key = key; + this.keyInfo = keyInfo; + this.deviceDisplayName = deviceDisplayName; + } + return matches; + } + + /** returns the device id of the newly created dehydrated device */ + async dehydrateDevice() { + if (this.inProgress) { + _logger.logger.log("Dehydration already in progress -- not starting new dehydration"); + return; + } + this.inProgress = true; + if (this.timeoutId) { + global.clearTimeout(this.timeoutId); + this.timeoutId = undefined; + } + try { + const pickleKey = Buffer.from(this.crypto.olmDevice.pickleKey); + + // update the crypto store with the timestamp + const key = await (0, _aes.encryptAES)((0, _olmlib.encodeBase64)(this.key), pickleKey, DEHYDRATION_ALGORITHM); + await this.crypto.cryptoStore.doTxn("readwrite", [_indexeddbCryptoStore.IndexedDBCryptoStore.STORE_ACCOUNT], txn => { + this.crypto.cryptoStore.storeSecretStorePrivateKey(txn, "dehydration", { + keyInfo: this.keyInfo, + key, + deviceDisplayName: this.deviceDisplayName, + time: Date.now() + }); + }); + _logger.logger.log("Attempting to dehydrate device"); + _logger.logger.log("Creating account"); + // create the account and all the necessary keys + const account = new global.Olm.Account(); + account.create(); + const e2eKeys = JSON.parse(account.identity_keys()); + const maxKeys = account.max_number_of_one_time_keys(); + // FIXME: generate in small batches? + account.generate_one_time_keys(maxKeys / 2); + account.generate_fallback_key(); + const otks = JSON.parse(account.one_time_keys()); + const fallbacks = JSON.parse(account.fallback_key()); + account.mark_keys_as_published(); + + // dehydrate the account and store it on the server + const pickledAccount = account.pickle(new Uint8Array(this.key)); + const deviceData = { + algorithm: DEHYDRATION_ALGORITHM, + account: pickledAccount + }; + if (this.keyInfo.passphrase) { + deviceData.passphrase = this.keyInfo.passphrase; + } + _logger.logger.log("Uploading account to server"); + // eslint-disable-next-line camelcase + const dehydrateResult = await this.crypto.baseApis.http.authedRequest(_httpApi.Method.Put, "/dehydrated_device", undefined, { + device_data: deviceData, + initial_device_display_name: this.deviceDisplayName + }, { + prefix: "/_matrix/client/unstable/org.matrix.msc2697.v2" + }); + + // send the keys to the server + const deviceId = dehydrateResult.device_id; + _logger.logger.log("Preparing device keys", deviceId); + const deviceKeys = { + algorithms: this.crypto.supportedAlgorithms, + device_id: deviceId, + user_id: this.crypto.userId, + keys: { + [`ed25519:${deviceId}`]: e2eKeys.ed25519, + [`curve25519:${deviceId}`]: e2eKeys.curve25519 + } + }; + const deviceSignature = account.sign(_anotherJson.default.stringify(deviceKeys)); + deviceKeys.signatures = { + [this.crypto.userId]: { + [`ed25519:${deviceId}`]: deviceSignature + } + }; + if (this.crypto.crossSigningInfo.getId("self_signing")) { + await this.crypto.crossSigningInfo.signObject(deviceKeys, "self_signing"); + } + _logger.logger.log("Preparing one-time keys"); + const oneTimeKeys = {}; + for (const [keyId, key] of Object.entries(otks.curve25519)) { + const k = { + key + }; + const signature = account.sign(_anotherJson.default.stringify(k)); + k.signatures = { + [this.crypto.userId]: { + [`ed25519:${deviceId}`]: signature + } + }; + oneTimeKeys[`signed_curve25519:${keyId}`] = k; + } + _logger.logger.log("Preparing fallback keys"); + const fallbackKeys = {}; + for (const [keyId, key] of Object.entries(fallbacks.curve25519)) { + const k = { + key, + fallback: true + }; + const signature = account.sign(_anotherJson.default.stringify(k)); + k.signatures = { + [this.crypto.userId]: { + [`ed25519:${deviceId}`]: signature + } + }; + fallbackKeys[`signed_curve25519:${keyId}`] = k; + } + _logger.logger.log("Uploading keys to server"); + await this.crypto.baseApis.http.authedRequest(_httpApi.Method.Post, "/keys/upload/" + encodeURI(deviceId), undefined, { + "device_keys": deviceKeys, + "one_time_keys": oneTimeKeys, + "org.matrix.msc2732.fallback_keys": fallbackKeys + }); + _logger.logger.log("Done dehydrating"); + + // dehydrate again in a week + this.timeoutId = global.setTimeout(this.dehydrateDevice.bind(this), oneweek); + return deviceId; + } finally { + this.inProgress = false; + } + } + stop() { + if (this.timeoutId) { + global.clearTimeout(this.timeoutId); + this.timeoutId = undefined; + } + } +} +exports.DehydrationManager = DehydrationManager; +//# sourceMappingURL=dehydration.js.map
\ No newline at end of file |