summaryrefslogtreecommitdiff
path: root/tests/fixtures/setup.ts
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fixtures/setup.ts')
-rw-r--r--tests/fixtures/setup.ts146
1 files changed, 146 insertions, 0 deletions
diff --git a/tests/fixtures/setup.ts b/tests/fixtures/setup.ts
new file mode 100644
index 0000000..0b23ec8
--- /dev/null
+++ b/tests/fixtures/setup.ts
@@ -0,0 +1,146 @@
+import {
+ createMessage,
+ decryptKey,
+ generateKey,
+ PrivateKey,
+ sign,
+} from "npm:openpgp@^6.1.1";
+import { passphrase } from "./test_data.ts";
+import { MaybeIterable } from "../../src/utils/iterator.ts";
+import { afterEach, beforeEach } from "@std/testing/bdd";
+import { Stub, stub } from "@std/testing/mock";
+
+export async function generateKeyPair(
+ name: string,
+ options?: Partial<Parameters<typeof generateKey>[0]>,
+): ReturnType<typeof generateKey> {
+ const key = await generateKey({
+ type: "ecc",
+ userIDs: [{
+ name,
+ email: `${
+ name.toLowerCase().replaceAll(/\s/g, "")
+ }@localhost.localdomain`,
+ }],
+ passphrase,
+ format: "object",
+ ...options,
+ });
+ const privateKey = await decryptKey({
+ privateKey: key.privateKey,
+ passphrase,
+ });
+ return { ...key, privateKey };
+}
+
+export function generateKeyPairWithSubkey(
+ name: string,
+): ReturnType<typeof generateKey> {
+ return generateKeyPair(name, {
+ curve: "nistP256",
+ subkeys: [{ type: "ecc", curve: "nistP256", sign: true }],
+ });
+}
+
+export async function createDetachedSignature(
+ data: Uint8Array,
+ signingKeys: MaybeIterable<PrivateKey>,
+): Promise<Uint8Array<ArrayBuffer>> {
+ const message = await createMessage({ binary: data });
+ const signature = await sign({
+ message,
+ signingKeys: Symbol.iterator in signingKeys
+ ? Iterator.from(signingKeys).toArray()
+ : signingKeys,
+ detached: true,
+ format: "object",
+ });
+ return signature.write() as Uint8Array<ArrayBuffer>;
+}
+
+export function corruptData(data: Uint8Array): Uint8Array<ArrayBuffer> {
+ const corrupted = new Uint8Array(data);
+ if (corrupted.length > 0) {
+ corrupted[0] += 1;
+ corrupted[0] %= 1 << 8;
+ }
+ return corrupted;
+}
+
+export function corruptSignatureFormat(
+ signature: Uint8Array,
+): Uint8Array<ArrayBuffer> {
+ const corrupted = new Uint8Array(signature);
+
+ if (corrupted.length > 0) {
+ // Strategy 1: Change the packet tag byte
+ // The first byte contains the tag and format information.
+ // Changing the lower 6 bits (new format tag) or higher bits (packet format)
+ // can easily break parsing. Let's try flipping a bit.
+ // corrupted[0] = corrupted[0] ^ 0x01; // Flip the last bit
+
+ // Strategy 2 (Alternative - more drastic): Truncate the signature
+ // return corrupted.slice(0, corrupted.length / 2); // Cut off half the signature
+
+ // Strategy 3 (Alternative - modify length field):
+ // This is more complex as length encoding varies, but for typical new format
+ // packets, length information is in the bytes immediately following the tag.
+ // Modifying these can cause the parser to misinterpret the packet length.
+ // Example (simplified, might need adjustment based on actual encoding):
+ if (corrupted.length > 2) {
+ corrupted[1] = (corrupted[1] + 10) % 256;
+ }
+ }
+ return corrupted;
+}
+
+const inMemoryFiles = new Map<
+ string,
+ { text?: string; bytes?: Uint8Array<ArrayBuffer> }
+>();
+
+export function startMockFs(): void {
+ inMemoryFiles.clear();
+
+ beforeEach(() => {
+ Deno.readTextFile = stub(
+ Deno,
+ "readTextFile",
+ async (path: string | URL) => {
+ const url = new URL(path).href;
+ const content = inMemoryFiles.get(url)?.text;
+ if (content === undefined) {
+ throw new Deno.errors.NotFound(`File not found: ${url}`);
+ }
+ return await Promise.resolve(content);
+ },
+ );
+
+ Deno.readFile = stub(Deno, "readFile", async (path: string | URL) => {
+ const url = new URL(path).href;
+ const content = inMemoryFiles.get(url)?.bytes;
+ if (content === undefined) {
+ throw new Deno.errors.NotFound(`File not found: ${url}`);
+ }
+ return await Promise.resolve(content);
+ });
+
+ inMemoryFiles.clear();
+ });
+
+ afterEach(() => {
+ (Deno.readTextFile as Stub).restore();
+ (Deno.readFile as Stub).restore();
+ });
+}
+
+export function createInMemoryFile(
+ url: URL,
+ content: string | Uint8Array<ArrayBuffer>,
+): URL {
+ inMemoryFiles.set(
+ url.href,
+ typeof content === "string" ? { text: content } : { bytes: content },
+ );
+ return url;
+}