74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
/**
|
|
* Test helper: build a real, signature-valid chunk byte string.
|
|
*
|
|
* Uses `@suaveplan/drive-plugin-chunks`' `buildSignedChunk` over a
|
|
* synthetic but well-formed `Chunk` so `verifyChunkSig` accepts the
|
|
* result. Fixtures stay deterministic — no random bytes anywhere.
|
|
*/
|
|
|
|
import {
|
|
getPublicKey,
|
|
randomPrivateKey,
|
|
} from "@suaveplan/crypto-curve/ed25519";
|
|
import { buildSignedChunk } from "@suaveplan/drive-plugin-chunks";
|
|
|
|
export interface Keypair {
|
|
readonly privKey: Uint8Array;
|
|
readonly pubKey: Uint8Array;
|
|
}
|
|
|
|
export function makeKeypair(seed = 1): Keypair {
|
|
// Deterministic seed via a 32-byte buffer filled with `seed`. Noble
|
|
// does not strictly require uniformly-random keys for verifiability,
|
|
// only that the corresponding public key is derived from the same
|
|
// private key.
|
|
const priv =
|
|
seed === 0 ? randomPrivateKey() : new Uint8Array(32).fill(seed & 0xff);
|
|
const pub = getPublicKey(priv);
|
|
return { privKey: priv, pubKey: pub };
|
|
}
|
|
|
|
export function fileIdBytes(hex: string): Uint8Array {
|
|
if (hex.length !== 64) {
|
|
throw new Error(`fileId hex must be 64 chars, got ${hex.length}`);
|
|
}
|
|
const out = new Uint8Array(32);
|
|
for (let i = 0; i < 32; i++) {
|
|
const byteHex = hex.slice(i * 2, i * 2 + 2);
|
|
out[i] = Number.parseInt(byteHex, 16);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export function buildChunkBytes(args: {
|
|
readonly serverPrivKey: Uint8Array;
|
|
readonly fileIdHex: string;
|
|
readonly chunkId: number;
|
|
readonly totalChunks?: number;
|
|
readonly payload?: Uint8Array;
|
|
}): Uint8Array {
|
|
const totalChunks = args.totalChunks ?? 8;
|
|
const payload =
|
|
args.payload ?? new Uint8Array([args.chunkId & 0xff, 0x42, 0x13, 0x37]);
|
|
const chunkSize = Math.max(payload.byteLength, 4);
|
|
const chunk = {
|
|
metadata: {
|
|
version: 0x0001,
|
|
fileId: fileIdBytes(args.fileIdHex),
|
|
chunkId: args.chunkId,
|
|
totalChunks,
|
|
fileSize: BigInt(chunkSize * totalChunks),
|
|
chunkSize,
|
|
payloadLen: payload.byteLength,
|
|
flags: 0,
|
|
nonce: new Uint8Array(24),
|
|
aeadTag: new Uint8Array(16),
|
|
},
|
|
sig: new Uint8Array(64), // overwritten by buildSignedChunk
|
|
ciphertext: payload,
|
|
};
|
|
return buildSignedChunk(chunk, args.serverPrivKey);
|
|
}
|
|
|
|
export const TEST_FILE_ID_HEX = "a".repeat(64);
|