Checkpoint
Some checks failed
Test and build / Test and lint (push) Failing after 36s
Test and build / Build collector (push) Failing after 43s
Test and build / Build receiver (push) Failing after 42s

This commit is contained in:
2026-03-05 15:38:18 +01:00
parent 3106b2cf45
commit 13afa08e8a
108 changed files with 19509 additions and 729 deletions

110
ui/src/util.ts Normal file
View File

@@ -0,0 +1,110 @@
export const base64ToBytes = (b64: string): Uint8Array => {
const binaryString = atob(b64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
export const bytesToBase64 = (buf: Uint8Array): string => {
const bytes: string[] = new Array(buf.length);
for (let i = 0; i < buf.length; i++) {
bytes[i] = String.fromCharCode(buf[i]);
}
return btoa(bytes.join(''));
}
/**
* Do semi constant time comparison of two Uint8Arrays to prevent timing attacks.
* Returns true if the arrays are equal, false otherwise.
*
* Note: This is not truly constant time, but it is designed to take the same amount of time regardless of where the first difference is.
* It will still take longer for longer arrays, but it will not short-circuit on the first difference.
*/
export const constantTimeEqual = (a: Uint8Array, b: Uint8Array): boolean => {
if (a.length !== b.length) return false;
let result = 0;
for (let i = 0; i < a.length; i++) {
result |= a[i] ^ b[i];
}
return result === 0;
}
/* BufferReader is a utility class for reading and writing binary data from a Uint8Array buffer.
* It maintains an internal offset and length to track the current position in the buffer. It
* provides methods for reading unsigned integers in little-endian format, as well as arbitrary
* byte arrays. It also allows writing unsigned integers back into the buffer. This class is
* useful for parsing and constructing binary protocols.
*/
export class BufferReader {
protected buffer: Uint8Array;
protected offset: number = 0;
public length: number = 0;
constructor(buffer: Uint8Array) {
this.buffer = new Uint8Array(buffer.length);
for (let i = 0; i < buffer.length; i++) {
this.buffer[i] = buffer[i];
}
this.length = buffer.length;
}
public reset(buffer: Uint8Array) {
this.buffer = new Uint8Array(buffer.length);
for (let i = 0; i < buffer.length; i++) {
this.buffer[i] = buffer[i];
}
this.offset = 0;
this.length = buffer.length;
}
public readUint8(): number {
const value = this.buffer[this.offset];
this.offset++;
this.length--;
return value;
}
public readUint16LE(): number {
const value = this.buffer[this.offset] | (this.buffer[this.offset + 1] << 8);
this.offset += 2;
this.length -= 2;
return value;
}
public readUint32LE(): number {
const value = this.buffer[this.offset] |
(this.buffer[this.offset + 1] << 8) |
(this.buffer[this.offset + 2] << 16) |
(this.buffer[this.offset + 3] << 24);
this.offset += 4;
this.length -= 4;
return value;
}
public readBytes(size?: number): Uint8Array {
size ||= (this.buffer.length - this.offset);
const value = this.buffer.slice(this.offset, this.offset + size);
this.offset += size;
this.length -= size;
return value;
}
public writeUint16LE(value: number): void {
this.buffer[this.offset] = value & 0xFF;
this.buffer[this.offset + 1] = (value >> 8) & 0xFF;
this.offset += 2;
this.length += 2;
}
public writeUint32LE(value: number): void {
this.buffer[this.offset] = value & 0xFF;
this.buffer[this.offset + 1] = (value >> 8) & 0xFF;
this.buffer[this.offset + 2] = (value >> 16) & 0xFF;
this.buffer[this.offset + 3] = (value >> 24) & 0xFF;
this.offset += 4;
this.length += 4;
}
}