Fully move to protobufjs
This commit is contained in:
parent
20ea409d9e
commit
570fb182d4
46 changed files with 1133 additions and 12401 deletions
|
@ -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,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -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))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue