diff --git a/package-lock.json b/package-lock.json index cd5cc79c0..8a7afd66e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "telegram_react", - "version": "0.0.963", + "version": "0.0.992", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4425,6 +4425,11 @@ "randomfill": "^1.0.3" } }, + "crypto-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", + "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" + }, "crypto-random-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", diff --git a/package.json b/package.json index c722c3856..fa4a31a81 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { "homepage": "https://evgeny-nadymov.github.io/telegram-react", "name": "telegram_react", - "version": "0.0.991", + "version": "0.0.992", "private": true, "dependencies": { - "tdweb": "^1.7.2", "@material-ui/core": "^4.9.7", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.46", "classnames": "^2.2.6", + "crypto-js": "^4.0.0", "emoji-mart": "^3.0.0", "emoji-regex": "^8.0.0", "i18next": "^19.3.3", @@ -22,7 +22,8 @@ "react-i18next": "^11.3.4", "react-router-dom": "^5.0.0", "react-scripts": "^3.1.1", - "react-transition-group": "^4.3.0" + "react-transition-group": "^4.3.0", + "tdweb": "^1.7.2" }, "lint-staged": { "src/**/*.{js,jsx,json,css}": [ diff --git a/src/Calls/P2P/P2PEncryptor.js b/src/Calls/P2P/P2PEncryptor.js new file mode 100644 index 000000000..a9c4e0719 --- /dev/null +++ b/src/Calls/P2P/P2PEncryptor.js @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018-present, Evgeny Nadymov + * + * This source code is licensed under the GPL v.3.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CryptoJS from 'crypto-js'; + +const MTPROTO_ENCRYPTION = false; + +export default class P2PEncryptor { + constructor(key) { + const p2pKey = CryptoJS.enc.Base64.parse(key); + + this.key = CryptoJS.enc.Hex.parse('3132333435363738393031323334353641424344454647484940414243444546'); + this.iv = CryptoJS.enc.Hex.parse('0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f'); + this.mode = CryptoJS.mode.CTR; + this.padding = CryptoJS.pad.NoPadding; + } + + encryptToBase64(str) { + if (MTPROTO_ENCRYPTION) { + const { key, iv, mode, padding } = this; + + const encrypted = CryptoJS.AES.encrypt(str, key, { + mode, + iv, + padding + }); + + return encrypted.toString(); + } else { + return btoa(str); + } + } + + decryptFromBase64(base64) { + if (MTPROTO_ENCRYPTION) { + const { key, iv, mode, padding } = this; + + const decrypted = CryptoJS.AES.decrypt(base64, key, { + mode, + iv, + padding + }); + + return decrypted.toString(CryptoJS.enc.Utf8); + } else { + return atob(base64); + } + } +}; \ No newline at end of file diff --git a/src/Stores/CallStore.js b/src/Stores/CallStore.js index 018ad75c0..9cdb7ab88 100644 --- a/src/Stores/CallStore.js +++ b/src/Stores/CallStore.js @@ -19,6 +19,7 @@ import AppStore from './ApplicationStore'; import LStore from './LocalizationStore'; import UserStore from './UserStore'; import TdLibController from '../Controllers/TdLibController'; +import P2PEncryptor from '../Calls/P2P/P2PEncryptor'; const JOIN_TRACKS = true; const UNIFY_SDP = true; @@ -243,10 +244,18 @@ class CallStore extends EventEmitter { const { call_id, data } = update; try { - const signalingData = JSON.parse(atob(data)); - LOG_P2P_CALL('[update] updateNewCallSignalingData', update, signalingData); - if (this.p2pCallsEnabled) { - this.p2pApplyCallSignalingData(call_id, signalingData); + const { currentCall } = this; + if (currentCall) { + const { encryptor } = currentCall; + if (encryptor) { + const decryptedData = encryptor.decryptFromBase64(data); + const signalingData = JSON.parse(decryptedData); + // const signalingData = JSON.parse(atob(data)); + LOG_P2P_CALL('[update] updateNewCallSignalingData', update, signalingData); + if (this.p2pCallsEnabled) { + this.p2pApplyCallSignalingData(call_id, signalingData); + } + } } } catch (e) { ERROR_P2P_CALL('[update] updateNewSignalingData parse', update); @@ -1643,13 +1652,21 @@ class CallStore extends EventEmitter { }); } - p2pSendCallSignalingData(callId, data) { - LOG_P2P_CALL('[tdlib] sendCallSignalingData', callId, data); - TdLibController.send({ - '@type': 'sendCallSignalingData', - call_id: callId, - data: btoa(data) - }); + p2pSendCallSignalingData(callId, str) { + LOG_P2P_CALL('[tdlib] sendCallSignalingData', callId, str); + const { currentCall } = this; + if (currentCall) { + const { encryptor } = currentCall; + if (encryptor) { + const data = encryptor.encryptToBase64(str); + + TdLibController.send({ + '@type': 'sendCallSignalingData', + call_id: callId, + data + }); + } + } } p2pGetConfiguration(state){ @@ -1741,6 +1758,8 @@ class CallStore extends EventEmitter { if (!state) return; if (state['@type'] !== 'callStateReady') return; + const { encryption_key } = state; + const outputStream = new MediaStream(); const configuration = this.p2pGetConfiguration(state); @@ -1783,7 +1802,8 @@ class CallStore extends EventEmitter { callId: id, connection, inputStream: null, - outputStream + outputStream, + encryptor: new P2PEncryptor(encryption_key) }; LOG_P2P_CALL('p2pJoinCall currentCall', this.currentCall);