HMAC 계산을 Web Worker에서 처리하도록 변경

This commit is contained in:
static
2026-01-12 15:16:43 +09:00
parent b636d75ea0
commit e7dc96bb47
4 changed files with 52 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
import { hmac } from "@noble/hashes/hmac.js";
import { sha256 } from "@noble/hashes/sha2.js";
import HmacWorker from "$workers/hmac?worker";
import type { ComputeMessage, ResultMessage } from "$workers/hmac";
export const digestMessage = async (message: BufferSource) => {
return await crypto.subtle.digest("SHA-256", message);
@@ -18,10 +18,24 @@ export const generateHmacSecret = async () => {
};
};
export const createHmacStream = async (hmacSecret: CryptoKey) => {
const h = hmac.create(sha256, new Uint8Array(await crypto.subtle.exportKey("raw", hmacSecret)));
return {
update: (data: Uint8Array) => h.update(data),
digest: () => h.digest(),
};
export const signMessageHmac = async (message: Blob, hmacSecret: CryptoKey) => {
const worker = new HmacWorker();
const stream = message.stream();
const hmacSecretRaw = new Uint8Array(await crypto.subtle.exportKey("raw", hmacSecret));
return new Promise<Uint8Array>((resolve, reject) => {
worker.onmessage = (event: MessageEvent<ResultMessage>) => {
resolve(event.data.result);
worker.terminate();
};
worker.onerror = ({ error }) => {
reject(error);
worker.terminate();
};
worker.postMessage({ stream, key: hmacSecretRaw } satisfies ComputeMessage, {
transfer: [stream, hmacSecretRaw.buffer],
});
});
};

View File

@@ -1,13 +1,8 @@
import ExifReader from "exifreader";
import { limitFunction } from "p-limit";
import { CHUNK_SIZE } from "$lib/constants";
import {
encodeToBase64,
generateDataKey,
wrapDataKey,
encryptString,
createHmacStream,
} from "$lib/modules/crypto";
import { encodeToBase64, generateDataKey, wrapDataKey, encryptString } from "$lib/modules/crypto";
import { signMessageHmac } from "$lib/modules/crypto";
import { Scheduler } from "$lib/modules/scheduler";
import { generateThumbnail } from "$lib/modules/thumbnail";
import { uploadBlob } from "$lib/modules/upload";
@@ -56,16 +51,8 @@ export const clearUploadedFiles = () => {
const requestDuplicateFileScan = limitFunction(
async (file: File, hmacSecret: HmacSecret, onDuplicate: () => Promise<boolean>) => {
const hmacStream = await createHmacStream(hmacSecret.secret);
const reader = file.stream().getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
hmacStream.update(value);
}
const fileSigned = encodeToBase64(hmacStream.digest());
const hmacResult = await signMessageHmac(file, hmacSecret.secret);
const fileSigned = encodeToBase64(hmacResult);
const files = await trpc().file.listByHash.query({
hskVersion: hmacSecret.version,
contentHmac: fileSigned,

25
src/workers/hmac.ts Normal file
View File

@@ -0,0 +1,25 @@
import { hmac } from "@noble/hashes/hmac.js";
import { sha256 } from "@noble/hashes/sha2.js";
export interface ComputeMessage {
stream: ReadableStream;
key: Uint8Array;
}
export interface ResultMessage {
result: Uint8Array;
}
self.onmessage = async (event: MessageEvent<ComputeMessage>) => {
const h = hmac.create(sha256, event.data.key);
const reader = event.data.stream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
h.update(value);
}
const result = h.digest();
self.postMessage({ result } satisfies ResultMessage, { transfer: [result.buffer] });
};