Fully move to protobufjs

This commit is contained in:
Fedor Indutny 2021-07-13 11:54:53 -07:00 committed by GitHub
parent 20ea409d9e
commit 570fb182d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 1133 additions and 12401 deletions

View file

@ -11,6 +11,8 @@ import {
hmacSha256,
sha256,
verifyHmacSha256,
base64ToArrayBuffer,
typedArrayToArrayBuffer,
} from '../Crypto';
declare global {
@ -335,10 +337,7 @@ const Crypto = {
encryptedProfileName: string,
key: ArrayBuffer
): Promise<{ given: ArrayBuffer; family: ArrayBuffer | null }> {
const data = window.dcodeIO.ByteBuffer.wrap(
encryptedProfileName,
'base64'
).toArrayBuffer();
const data = base64ToArrayBuffer(encryptedProfileName);
return Crypto.decryptProfile(data, key).then(decrypted => {
const padded = new Uint8Array(decrypted);
@ -364,13 +363,9 @@ const Crypto = {
const foundFamilyName = familyEnd > givenEnd + 1;
return {
given: window.dcodeIO.ByteBuffer.wrap(padded)
.slice(0, givenEnd)
.toArrayBuffer(),
given: typedArrayToArrayBuffer(padded.slice(0, givenEnd)),
family: foundFamilyName
? window.dcodeIO.ByteBuffer.wrap(padded)
.slice(givenEnd + 1, familyEnd)
.toArrayBuffer()
? typedArrayToArrayBuffer(padded.slice(givenEnd + 1, familyEnd))
: null,
};
});

View file

@ -6,27 +6,14 @@
/* eslint-disable no-proto */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ByteBufferClass } from '../window.d';
let ByteBuffer: ByteBufferClass | undefined;
const arrayBuffer = new ArrayBuffer(0);
const uint8Array = new Uint8Array();
let StaticByteBufferProto: any;
const StaticArrayBufferProto = (arrayBuffer as any).__proto__;
const StaticUint8ArrayProto = (uint8Array as any).__proto__;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function getString(thing: any): string {
// Note: we must make this at runtime because it's loaded in the browser context
if (!ByteBuffer) {
ByteBuffer = new window.dcodeIO.ByteBuffer();
}
if (!StaticByteBufferProto) {
StaticByteBufferProto = (ByteBuffer as any).__proto__;
}
if (thing === Object(thing)) {
if (thing.__proto__ === StaticUint8ArrayProto) {
return String.fromCharCode.apply(null, thing);
@ -34,9 +21,6 @@ function getString(thing: any): string {
if (thing.__proto__ === StaticArrayBufferProto) {
return getString(new Uint8Array(thing));
}
if (thing.__proto__ === StaticByteBufferProto) {
return thing.toString('binary');
}
}
return thing;
}
@ -48,8 +32,7 @@ function getStringable(thing: any): boolean {
typeof thing === 'boolean' ||
(thing === Object(thing) &&
(thing.__proto__ === StaticArrayBufferProto ||
thing.__proto__ === StaticUint8ArrayProto ||
thing.__proto__ === StaticByteBufferProto))
thing.__proto__ === StaticUint8ArrayProto))
);
}

View file

@ -193,7 +193,7 @@ class MessageReceiverInner extends EventTarget {
server: WebAPIType;
serverTrustRoot: ArrayBuffer;
serverTrustRoot: Uint8Array;
signalingKey: ArrayBuffer;
@ -239,9 +239,7 @@ class MessageReceiverInner extends EventTarget {
if (!options.serverTrustRoot) {
throw new Error('Server trust root is required!');
}
this.serverTrustRoot = MessageReceiverInner.stringToArrayBufferBase64(
options.serverTrustRoot
);
this.serverTrustRoot = Bytes.fromBase64(options.serverTrustRoot);
this.number_id = oldUsername
? utils.unencodeNumber(oldUsername)[0]
@ -286,18 +284,6 @@ class MessageReceiverInner extends EventTarget {
});
}
static stringToArrayBuffer = (string: string): ArrayBuffer =>
window.dcodeIO.ByteBuffer.wrap(string, 'binary').toArrayBuffer();
static arrayBufferToString = (arrayBuffer: ArrayBuffer): string =>
window.dcodeIO.ByteBuffer.wrap(arrayBuffer).toString('binary');
static stringToArrayBufferBase64 = (string: string): ArrayBuffer =>
window.dcodeIO.ByteBuffer.wrap(string, 'base64').toArrayBuffer();
static arrayBufferToStringBase64 = (arrayBuffer: ArrayBuffer): string =>
window.dcodeIO.ByteBuffer.wrap(arrayBuffer).toString('base64');
async connect(socket?: WebSocket): Promise<void> {
if (this.calledClose) {
return;
@ -2479,8 +2465,8 @@ class MessageReceiverInner extends EventTarget {
const paddedData = await Crypto.decryptAttachment(
encrypted,
MessageReceiverInner.stringToArrayBufferBase64(key),
MessageReceiverInner.stringToArrayBufferBase64(digest)
typedArrayToArrayBuffer(Bytes.fromBase64(key)),
typedArrayToArrayBuffer(Bytes.fromBase64(digest))
);
if (!isNumber(size)) {
@ -2688,14 +2674,4 @@ export default class MessageReceiver {
checkSocket: () => void;
getProcessedCount: () => number;
static stringToArrayBuffer = MessageReceiverInner.stringToArrayBuffer;
static arrayBufferToString = MessageReceiverInner.arrayBufferToString;
static stringToArrayBufferBase64 =
MessageReceiverInner.stringToArrayBufferBase64;
static arrayBufferToStringBase64 =
MessageReceiverInner.arrayBufferToStringBase64;
}

View file

@ -28,23 +28,22 @@ import PQueue from 'p-queue';
import { v4 as getGuid } from 'uuid';
import { client as WebSocketClient, connection as WebSocket } from 'websocket';
import { z } from 'zod';
import Long from 'long';
import { Long } from '../window.d';
import { assert } from '../util/assert';
import { getUserAgent } from '../util/getUserAgent';
import { toWebSafeBase64 } from '../util/webSafeBase64';
import { isPackIdValid, redactPackId } from '../types/Stickers';
import * as Bytes from '../Bytes';
import {
arrayBufferToBase64,
base64ToArrayBuffer,
bytesFromHexString,
bytesFromString,
concatenateBytes,
constantTimeEqual,
decryptAesGcm,
deriveSecrets,
encryptCdsDiscoveryRequest,
getBytes,
getRandomValue,
splitUuids,
typedArrayToArrayBuffer,
@ -84,7 +83,7 @@ type SgxConstantsType = {
let sgxConstantCache: SgxConstantsType | null = null;
function makeLong(value: string): Long {
return window.dcodeIO.Long.fromString(value);
return Long.fromString(value);
}
function getSgxConstants() {
if (sgxConstantCache) {
@ -2434,34 +2433,38 @@ export function initialize({
function validateAttestationQuote({
serverStaticPublic,
quote,
quote: quoteArrayBuffer,
}: {
serverStaticPublic: ArrayBuffer;
quote: ArrayBuffer;
}) {
const SGX_CONSTANTS = getSgxConstants();
const byteBuffer = window.dcodeIO.ByteBuffer.wrap(
quote,
'binary',
window.dcodeIO.ByteBuffer.LITTLE_ENDIAN
);
const quote = Buffer.from(quoteArrayBuffer);
const quoteVersion = byteBuffer.readShort(0) & 0xffff;
let off = 0;
const quoteVersion = quote.readInt32LE(off) & 0xffff;
off += 4;
if (quoteVersion < 0 || quoteVersion > 2) {
throw new Error(`Unknown version ${quoteVersion}`);
}
const miscSelect = new Uint8Array(getBytes(quote, 64, 4));
const miscSelect = quote.slice(off, off + 64);
off += 64;
if (!miscSelect.every(byte => byte === 0)) {
throw new Error('Quote miscSelect invalid!');
}
const reserved1 = new Uint8Array(getBytes(quote, 68, 28));
const reserved1 = quote.slice(off, off + 28);
off += 28;
if (!reserved1.every(byte => byte === 0)) {
throw new Error('Quote reserved1 invalid!');
}
const flags = byteBuffer.readLong(96);
const flags = Long.fromBytesLE(
Array.from(quote.slice(off, off + 8).values())
);
off += 8;
if (
flags.and(SGX_CONSTANTS.SGX_FLAGS_RESERVED).notEquals(0) ||
flags.and(SGX_CONSTANTS.SGX_FLAGS_INITTED).equals(0) ||
@ -2470,25 +2473,29 @@ export function initialize({
throw new Error(`Quote flags invalid ${flags.toString()}`);
}
const xfrm = byteBuffer.readLong(104);
const xfrm = Long.fromBytesLE(
Array.from(quote.slice(off, off + 8).values())
);
off += 8;
if (xfrm.and(SGX_CONSTANTS.SGX_XFRM_RESERVED).notEquals(0)) {
throw new Error(`Quote xfrm invalid ${xfrm}`);
}
const mrenclave = new Uint8Array(getBytes(quote, 112, 32));
const enclaveIdBytes = new Uint8Array(
bytesFromHexString(directoryEnclaveId)
);
if (!mrenclave.every((byte, index) => byte === enclaveIdBytes[index])) {
const mrenclave = quote.slice(off, off + 32);
off += 32;
const enclaveIdBytes = Bytes.fromHex(directoryEnclaveId);
if (mrenclave.compare(enclaveIdBytes) !== 0) {
throw new Error('Quote mrenclave invalid!');
}
const reserved2 = new Uint8Array(getBytes(quote, 144, 32));
const reserved2 = quote.slice(off, off + 32);
off += 32;
if (!reserved2.every(byte => byte === 0)) {
throw new Error('Quote reserved2 invalid!');
}
const reportData = new Uint8Array(getBytes(quote, 368, 64));
const reportData = quote.slice(off, off + 64);
off += 64;
const serverStaticPublicBytes = new Uint8Array(serverStaticPublic);
if (
!reportData.every((byte, index) => {
@ -2501,22 +2508,26 @@ export function initialize({
throw new Error('Quote report_data invalid!');
}
const reserved3 = new Uint8Array(getBytes(quote, 208, 96));
const reserved3 = quote.slice(off, off + 96);
off += 96;
if (!reserved3.every(byte => byte === 0)) {
throw new Error('Quote reserved3 invalid!');
}
const reserved4 = new Uint8Array(getBytes(quote, 308, 60));
const reserved4 = quote.slice(off, off + 60);
off += 60;
if (!reserved4.every(byte => byte === 0)) {
throw new Error('Quote reserved4 invalid!');
}
const signatureLength = byteBuffer.readInt(432) & 0xffff_ffff;
const signatureLength = quote.readInt32LE(432) >>> 0;
off += 4;
if (signatureLength !== quote.byteLength - 436) {
throw new Error(`Bad signatureLength ${signatureLength}`);
}
// const signature = Uint8Array.from(getBytes(quote, 436, signatureLength));
// const signature = quote.slice(off, signatureLength);
// off += signatureLength
}
function validateAttestationSignatureBody(