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 | 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 189x 189x 189x 189x 189x 189x 189x 8x 286x 286x 286x 286x 2x 2x 2x 2x 2x 284x 286x 8x 8x 8x 108x 1x 1x 107x 107x 107x 108x 2x 2x 105x 108x 8x 8x 8x 179x 179x 179x 179x 8x 8x 8x 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);
}
|