const ec = new EC('p256');
const key = ec.keyFromPrivate(privateKeyHex, 'hex');
const signature = key.sign(hashHex, { canonical: true });
const derHex = signature.toDER('hex'); // DER-encoded signatureconst stampObj = {
publicKey: compressedPublicKey, // 66-char hex string
scheme: 'SIGNATURE_SCHEME_TK_API_P256',
signature: derHex, // DER-encoded signature as hex
};const signature = base64UrlEncode(JSON.stringify(stampObj));
// Use signature in your API request
import { ec as EC } from 'elliptic';
// SHA-256 hashing function
const sha256 = async (input) => {
const data = new TextEncoder().encode(input);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
return Array.from(new Uint8Array(hashBuffer))
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
};
// Base64URL encoding
const toBase64Url = (str) => {
const b64 = btoa(unescape(encodeURIComponent(str)));
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
};
/**
* Sign payload using API key pair
* @param {string} payload - The payload string to sign (typically JSON.stringify(requestBody))
* @param {string} apiPrivateKey - 64-character hex string (32 bytes)
* @param {string} apiPublicKey - 66-character hex string (33 bytes, compressed)
* @returns {Promise-{signature: string, details: object}-} - Signature result
*/
export const signPayloadWithApiKey = async (payload, apiPrivateKey, apiPublicKey) => {
if (!apiPrivateKey || !apiPublicKey) {
throw new Error('API key pair not found');
}
// Initialize elliptic curve (P-256)
const ec = new EC('p256');
// Verify public key matches private key
const key = ec.keyFromPrivate(apiPrivateKey, 'hex');
const derivedPubHex = key.getPublic(true, 'hex'); // Compressed format
if (derivedPubHex !== apiPublicKey) {
throw new Error('Public key does not match private key');
}
// Hash the payload
const hashHex = await sha256(payload);
// Sign the hash
const sig = key.sign(hashHex, { canonical: true });
// Encode signature to DER format
const derHex = sig.toDER('hex');
// Construct signature object
const stampObj = {
publicKey: apiPublicKey,
scheme: 'SIGNATURE_SCHEME_TK_API_P256',
signature: derHex,
};
// Base64URL encode the signature
const signature = toBase64Url(JSON.stringify(stampObj));
return {
signature,
details: {
publicKey: apiPublicKey,
scheme: stampObj.scheme,
signature: derHex,
payloadHash: hashHex,
},
};
};
// Usage example:
// const result = await signPayloadWithApiKey(
// JSON.stringify(requestBody),
// localStorage.getItem('apiPrivateKey'),
// localStorage.getItem('apiPublicKey')
// );
// // Use result.signature in your API request