UNPKG

@a4smanjorg5/invoida

Version:

> Core signing and cryptographic module for the Invoida project

28 lines (27 loc) 1.67 kB
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);