UNPKG

open-collaboration-protocol

Version:

Open Collaboration Protocol implementation, part of the Open Collaboration Tools project

103 lines 4.38 kB
// ****************************************************************************** // Copyright 2024 TypeFox GmbH // This program and the accompanying materials are made available under the // terms of the MIT License, which is available in the project root. // ****************************************************************************** import { Encoding } from './encoding.js'; import { Compression } from './compression.js'; import { getCryptoLib } from '../utils/crypto.js'; import { fromBase64, toBase64 } from '../utils/base64.js'; export var Encryption; (function (Encryption) { async function generateKeyPair() { return getCryptoLib().generateKeyPair(); } Encryption.generateKeyPair = generateKeyPair; async function generateSymKey() { return getCryptoLib().generateSymKey(); } Encryption.generateSymKey = generateSymKey; async function symEncrypt(data, key, iv) { return getCryptoLib().symEncrypt(data, key, iv); } Encryption.symEncrypt = symEncrypt; async function symDecrypt(data, key, iv) { return getCryptoLib().symDecrypt(data, key, iv); } Encryption.symDecrypt = symDecrypt; async function publicEncrypt(data, key) { return getCryptoLib().publicEncrypt(data, key); } Encryption.publicEncrypt = publicEncrypt; async function privateDecrypt(data, key) { return getCryptoLib().privateDecrypt(data, key); } Encryption.privateDecrypt = privateDecrypt; async function generateIV() { return getCryptoLib().generateIV(); } Encryption.generateIV = generateIV; async function encrypt(message, symKey, ...keys) { const key = await symKey.symmetricKey; const keyBuffer = fromBase64(key); const content = message.content; const encoded = Encoding.encode(content); const compressionAlgo = Compression.bestFit(keys.map(key => key.supportedCompression)); const compressed = await Compression.compress(encoded, compressionAlgo); const iv = await getCryptoLib().generateIV(); const encrypted = await getCryptoLib().symEncrypt(compressed, key, iv); const encryptedKeys = await Promise.all(keys.map(async (key) => { let cachedKey = symKey.cache?.[key.peerId]; if (!cachedKey) { cachedKey = toBase64(await getCryptoLib().publicEncrypt(keyBuffer, key.publicKey)); if (symKey.cache) { symKey.cache[key.peerId] = cachedKey; } } return { target: key.peerId, key: cachedKey, iv }; })); return { ...message, metadata: { ...message.metadata, encryption: { keys: encryptedKeys }, compression: { algorithm: compressionAlgo } }, content: encrypted }; } Encryption.encrypt = encrypt; async function decrypt(message, privateKey) { // We always expect exactly one key for every message we receive // This is obviously the case for any 1:1 message such as requests or notifications. // However, even for broadcasts, the server will modify the message to only contain the key for the target peer. if (message.metadata.encryption.keys.length !== 1) { throw new Error('Expected exactly one key for decryption'); } const key = message.metadata.encryption.keys[0]; let decryptedKey = privateKey.cache?.[key.key]; if (!decryptedKey) { decryptedKey = toBase64(await getCryptoLib().privateDecrypt(fromBase64(key.key), privateKey.privateKey)); if (privateKey.cache) { privateKey.cache[key.key] = decryptedKey; } } const decrypted = await getCryptoLib().symDecrypt(message.content, decryptedKey, key.iv); const decompressed = await Compression.decompress(decrypted, message.metadata.compression.algorithm); const decoded = Encoding.decode(decompressed); return { ...message, content: decoded }; } Encryption.decrypt = decrypt; })(Encryption || (Encryption = {})); //# sourceMappingURL=encryption.js.map