paseto-ts
Version:
PASETO v4 (encrypt, decrypt, sign & verify) in TypeScript
55 lines (54 loc) • 2.59 kB
JavaScript
import { PasetoFormatInvalid, PasetoPurposeInvalid } from '../lib/errors.js';
import { concat, stringToUint8Array } from '../lib/uint8array.js';
import { base64UrlEncode } from '../lib/base64url.js';
import { generateKeyPair } from '@stablelib/ed25519';
export function generateKeys(purpose, opts = { format: 'paserk' }) {
let ret;
const format = opts?.format ?? 'paserk';
const getRandomValues = opts?.getRandomValues ?? (typeof globalThis !== 'undefined' && globalThis.crypto?.getRandomValues ? globalThis.crypto.getRandomValues.bind(globalThis.crypto) : undefined);
if (!getRandomValues) {
throw new Error('No compatible getRandomValues implementation detected in the global scope. Please pass a getRandomValues implementation to the options object (signature: getRandomValues<Uint8Array>(array: Uint8Array): Uint8Array)');
}
switch (purpose) {
case 'local':
// For local keys, we generate a random 32-byte key
const random = getRandomValues(new Uint8Array(32));
if (random === null) {
throw new Error('getRandomValues returned an invalid length Uint8Array');
}
switch (format) {
case 'paserk':
ret = `k4.local.${base64UrlEncode(random)}`;
break;
case 'buffer':
ret = concat(stringToUint8Array('k4.local.'), random);
break;
default:
throw new PasetoFormatInvalid(`Invalid format: ${format}`);
}
break;
case 'public':
// For public keys, we generate an Ed25519 key pair
const keyPair = generateKeyPair();
switch (format) {
case 'paserk':
ret = {
secretKey: `k4.secret.${base64UrlEncode(keyPair.secretKey)}`,
publicKey: `k4.public.${base64UrlEncode(keyPair.publicKey)}`,
};
break;
case 'buffer':
ret = {
secretKey: concat(stringToUint8Array('k4.secret.'), keyPair.secretKey),
publicKey: concat(stringToUint8Array('k4.public.'), keyPair.publicKey),
};
break;
default:
throw new PasetoFormatInvalid(`Invalid format: ${format}`);
}
break;
default:
throw new PasetoPurposeInvalid(`Invalid purpose: ${purpose}`);
}
return ret;
}