mirror of
https://github.com/hanzoai/jose.git
synced 2026-09-24 17:00:01 +00:00
Build every nested declaration and type-check the emitted entry points across supported module-resolution and library configurations. Validate type regressions, documented subpaths, package metadata, type resolution, and generated docs in CI. Expand dist cache inputs. Signed-off-by: Filip Skokan <[email protected]>
120 lines
3.0 KiB
TypeScript
120 lines
3.0 KiB
TypeScript
/// <reference types="node"/>
|
|
|
|
import { promisify } from 'node:util'
|
|
import * as crypto from 'node:crypto'
|
|
import { Buffer } from 'node:buffer'
|
|
|
|
const generate = promisify(crypto.generateKeyPair)
|
|
|
|
const stub: Pick<
|
|
typeof import('../src/index.js'),
|
|
'exportJWK' | 'generateKeyPair' | 'generateSecret' | 'importJWK'
|
|
> = {
|
|
// @ts-expect-error
|
|
exportJWK(key) {
|
|
let k: crypto.KeyObject
|
|
if (key instanceof Uint8Array) {
|
|
k = crypto.createSecretKey(key)
|
|
} else {
|
|
// @ts-expect-error
|
|
k = key
|
|
}
|
|
|
|
return (k as unknown as crypto.KeyObject).export({ format: 'jwk' })
|
|
},
|
|
// @ts-expect-error
|
|
importJWK(jwk) {
|
|
if (jwk.k) {
|
|
return Buffer.from(jwk.k, 'base64url')
|
|
}
|
|
if (jwk.d || jwk.priv) {
|
|
return crypto.createPrivateKey({ format: 'jwk', key: jwk as crypto.JsonWebKey })
|
|
}
|
|
return crypto.createPublicKey({ format: 'jwk', key: jwk as crypto.JsonWebKey })
|
|
},
|
|
// @ts-expect-error
|
|
generateSecret(alg) {
|
|
let length: number
|
|
switch (alg) {
|
|
case 'HS256':
|
|
case 'HS384':
|
|
case 'HS512':
|
|
case 'A128CBC-HS256':
|
|
case 'A192CBC-HS384':
|
|
case 'A256CBC-HS512':
|
|
length = parseInt(alg.slice(-3), 10)
|
|
break
|
|
case 'A128KW':
|
|
case 'A192KW':
|
|
case 'A256KW':
|
|
case 'A128GCMKW':
|
|
case 'A192GCMKW':
|
|
case 'A256GCMKW':
|
|
case 'A128GCM':
|
|
case 'A192GCM':
|
|
case 'A256GCM':
|
|
length = parseInt(alg.slice(1, 4), 10)
|
|
break
|
|
default:
|
|
throw new Error('unreachable')
|
|
}
|
|
|
|
return crypto.createSecretKey(crypto.randomBytes(length >> 3))
|
|
},
|
|
// @ts-expect-error
|
|
async generateKeyPair(alg, options) {
|
|
switch (alg) {
|
|
case 'RS256':
|
|
case 'RS384':
|
|
case 'RS512':
|
|
case 'PS256':
|
|
case 'PS384':
|
|
case 'PS512':
|
|
case 'RSA-OAEP':
|
|
case 'RSA-OAEP-256':
|
|
case 'RSA-OAEP-384':
|
|
case 'RSA-OAEP-512': {
|
|
const modulusLength = options?.modulusLength ?? 2048
|
|
const keypair = await generate('rsa', {
|
|
modulusLength,
|
|
publicExponent: 0x10001,
|
|
})
|
|
return keypair
|
|
}
|
|
case 'ES256':
|
|
return generate('ec', { namedCurve: 'P-256' })
|
|
case 'ES384':
|
|
return generate('ec', { namedCurve: 'P-384' })
|
|
case 'ES512':
|
|
return generate('ec', { namedCurve: 'P-521' })
|
|
case 'Ed25519': // Fall through
|
|
case 'EdDSA':
|
|
return generate('ed25519')
|
|
case 'ECDH-ES':
|
|
case 'ECDH-ES+A128KW':
|
|
case 'ECDH-ES+A192KW':
|
|
case 'ECDH-ES+A256KW': {
|
|
const crv = options?.crv ?? 'P-256'
|
|
switch (crv) {
|
|
case 'P-256':
|
|
case 'P-384':
|
|
case 'P-521':
|
|
return generate('ec', { namedCurve: crv })
|
|
case 'X25519':
|
|
return generate('x25519')
|
|
default:
|
|
Error('unreachable')
|
|
}
|
|
}
|
|
case 'ML-DSA-44':
|
|
case 'ML-DSA-65':
|
|
case 'ML-DSA-87':
|
|
return generate(alg.toLowerCase() as 'ml-dsa-44' | 'ml-dsa-65' | 'ml-dsa-87')
|
|
default:
|
|
Error('unreachable')
|
|
}
|
|
},
|
|
}
|
|
|
|
export { stub }
|