UNPKG

@fanoutio/grip

Version:
132 lines (131 loc) 3.71 kB
import * as jose from 'jose'; import { decodeBytesFromBase64String } from './base64.js'; const textEncoder = new TextEncoder(); const textDecoder = new TextDecoder(); export class PemKey { keyString; type; constructor(keyString) { if (keyString.startsWith('-----BEGIN PUBLIC KEY-----')) { this.type = 'public'; } else if (keyString.startsWith('-----BEGIN PRIVATE KEY-----')) { this.type = 'private'; } else { throw new TypeError('Attempt to construct PemKey with string that is evidently not a PEM'); } this.keyString = keyString; } async getKeyLike(alg) { if (this.keyString.indexOf('-----BEGIN PRIVATE KEY-----') === 0) { return jose.importPKCS8(this.keyString, alg); } if (this.keyString.indexOf('-----BEGIN PUBLIC KEY-----') === 0) { return jose.importSPKI(this.keyString, alg); } throw new Error('PEM type not supported.'); } } export class JwkKey { jwk; constructor(jwk) { this.jwk = jwk; } async getSecretOrKeyLike(alg) { return jose.importJWK(this.jwk, alg); } } export function isSymmetricSecret(key) { if (key instanceof Uint8Array) { return true; } else if (key instanceof PemKey) { return false; } else if (key instanceof JwkKey) { return key.jwk.kty === 'oct'; } return key.type === 'secret'; } function isPem(keyString) { return (keyString.startsWith('-----BEGIN PUBLIC KEY-----') || keyString.startsWith('-----BEGIN PRIVATE KEY-----')); } function isJsonWebKey(obj) { if (obj == null) { return false; } return obj.kty != null; } export function loadKey(key) { let result = key; if (typeof result === 'string' && result.startsWith('base64:')) { result = result.slice(7); result = decodeBytesFromBase64String(result); } // If the array starts with five hyphens, // it might be a PEM-encoded SPKI or PKCS#8 key if (result instanceof Uint8Array && result.at(0) === 45 && result.at(1) === 45 && result.at(2) === 45 && result.at(3) === 45 && result.at(4) === 45) { let keyString = null; try { keyString = textDecoder.decode(result); } catch { } if (keyString != null) { if (isPem(keyString)) { result = new PemKey(keyString); } } } if (typeof result === 'string') { if (isPem(result)) { result = new PemKey(result); } } // '{' if (result instanceof Uint8Array && result.at(0) === 123) { let keyString = null; try { keyString = textDecoder.decode(result); } catch { } if (keyString != null) { let jsonObj = null; try { jsonObj = JSON.parse(keyString); } catch { } if (jsonObj != null && isJsonWebKey(jsonObj)) { result = new JwkKey(jsonObj); } } } if (typeof result === 'string') { if (result.startsWith('{')) { let jsonObj = null; try { jsonObj = JSON.parse(result); } catch { } if (jsonObj != null && isJsonWebKey(jsonObj)) { result = new JwkKey(jsonObj); } } } if (isJsonWebKey(result)) { result = new JwkKey(result); } if (typeof result === 'string') { result = textEncoder.encode(result); } return result; }