File size: 3,155 Bytes
494c9e4 | 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 | /**
* 哈希工具函数
*/
import { tr } from '../lang/i18n-lite';
/**
* Crypto Subtle 不可用错误
* 用于标识因 crypto.subtle 不可用导致的错误
*/
export class CryptoSubtleUnavailableError extends Error {
constructor(message: string) {
super(message);
this.name = 'CryptoSubtleUnavailableError';
}
}
/**
* 验证哈希值格式(4位十六进制)
* @param hash 待验证的哈希值
* @returns 是否为有效的4位十六进制哈希
*/
export function isValidHash(hash: string): boolean {
return /^[0-9a-fA-F]{4}$/.test(hash);
}
/**
* 检查 crypto.subtle 是否可用
* @returns 是否可用
*/
function isCryptoSubtleAvailable(): boolean {
return typeof crypto !== 'undefined' &&
crypto.subtle !== undefined;
}
/**
* 计算文件内容的4位哈希值
* @param data 文件内容
* @returns 4位十六进制哈希值
* @throws CryptoSubtleUnavailableError 如果 crypto.subtle 不可用
*/
export async function hashContent(data: any): Promise<string> {
// 检查 crypto.subtle 是否可用
if (!isCryptoSubtleAvailable()) {
const isLocalhost = window.location.hostname === 'localhost' ||
window.location.hostname === '127.0.0.1' ||
window.location.hostname === '[::1]';
const protocol = window.location.protocol;
let message = tr('Unable to use encryption API (crypto.subtle), local cache save feature is unavailable.') + '\n\n';
if (protocol === 'http:' && !isLocalhost) {
message += tr('Reason: Currently accessing via non-HTTPS non-localhost address, browser security policy has disabled encryption API.') + '\n\n';
message += tr('Solution:') + '\n';
message += '1. ' + tr('Recommended: Access via http://localhost:port (recommended)') + '\n';
message += '2. ' + tr('Or: Configure HTTPS access');
} else if (protocol === 'file:') {
message += tr('Reason: Opening page via file:// protocol, browser security policy has disabled encryption API.') + '\n\n';
message += tr('Solution: Please access the application via http://localhost:port');
} else {
message += tr('Reason: Browser does not support or has disabled encryption API.') + '\n\n';
message += tr('Solution:') + '\n';
message += '1. ' + tr('Use http://localhost:port to access (recommended)') + '\n';
message += '2. ' + tr('Or configure HTTPS access');
}
throw new CryptoSubtleUnavailableError(message);
}
// 序列化数据
const content = JSON.stringify(data);
// 使用 SubtleCrypto API 计算 SHA-256
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(content);
const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
// 转换为十六进制字符串,取前4位
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex.slice(0, 4);
}
|