import crypto from 'crypto'; import { createSigner, createVerifier } from './JWS'; import { JsonWebKey2020, Sm2VerificationKey2019, Sm2VerificationKey2020, } from './types'; import { Sm2KeyPair } from './Sm2KeyPair'; const getKeyPairForKtyAndCrv = (kty: string, crv: string) => { if (kty === 'EC' && crv === 'SM2') { return Sm2KeyPair; } throw new Error(`getKeyPairForKtyAndCrv does not support: ${kty} and ${crv}`); }; const getKeyPairForType = (k: any) => { if (k.type === 'JsonWebKey2020') { return getKeyPairForKtyAndCrv(k.publicKeyJwk.kty, k.publicKeyJwk.crv); } if ( k.type === 'Sm2VerificationKey2019' || k.type === 'Sm2VerificationKey2020' ) { return Sm2KeyPair; } throw new Error('getKeyPairForType does not support type: ' + k.type); }; const getVerifier = async (k: any, options = { detached: true }) => { const { publicKeyJwk } = await k.export({ type: 'JsonWebKey2020' }); const { kty, crv } = publicKeyJwk; if (kty === 'EC' && crv === 'SM2') { return createVerifier(k.verifier('SM2'), 'SM2', options); } throw new Error( `getVerifier does not suppport ${JSON.stringify(publicKeyJwk, null, 2)}` ); }; const getSigner = async (k: any, options = { detached: true }) => { const { publicKeyJwk } = await k.export({ type: 'JsonWebKey2020' }); const { kty, crv } = publicKeyJwk; if (kty === 'EC' && crv === 'SM2') { return createSigner(k.signer('SM2'), 'SM2', options); } throw new Error( `getSigner does not suppport ${JSON.stringify(publicKeyJwk, null, 2)}` ); }; const applyJwa = async (k: any, options?: any) => { const verifier = await getVerifier(k, options); k.verifier = () => verifier as any; if (k.privateKey) { const signer = await getSigner(k, options); k.signer = () => signer as any; } return k; }; // this is dirty... const useJwa = async (k: any, options?: any) => { // before mutation, annotate the apply function.... k.useJwa = async (options?: any) => { return applyJwa(k, options); }; return applyJwa(k, options); }; export class SM2JsonWebKey { public id!: string; public type!: string; public controller!: string; static generate = async ( options: any = { kty: 'EC', crv: 'SM2', detached: true, } ) => { const KeyPair = getKeyPairForKtyAndCrv(options.kty, options.crv); if (!options.secureRandom) { options.secureRandom = () => { return crypto.randomBytes(32); }; } const kp = await KeyPair.generate({ secureRandom: options.secureRandom, }); const { detached } = options; return useJwa(kp, { detached }); }; static from = async ( k: JsonWebKey2020 | Sm2VerificationKey2019 | Sm2VerificationKey2020, options: any = { detached: true } ) => { const KeyPair = getKeyPairForType(k); const kp = await KeyPair.from(k as any); let { detached, header } = options; if (detached === undefined) { detached = true; } return useJwa(kp, { detached, header }); }; public signer!: () => any; public verifier!: () => any; }