nodemod
Version:
A collection of node modules for The Really Project
60 lines • 2.31 kB
JavaScript
import { createHmac } from 'crypto';
export class SignaturError extends Error {
type;
constructor(type, message) {
super();
this.name = 'SignaturError';
this.message = message;
this.type = type;
}
toJSON() {
return {
error: {
type: this.type,
message: this.message,
},
};
}
}
function urlSafeBase64(s) {
return s.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
export function signSync(data, secret, options) {
const { separator = '.' } = options || {};
if (null == data) {
throw new TypeError(`Expected 'data' to be defined, but received '${JSON.stringify(data)}'`);
}
if ('string' !== typeof (secret) || !secret.length) {
throw new TypeError(`Expected 'secret' to be defined, but received '${secret}'`);
}
const stringData = JSON.stringify({ data });
const encoded = Buffer.from(stringData, 'utf8').toString('base64');
const signature = createHmac('sha256', secret).update(stringData).digest('base64');
return urlSafeBase64(`${encoded}${separator}${signature}`);
}
export function unsignSync(signature, secret, options) {
const { separator = '.' } = options || {};
if ('string' !== typeof (signature) || !signature.length) {
throw new TypeError(`Expected 'signature' to be defined, but received '${signature}'`);
}
if ('string' !== typeof (secret) || !secret.length) {
throw new TypeError(`Expected 'secret' to be defined, but received '${secret}'`);
}
const [hash, enc] = signature.split(separator, 2);
const decoded = Buffer.from((hash + '==='.slice((hash.length + 3) % 4))
.replace(/-/g, '+')
.replace(/_/g, '/'), 'base64')
.toString('utf8');
const signedDecoded = urlSafeBase64(createHmac('sha256', secret).update(decoded).digest('base64'));
if (enc !== signedDecoded) {
throw new SignaturError('invalid_signature', 'Signature not match');
}
return JSON.parse(decoded).data;
}
export async function sign(data, secret, options) {
return signSync(data, secret, options);
}
export async function unsign(signature, secret, options) {
return unsignSync(signature, secret, options);
}
//# sourceMappingURL=index.js.map