import stableStringify from 'json-stable-stringify' ; const CryptoKeyCache = new Map < string , CryptoKey > ( ) ; const JsonWebKeyCache = new WeakMap < CryptoKey , JsonWebKey > ( ) ; type Algorithms = string | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm ; export function getKeyParameter ( type ) { if ( type === 'ecdh' ) return [ [ 'deriveKey' , 'deriveBits' ] , { name : 'ECDH' , namedCurve : 'K-256' } ] ; if ( type === 'aes' ) return [ [ 'encrypt' , 'decrypt' ] , { name : 'AES-GCM' , length : 256 } ] ; if ( type === 'ecdsa' ) return [ [ 'sign' , 'verify' ] , { name : 'ecdsa' , namedCurve : 'K-256' } ] ; throw new TypeError ( 'Invalid key type' ) ; } param algorithm param key param usage export async function JsonWebKeyToCryptoKey ( key , usage , algorithm ) { key = { ... key } ; const usages = [ ... usage ] . sort ( ) . join ( ',' ) ; if ( key . key_ops ) { if ( key . key_ops . sort ( ) . join ( '.' ) !== usages ) { key . key_ops = [ ... usage ] ; } } const _key = stableStringify ( key ) + usages ; if ( CryptoKeyCache . has ( _key ) ) return CryptoKeyCache . get ( _key ) ! ; const cryptoKey = await crypto . subtle . importKey ( 'jwk' , key , algorithm , true , [ ... usage ] ) ; CryptoKeyCache . set ( _key , cryptoKey ) ; JsonWebKeyCache . set ( cryptoKey , key ) ; return cryptoKey ; } param key export async function CryptoKeyToJsonWebKey < T extends JsonWebKey = JsonWebKey > ( key ) { if ( JsonWebKeyCache . has ( key ) ) return JsonWebKeyCache . get ( key ) ! as T ; const jwk = await crypto . subtle . exportKey ( 'jwk' , key ) ; JsonWebKeyCache . set ( key , jwk ) ; const hash = stableStringify ( jwk ) + [ ... key . usages ] . sort ( ) . join ( ',' ) ; CryptoKeyCache . set ( hash , key ) ; return jwk as T ; }