Buckets:
| import { importJWK } from '../key/import.js'; | |
| import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js'; | |
| import isObject from '../lib/is_object.js'; | |
| function getKtyFromAlg(alg) { | |
| switch (typeof alg === 'string' && alg.slice(0, 2)) { | |
| case 'RS': | |
| case 'PS': | |
| return 'RSA'; | |
| case 'ES': | |
| return 'EC'; | |
| case 'Ed': | |
| return 'OKP'; | |
| default: | |
| throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); | |
| } | |
| } | |
| function isJWKSLike(jwks) { | |
| return (jwks && | |
| typeof jwks === 'object' && | |
| Array.isArray(jwks.keys) && | |
| jwks.keys.every(isJWKLike)); | |
| } | |
| function isJWKLike(key) { | |
| return isObject(key); | |
| } | |
| function clone(obj) { | |
| if (typeof structuredClone === 'function') { | |
| return structuredClone(obj); | |
| } | |
| return JSON.parse(JSON.stringify(obj)); | |
| } | |
| class LocalJWKSet { | |
| constructor(jwks) { | |
| this._cached = new WeakMap(); | |
| if (!isJWKSLike(jwks)) { | |
| throw new JWKSInvalid('JSON Web Key Set malformed'); | |
| } | |
| this._jwks = clone(jwks); | |
| } | |
| async getKey(protectedHeader, token) { | |
| const { alg, kid } = { ...protectedHeader, ...token?.header }; | |
| const kty = getKtyFromAlg(alg); | |
| const candidates = this._jwks.keys.filter((jwk) => { | |
| let candidate = kty === jwk.kty; | |
| if (candidate && typeof kid === 'string') { | |
| candidate = kid === jwk.kid; | |
| } | |
| if (candidate && typeof jwk.alg === 'string') { | |
| candidate = alg === jwk.alg; | |
| } | |
| if (candidate && typeof jwk.use === 'string') { | |
| candidate = jwk.use === 'sig'; | |
| } | |
| if (candidate && Array.isArray(jwk.key_ops)) { | |
| candidate = jwk.key_ops.includes('verify'); | |
| } | |
| if (candidate && alg === 'EdDSA') { | |
| candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'; | |
| } | |
| if (candidate) { | |
| switch (alg) { | |
| case 'ES256': | |
| candidate = jwk.crv === 'P-256'; | |
| break; | |
| case 'ES256K': | |
| candidate = jwk.crv === 'secp256k1'; | |
| break; | |
| case 'ES384': | |
| candidate = jwk.crv === 'P-384'; | |
| break; | |
| case 'ES512': | |
| candidate = jwk.crv === 'P-521'; | |
| break; | |
| } | |
| } | |
| return candidate; | |
| }); | |
| const { 0: jwk, length } = candidates; | |
| if (length === 0) { | |
| throw new JWKSNoMatchingKey(); | |
| } | |
| if (length !== 1) { | |
| const error = new JWKSMultipleMatchingKeys(); | |
| const { _cached } = this; | |
| error[Symbol.asyncIterator] = async function* () { | |
| for (const jwk of candidates) { | |
| try { | |
| yield await importWithAlgCache(_cached, jwk, alg); | |
| } | |
| catch { } | |
| } | |
| }; | |
| throw error; | |
| } | |
| return importWithAlgCache(this._cached, jwk, alg); | |
| } | |
| } | |
| async function importWithAlgCache(cache, jwk, alg) { | |
| const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); | |
| if (cached[alg] === undefined) { | |
| const key = await importJWK({ ...jwk, ext: true }, alg); | |
| if (key instanceof Uint8Array || key.type !== 'public') { | |
| throw new JWKSInvalid('JSON Web Key Set members must be public keys'); | |
| } | |
| cached[alg] = key; | |
| } | |
| return cached[alg]; | |
| } | |
| export function createLocalJWKSet(jwks) { | |
| const set = new LocalJWKSet(jwks); | |
| const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token); | |
| Object.defineProperties(localJWKSet, { | |
| jwks: { | |
| value: () => clone(set._jwks), | |
| enumerable: true, | |
| configurable: false, | |
| writable: false, | |
| }, | |
| }); | |
| return localJWKSet; | |
| } | |
Xet Storage Details
- Size:
- 4.18 kB
- Xet hash:
- 48a7021beb0389c6d695f30132ee21ce9d8ed699e8a77a4ca6b701dd94704475
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.