check / check (push) Successful in 2m40s
downloadFile, shared by quak get, the content cache and backup, hashes the decrypted bytes (unkeyed BLAKE2b-512, standard base64) and stores nothing on a mismatch, failing with an error naming the file ID. A live photo ZIP is unpacked with fflate and its image and video hashed separately as <imageHash>:<videoHash>. decryptFile reads the older imageHash/videoHash fields for live photos. A file with no recorded hash is stored unchecked. Model: opus-5-5
34 lines
1.0 KiB
TypeScript
34 lines
1.0 KiB
TypeScript
import { beforeAll, describe, expect, it } from "vitest";
|
|
import {
|
|
chunkHashFinal,
|
|
chunkHashInit,
|
|
chunkHashUpdate,
|
|
init,
|
|
} from "../../src/crypto/index.js";
|
|
|
|
beforeAll(async () => {
|
|
await init();
|
|
});
|
|
|
|
describe("content hash", () => {
|
|
// RFC 7693 Appendix A: BLAKE2b-512 of "abc".
|
|
const abc = Buffer.from(
|
|
"ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1" +
|
|
"7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923",
|
|
"hex",
|
|
).toString("base64");
|
|
|
|
it("is unkeyed BLAKE2b-512 in standard base64", () => {
|
|
const state = chunkHashInit();
|
|
chunkHashUpdate(state, new TextEncoder().encode("abc"));
|
|
expect(chunkHashFinal(state)).toBe(abc);
|
|
});
|
|
|
|
it("gives the same hash when the input arrives in chunks", () => {
|
|
const state = chunkHashInit();
|
|
chunkHashUpdate(state, new TextEncoder().encode("a"));
|
|
chunkHashUpdate(state, new TextEncoder().encode("bc"));
|
|
expect(chunkHashFinal(state)).toBe(abc);
|
|
});
|
|
});
|