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 201x 201x 201x 201x 201x 201x 201x 10x 302x 302x 302x 302x 2x 2x 2x 2x 2x 300x 302x 10x 10x 10x 112x 1x 1x 111x 111x 111x 112x 2x 2x 109x 112x 10x 10x 10x 191x 191x 191x 191x 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);
}
|