Browse Source

Fix computing call fingerprint

master
Eduard Kuzmenko 2 years ago
parent
commit
0c9a3b8548
  1. 3
      src/components/call/index.ts
  2. 5
      src/helpers/bigInt/bigIntConstants.ts
  3. 9
      src/helpers/bigInt/bigIntConversion.ts
  4. 3
      src/lib/calls/callsController.ts
  5. 6
      src/lib/crypto/computeDhKey.ts
  6. 16
      src/lib/mtproto/tl_utils.ts
  7. 1
      src/scss/partials/popups/_call.scss

3
src/components/call/index.ts

@ -10,6 +10,7 @@ import { attachClickEvent } from "../../helpers/dom/clickEvent";
import ControlsHover from "../../helpers/dom/controlsHover"; import ControlsHover from "../../helpers/dom/controlsHover";
import findUpClassName from "../../helpers/dom/findUpClassName"; import findUpClassName from "../../helpers/dom/findUpClassName";
import { addFullScreenListener, cancelFullScreen, isFullScreen, requestFullScreen } from "../../helpers/dom/fullScreen"; import { addFullScreenListener, cancelFullScreen, isFullScreen, requestFullScreen } from "../../helpers/dom/fullScreen";
import replaceContent from "../../helpers/dom/replaceContent";
import MovablePanel from "../../helpers/movablePanel"; import MovablePanel from "../../helpers/movablePanel";
import onMediaLoad from "../../helpers/onMediaLoad"; import onMediaLoad from "../../helpers/onMediaLoad";
import themeController from "../../helpers/themeController"; import themeController from "../../helpers/themeController";
@ -441,7 +442,7 @@ export default class PopupCall extends PopupElement {
if(!this.emojisSubtitle.textContent && connectionState < CALL_STATE.EXCHANGING_KEYS) { if(!this.emojisSubtitle.textContent && connectionState < CALL_STATE.EXCHANGING_KEYS) {
Promise.resolve(instance.getEmojisFingerprint()).then((emojis) => { Promise.resolve(instance.getEmojisFingerprint()).then((emojis) => {
this.emojisSubtitle.append(wrapEmojiText(emojis.join(''))); replaceContent(this.emojisSubtitle, wrapEmojiText(emojis.join('')));
}); });
} }

5
src/helpers/bigInt/bigIntConstants.ts

@ -0,0 +1,5 @@
import bigInt from 'big-integer';
export const safeBigInt = bigInt(Number.MAX_SAFE_INTEGER);
export const ulongBigInt = bigInt(bigInt[2]).pow(64);
export const longBigInt = ulongBigInt.divide(bigInt[2]);

9
src/helpers/bigInt/bigIntConversion.ts

@ -1,4 +1,5 @@
import bigInt from 'big-integer'; import bigInt from 'big-integer';
import { longBigInt, ulongBigInt } from './bigIntConstants';
export function bigIntFromBytes(bytes: Uint8Array | number[], base = 256) { export function bigIntFromBytes(bytes: Uint8Array | number[], base = 256) {
return bigInt.fromArray(bytes instanceof Uint8Array ? [...bytes] : bytes, base); return bigInt.fromArray(bytes instanceof Uint8Array ? [...bytes] : bytes, base);
@ -7,3 +8,11 @@ export function bigIntFromBytes(bytes: Uint8Array | number[], base = 256) {
export function bigIntToBytes(bigInt: bigInt.BigInteger) { export function bigIntToBytes(bigInt: bigInt.BigInteger) {
return new Uint8Array(bigInt.toArray(256).value); return new Uint8Array(bigInt.toArray(256).value);
} }
export function bigIntToSigned(bigInt: bigInt.BigInteger) {
return bigInt.greater(longBigInt) ? bigInt.minus(ulongBigInt) : bigInt;
}
export function bigIntToUnsigned(bigInt: bigInt.BigInteger) {
return bigInt.isNegative() ? ulongBigInt.add(bigInt) : bigInt;
}

3
src/lib/calls/callsController.ts

@ -115,7 +115,8 @@ export class CallsController extends EventListenerBase<{
const {key, key_fingerprint} = await this.managers.appCallsManager.computeKey(g_a, dh.b, dh.p); const {key, key_fingerprint} = await this.managers.appCallsManager.computeKey(g_a, dh.b, dh.p);
if(call.key_fingerprint !== key_fingerprint) { if(call.key_fingerprint !== key_fingerprint) {
this.log.error('Incorrect key fingerprint', call.key_fingerprint, key_fingerprint); this.log.error('Incorrect key fingerprint', call.key_fingerprint, key_fingerprint, g_a, dh);
instance.hangUp('phoneCallDiscardReasonDisconnect');
break; break;
} }

6
src/lib/crypto/computeDhKey.ts

@ -4,14 +4,14 @@
* https://github.com/morethanwords/tweb/blob/master/LICENSE * https://github.com/morethanwords/tweb/blob/master/LICENSE
*/ */
import { bigIntFromBytes } from "../../helpers/bigInt/bigIntConversion"; import { bigIntFromBytes, bigIntToSigned } from "../../helpers/bigInt/bigIntConversion";
import cryptoWorker from "./cryptoMessagePort"; import cryptoWorker from "./cryptoMessagePort";
export default async function computeDhKey(g_b: Uint8Array, a: Uint8Array, p: Uint8Array) { export default async function computeDhKey(g_b: Uint8Array, a: Uint8Array, p: Uint8Array) {
const key = await cryptoWorker.invokeCrypto('mod-pow', g_b, a, p); const key = await cryptoWorker.invokeCrypto('mod-pow', g_b, a, p);
const keySha1Hashed = await cryptoWorker.invokeCrypto('sha1', key); const keySha1Hashed = await cryptoWorker.invokeCrypto('sha1', key);
const key_fingerprint = keySha1Hashed.slice(-8).reverse(); // key_fingerprint: key_fingerprint as any // ! it doesn't work const key_fingerprint = keySha1Hashed.slice(-8).reverse();
const key_fingerprint_long = bigIntFromBytes(key_fingerprint).toString(10); // bigInt2str(str2bigInt(bytesToHex(key_fingerprint), 16), 10); const key_fingerprint_long = bigIntToSigned(bigIntFromBytes(key_fingerprint)).toString(10);
return {key, key_fingerprint: key_fingerprint_long}; return {key, key_fingerprint: key_fingerprint_long};
} }

16
src/lib/mtproto/tl_utils.ts

@ -17,16 +17,14 @@ import isObject from '../../helpers/object/isObject';
import gzipUncompress from '../../helpers/gzipUncompress'; import gzipUncompress from '../../helpers/gzipUncompress';
import bigInt from 'big-integer'; import bigInt from 'big-integer';
import ulongFromInts from '../../helpers/long/ulongFromInts'; import ulongFromInts from '../../helpers/long/ulongFromInts';
import { safeBigInt } from '../../helpers/bigInt/bigIntConstants';
import { bigIntToSigned, bigIntToUnsigned } from '../../helpers/bigInt/bigIntConversion';
const boolFalse = +Schema.API.constructors.find((c) => c.predicate === 'boolFalse').id; const boolFalse = +Schema.API.constructors.find((c) => c.predicate === 'boolFalse').id;
const boolTrue = +Schema.API.constructors.find((c) => c.predicate === 'boolTrue').id; const boolTrue = +Schema.API.constructors.find((c) => c.predicate === 'boolTrue').id;
const vector = +Schema.API.constructors.find((c) => c.predicate === 'vector').id; const vector = +Schema.API.constructors.find((c) => c.predicate === 'vector').id;
const gzipPacked = +Schema.MTProto.constructors.find((c) => c.predicate === 'gzip_packed').id; const gzipPacked = +Schema.MTProto.constructors.find((c) => c.predicate === 'gzip_packed').id;
const safeBigInt = bigInt(Number.MAX_SAFE_INTEGER);
const ulongBigInt = bigInt(bigInt[2]).pow(64);
const longBigInt = ulongBigInt.divide(bigInt[2]);
class TLSerialization { class TLSerialization {
private maxLength = 2048; // 2Kb private maxLength = 2048; // 2Kb
private offset = 0; // in bytes private offset = 0; // in bytes
@ -151,11 +149,7 @@ class TLSerialization {
} }
} }
let _bigInt = bigInt(sLong as string); const _bigInt = bigIntToUnsigned(bigInt(sLong as string));
if(_bigInt.isNegative()) { // make it unsigned
_bigInt = ulongBigInt.add(_bigInt);
}
const {quotient, remainder} = _bigInt.divmod(0x100000000); const {quotient, remainder} = _bigInt.divmod(0x100000000);
const high = quotient.toJSNumber(); const high = quotient.toJSNumber();
const low = remainder.toJSNumber(); const low = remainder.toJSNumber();
@ -504,8 +498,8 @@ class TLDeserialization<FetchLongAs extends Long> {
const iHigh = this.readInt((field || '') + ':long[high]'); const iHigh = this.readInt((field || '') + ':long[high]');
let ulong = ulongFromInts(iHigh, iLow); let ulong = ulongFromInts(iHigh, iLow);
if(/* !unsigned && */!this.mtproto && ulong.greater(longBigInt)) { // make it signed if(/* !unsigned && */!this.mtproto) { // make it signed
ulong = ulong.minus(ulongBigInt); ulong = bigIntToSigned(ulong);
} }
if(!this.mtproto) { if(!this.mtproto) {

1
src/scss/partials/popups/_call.scss

@ -10,6 +10,7 @@
#{$parent} { #{$parent} {
&-header { &-header {
width: 100%; width: 100%;
justify-content: space-between;
} }
&-title { &-title {

Loading…
Cancel
Save