@a4smanjorg5/invoida
Version:
> Core signing and cryptographic module for the Invoida project
28 lines (27 loc) • 1.67 kB
JavaScript
import { glob } from 'glob';
import { CompactSign, exportJWK, exportPKCS8, generateKeyPair as genKp, importPKCS8, } from 'jose';
import { randomBytes } from 'crypto';
import { mkdir, readFile, unlink, writeFile } from 'fs/promises';
import { join } from 'path';
const BUFFER_SIZE = Math.max(+process.env.INVOIDA_KIDSZ, 8) || 8;
const encodeObj = (obj) => new Uint8Array(Buffer.from(JSON.stringify(obj).replace(/[^\x00-\xff]/g, char => ('\\u' + char.charCodeAt(0).toString(16).padStart(4, '0')))));
export const generateKeyPair = async (kid) => {
const { privateKey, publicKey } = await genKp('ES256');
const jwk = await exportJWK(publicKey);
jwk.kid = kid || randomBytes(BUFFER_SIZE).toString('base64url');
await mkdir(pathToKeysDir(''), { recursive: true }).catch();
await Promise.all([
writeFile(pathToKeysDir(jwk.kid + '.jwk'), JSON.stringify(jwk)),
writeFile(pathToKeysDir(jwk.kid + '.pem'), await exportPKCS8(privateKey)),
]);
return jwk;
};
export const listKeys = async () => Promise.all((await glob(pathToKeysDir('*.jwk'), { windowsPathsNoEscape: true })).map(async (path) => JSON.parse('' + await readFile(path))));
export const removeKeyPair = (kid) => Promise.all([
unlink(pathToKeysDir(kid + '.pem')),
unlink(pathToKeysDir(kid + '.jwk')),
]).then(arr => arr[0]);
export const sign = async (payload, kid) => new CompactSign(encodeObj({ iat: Math.floor(Date.now() / 1000), ...payload }))
.setProtectedHeader({ alg: 'ES256', kid })
.sign(await importPKCS8('' + await readFile(pathToKeysDir(kid + '.pem')), 'ES256'));
const pathToKeysDir = (...paths) => join(process.env.INVOIDA_CERTS_DIR, ...paths);