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 | 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 207x 207x 207x 207x 207x 207x 207x 10x 314x 314x 314x 314x 2x 2x 2x 2x 2x 312x 314x 10x 10x 10x 118x 1x 1x 117x 117x 117x 118x 2x 2x 115x 118x 10x 10x 10x 197x 197x 197x 197x 10x 10x 10x 20x 19x 20x | // Copyright 2026 优谷雅言 open.shengzhiai.com. Licensed under the Apache License, Version 2.0.
// HMAC-SHA256 signature (CONTRACT 0.2, DESIGN 5.2) with Web Crypto, available in browsers and Node 18+.
import { localError } from './errors.js';
import { bytesToBase64, getCrypto, utf8 } from './util.js';
/**
* The signed text: drop null, undefined and empty string values, sort keys in natural order,
* join as key=value with &, no URL encoding.
*/
export function buildSignPayload(params) {
const p = params || {};
return Object.keys(p)
.filter((k) => p[k] !== null && p[k] !== undefined && p[k] !== '')
.sort()
.map((k) => `${k}=${p[k]}`)
.join('&');
}
function subtleOf(cryptoImpl) {
const c = getCrypto(cryptoImpl);
const subtle = c && c.subtle;
if (!subtle || typeof subtle.importKey !== 'function') {
throw localError(
90010,
'Web Crypto subtle 不可用。浏览器需运行在 https 或 localhost 安全上下文,Node 18 需传入 crypto 选项,例如 webcrypto',
);
}
return subtle;
}
/** Imports the HMAC key once; the promise can be cached by the caller. */
export function importHmacKey(secret, cryptoImpl) {
if (typeof secret !== 'string' || secret === '') {
return Promise.reject(localError(90010, '签名需要非空的 secretKey'));
}
let subtle;
try {
subtle = subtleOf(cryptoImpl);
} catch (e) {
return Promise.reject(e);
}
return subtle.importKey('raw', utf8(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
}
/** Signs an already built payload with an imported key. */
export async function signPayloadWithKey(payload, key, cryptoImpl) {
const subtle = subtleOf(cryptoImpl);
const sig = await subtle.sign('HMAC', key, utf8(payload));
return bytesToBase64(new Uint8Array(sig));
}
/** Base64(HMAC_SHA256(buildSignPayload(params), secret)). */
export async function signHmacSha256(params, secret, cryptoImpl) {
const key = await importHmacKey(secret, cryptoImpl);
return signPayloadWithKey(buildSignPayload(params), key, cryptoImpl);
}
|