UNPKG

@jsxc/jsxc

Version:

Real-time XMPP chat application with video calls, file transfer and encrypted communication

65 lines (49 loc) 2.1 kB
import Address from '../vendor/Address'; import Store from './Store'; import BundleManager from './BundleManager'; import EncryptedDeviceMessage from '../model/EncryptedDeviceMessage'; import { SessionCipher } from '../vendor/SessionCipher'; import { SessionBuilder } from '../vendor/SessionBuilder'; import Bundle from './Bundle'; import Log from '@util/Log'; export default class Session { private sessionCipher; constructor(private address: Address, private store: Store, private bundleManager: BundleManager) {} public async decrypt(ciphertext, preKey: boolean = false): Promise<ArrayBuffer> { let sessionCipher = this.getSessionCipher(); let plaintextBuffer; if (preKey) { plaintextBuffer = await sessionCipher.decryptPreKeyMessage(ciphertext); } else { plaintextBuffer = await sessionCipher.decryptMessage(ciphertext); } return plaintextBuffer; } public async encrypt(plaintext): Promise<EncryptedDeviceMessage | null> { try { if (!this.store.hasSession(this.address.toString())) { await this.establishSession(); } let session = this.getSessionCipher(); let ciphertext = await session.encryptMessage(plaintext); return new EncryptedDeviceMessage(this.address, ciphertext); } catch (err) { Log.warn('Could not encrypt data for device with id ' + this.address.getDeviceId(), err); return null; // Otherwise Promise.all throws an error } } private async establishSession() { let bundle = await this.bundleManager.requestBundle(this.address); await this.processPreKeyMessage(bundle); } private processPreKeyMessage = (bundle: Bundle): Promise<void> => { let builder = new SessionBuilder(this.address, this.store); return builder.processPreKey(bundle).then(() => undefined); }; private getSessionCipher(): SessionCipher { if (!this.sessionCipher) { this.sessionCipher = new SessionCipher(this.address, this.store); } return this.sessionCipher; } }