Initial commit
This commit is contained in:
126
tests/drop-crypto.test.mjs
Normal file
126
tests/drop-crypto.test.mjs
Normal file
@@ -0,0 +1,126 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { loadModule } from "./test-helpers.mjs";
|
||||
|
||||
const crypto = await loadModule("app/utils/crypto.ts");
|
||||
const id = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
||||
const key = crypto.generateKey();
|
||||
const wrongKey = crypto.generateKey();
|
||||
const nonce = crypto.generateNoncePrefix();
|
||||
|
||||
test("AES-GCM manifest and chunk round trips preserve plaintext", async () => {
|
||||
const plain = new TextEncoder().encode("hello chunk");
|
||||
const cipher = await crypto.encryptChunk(
|
||||
plain,
|
||||
key,
|
||||
id,
|
||||
nonce,
|
||||
0,
|
||||
8 * 1024 * 1024,
|
||||
1,
|
||||
);
|
||||
assert.deepEqual(
|
||||
[
|
||||
...(await crypto.decryptChunk(
|
||||
cipher,
|
||||
key,
|
||||
id,
|
||||
nonce,
|
||||
0,
|
||||
plain.byteLength,
|
||||
8 * 1024 * 1024,
|
||||
1,
|
||||
)),
|
||||
],
|
||||
[...plain],
|
||||
);
|
||||
const manifest = {
|
||||
version: 2,
|
||||
name: "hello.txt",
|
||||
type: "text/plain",
|
||||
size: plain.byteLength,
|
||||
lastModified: 1,
|
||||
chunkSize: 8 * 1024 * 1024,
|
||||
chunkCount: 1,
|
||||
};
|
||||
const encrypted = await crypto.encryptManifest(manifest, key, id, nonce);
|
||||
assert.deepEqual(
|
||||
await crypto.decryptManifest(
|
||||
encrypted,
|
||||
key,
|
||||
id,
|
||||
nonce,
|
||||
manifest.chunkSize,
|
||||
manifest.chunkCount,
|
||||
),
|
||||
manifest,
|
||||
);
|
||||
});
|
||||
|
||||
test("empty chunks are authenticated and round-trip", async () => {
|
||||
const cipher = await crypto.encryptChunk(
|
||||
new Uint8Array(),
|
||||
key,
|
||||
id,
|
||||
nonce,
|
||||
0,
|
||||
8 * 1024 * 1024,
|
||||
1,
|
||||
);
|
||||
assert.equal(cipher.byteLength, 16);
|
||||
assert.equal(
|
||||
(
|
||||
await crypto.decryptChunk(
|
||||
cipher,
|
||||
key,
|
||||
id,
|
||||
nonce,
|
||||
0,
|
||||
0,
|
||||
8 * 1024 * 1024,
|
||||
1,
|
||||
)
|
||||
).byteLength,
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
test("tampering and wrong key or AAD fail integrity", async () => {
|
||||
const cipher = await crypto.encryptChunk(
|
||||
new Uint8Array([1, 2, 3]),
|
||||
key,
|
||||
id,
|
||||
nonce,
|
||||
0,
|
||||
8 * 1024 * 1024,
|
||||
1,
|
||||
);
|
||||
const tampered = new Uint8Array(cipher);
|
||||
tampered[0] ^= 1;
|
||||
await assert.rejects(
|
||||
crypto.decryptChunk(tampered, key, id, nonce, 0, 3, 8 * 1024 * 1024, 1),
|
||||
/integrity/,
|
||||
);
|
||||
await assert.rejects(
|
||||
crypto.decryptChunk(cipher, wrongKey, id, nonce, 0, 3, 8 * 1024 * 1024, 1),
|
||||
/integrity/,
|
||||
);
|
||||
await assert.rejects(
|
||||
crypto.decryptChunk(cipher, key, id, nonce, 1, 3, 8 * 1024 * 1024, 1),
|
||||
/integrity/,
|
||||
);
|
||||
});
|
||||
|
||||
test("tag-only manifests are rejected before decryption", async () => {
|
||||
await assert.rejects(
|
||||
crypto.decryptManifest(
|
||||
new Uint8Array(16),
|
||||
key,
|
||||
id,
|
||||
nonce,
|
||||
8 * 1024 * 1024,
|
||||
1,
|
||||
),
|
||||
/empty/,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user