mirror of
https://github.com/hanzoai/jose.git
synced 2026-09-24 17:00:01 +00:00
135 lines
3.9 KiB
TypeScript
135 lines
3.9 KiB
TypeScript
import type QUnit from 'qunit'
|
|
import type * as jose from '../src/index.js'
|
|
|
|
type keyType = Uint8Array | jose.CryptoKey | jose.KeyObject | jose.GenerateKeyPairResult
|
|
|
|
function isKeyPair(input: keyType): input is jose.GenerateKeyPairResult {
|
|
return 'publicKey' in input && 'privateKey' in input
|
|
}
|
|
|
|
async function getKeys(
|
|
secretOrKeyPair: keyType,
|
|
jwk: false,
|
|
keys: Pick<typeof jose, 'exportJWK' | 'generateKeyPair' | 'generateSecret' | 'importJWK'>,
|
|
): Promise<Array<Uint8Array | jose.CryptoKey | jose.KeyObject>>
|
|
async function getKeys(
|
|
secretOrKeyPair: keyType,
|
|
jwk: true,
|
|
keys: Pick<typeof jose, 'exportJWK' | 'generateKeyPair' | 'generateSecret' | 'importJWK'>,
|
|
): Promise<Array<jose.JWK>>
|
|
async function getKeys(
|
|
secretOrKeyPair: keyType,
|
|
jwk: boolean,
|
|
keys: Pick<typeof jose, 'exportJWK' | 'generateKeyPair' | 'generateSecret' | 'importJWK'>,
|
|
) {
|
|
let sKey = isKeyPair(secretOrKeyPair) ? secretOrKeyPair.privateKey : secretOrKeyPair
|
|
let vKey = isKeyPair(secretOrKeyPair) ? secretOrKeyPair.publicKey : secretOrKeyPair
|
|
|
|
if (jwk) {
|
|
// @ts-ignore
|
|
return [await keys.exportJWK(sKey), await keys.exportJWK(vKey)]
|
|
}
|
|
|
|
return [sKey, vKey]
|
|
}
|
|
|
|
function jwkWithProps(jwk: jose.JWK, alg: string) {
|
|
jwk = structuredClone(jwk)
|
|
jwk.alg = alg
|
|
jwk.use = 'sig'
|
|
if (jwk.k) {
|
|
jwk.key_ops = ['sign', 'verify']
|
|
} else if (jwk.d || jwk.priv) {
|
|
jwk.key_ops = ['sign']
|
|
} else {
|
|
jwk.key_ops = ['verify']
|
|
}
|
|
|
|
return jwk
|
|
}
|
|
|
|
export async function jws(
|
|
t: typeof QUnit.assert,
|
|
lib: typeof jose,
|
|
keys: Pick<typeof jose, 'exportJWK' | 'generateKeyPair' | 'generateSecret' | 'importJWK'>,
|
|
alg: string,
|
|
secretOrKeyPair: keyType,
|
|
payload = crypto.getRandomValues(new Uint8Array(16)),
|
|
) {
|
|
// Test Uint8Array, CryptoKey, and KeyObject key inputs
|
|
{
|
|
const [sKey, vKey] = await getKeys(secretOrKeyPair, false, keys)
|
|
const jws = await new lib.FlattenedSign(payload).setProtectedHeader({ alg }).sign(sKey)
|
|
{
|
|
const verified = await lib.flattenedVerify(jws, vKey)
|
|
t.deepEqual([...verified.payload], [...payload])
|
|
}
|
|
{
|
|
const verified = await lib.flattenedVerify(jws, async () => vKey)
|
|
t.propContains(verified, {
|
|
key: vKey,
|
|
payload,
|
|
protectedHeader: { alg },
|
|
})
|
|
}
|
|
}
|
|
|
|
if (secretOrKeyPair instanceof Uint8Array) return
|
|
|
|
// Test JWK key input
|
|
{
|
|
const [sKey, vKey] = await getKeys(secretOrKeyPair, true, keys)
|
|
const jws = await new lib.FlattenedSign(payload).setProtectedHeader({ alg }).sign(sKey)
|
|
await new lib.FlattenedSign(payload).setProtectedHeader({ alg }).sign(jwkWithProps(sKey, alg))
|
|
for (const key of [
|
|
vKey,
|
|
async () => vKey,
|
|
jwkWithProps(vKey, alg),
|
|
async () => jwkWithProps(vKey, alg),
|
|
]) {
|
|
// @ts-ignore
|
|
const verified = await lib.flattenedVerify(jws, key)
|
|
t.deepEqual([...verified.payload], [...payload])
|
|
}
|
|
}
|
|
|
|
// Test JWK key input with all JWK properties
|
|
{
|
|
const [sKey, vKey] = await getKeys(secretOrKeyPair, true, keys)
|
|
const jws = await new lib.FlattenedSign(payload)
|
|
.setProtectedHeader({ alg })
|
|
.sign(jwkWithProps(sKey, alg))
|
|
const verified = await lib.flattenedVerify(jws, {
|
|
...vKey,
|
|
alg,
|
|
use: 'sig',
|
|
key_ops: ['verify'],
|
|
})
|
|
t.deepEqual([...verified.payload], [...payload])
|
|
}
|
|
}
|
|
|
|
export async function jwt(
|
|
t: typeof QUnit.assert,
|
|
lib: typeof jose,
|
|
keys: Pick<typeof jose, 'exportJWK' | 'generateKeyPair' | 'generateSecret' | 'importJWK'>,
|
|
alg: string,
|
|
secretOrKeyPair: keyType,
|
|
) {
|
|
const [sKey, vKey] = await getKeys(secretOrKeyPair, false, keys)
|
|
const jwt = await new lib.SignJWT({ foo: 'bar', '🤷♂️': '🤷♀️' })
|
|
.setProtectedHeader({ alg, '🤷♂️': '🤷♀️' })
|
|
.sign(sKey)
|
|
const verified = await lib.jwtVerify(jwt, vKey)
|
|
t.deepEqual(verified, {
|
|
payload: {
|
|
foo: 'bar',
|
|
'🤷♂️': '🤷♀️',
|
|
},
|
|
protectedHeader: {
|
|
alg,
|
|
'🤷♂️': '🤷♀️',
|
|
},
|
|
})
|
|
}
|