Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | 9x 9x 5x 3x 1x 8x 8x 8x 3x 3x 3x 3x 3x 1x 1x 2x 4x 4x 4x 4x 4x 1x 1x 3x 2x | import { createI18nKey } from "./ProtocolValidator.js";
import { ISegmentedSRI, EngineErrorCode } from "../types.js";
import { EngineError } from "../errors/EngineError.js";
/**
* 2026 Zenith Tier: 分割された SRI ハッシュの検証を行うユーティリティ。
* 巨大なファイルのダウンロード中にインクリメンタルな検証を可能にします。
*/
export class SegmentedVerifier {
/**
* チャンク(セグメント)ごとのハッシュを検証します。
*/
public static async verifySegment(
data: Uint8Array,
expectedHash: string,
): Promise<boolean> {
const [algo, expectedBase64] = expectedHash.split("-") as [string, string];
let webCryptoAlgo: string;
if (algo === "sha256") webCryptoAlgo = "SHA-256";
else if (algo === "sha384") webCryptoAlgo = "SHA-384";
else if (algo === "sha512") webCryptoAlgo = "SHA-512";
else return false;
// 2026: Ensure we are passing a compatible buffer to subtle crypto
const digest = await crypto.subtle.digest(
webCryptoAlgo,
data as BufferSource,
);
const actualBase64 = btoa(String.fromCharCode(...new Uint8Array(digest)));
return actualBase64 === expectedBase64;
}
/**
* ストリーム読み込み中にインクリメンタルに検証を行います。
*/
public static async assertSegmented(
fullData: ArrayBuffer,
segmentedSri: ISegmentedSRI,
): Promise<void> {
const { segmentSize, hashes } = segmentedSri;
const bytes = new Uint8Array(fullData);
Iif (!Number.isInteger(segmentSize) || segmentSize <= 0) {
const i18nKey = createI18nKey("engine.errors.sriMismatch");
throw new EngineError({
code: EngineErrorCode.SRI_MISMATCH,
message: "Segmented SRI verification failed: invalid segmentSize.",
i18nKey,
});
}
const expectedSegments = Math.ceil(bytes.length / segmentSize);
if (hashes.length !== expectedSegments) {
const i18nKey = createI18nKey("engine.errors.sriMismatch");
throw new EngineError({
code: EngineErrorCode.SRI_MISMATCH,
message: `Segmented SRI verification failed: expected ${expectedSegments} hashes, got ${hashes.length}.`,
i18nKey,
});
}
for (let i = 0; i < expectedSegments; i++) {
const start = i * segmentSize;
const end = Math.min(start + segmentSize, bytes.length);
// 2026 Zenith Tier: subarray() を使用して物理的なメモリコピーを回避
const segment = bytes.subarray(start, end);
const isValid = await this.verifySegment(segment, hashes[i]!);
if (!isValid) {
const i18nKey = createI18nKey("engine.errors.sriMismatch");
throw new EngineError({
code: EngineErrorCode.SRI_MISMATCH,
message: `Segmented SRI verification failed at segment ${i}.`,
i18nKey,
});
}
// 2026 Zenith Tier: 大規模検証中のメインスレッド・ブロッキングを防止
// 5セグメントごとにイベントループへ制御を戻す
if (i % 5 === 0) {
await new Promise((resolve) => setTimeout(resolve, 0));
}
}
}
}
|