-
-
Notifications
You must be signed in to change notification settings - Fork 300
/
jwk.ts
119 lines (108 loc) · 3.52 KB
/
jwk.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import type QUnit from 'qunit'
import * as env from './env.js'
import { KEYS } from './fixtures.js'
import type * as jose from '../src/index.js'
export default (QUnit: QUnit, lib: typeof jose) => {
const { module, test } = QUnit
module('jwk.ts')
type Vector = [string, JsonWebKey, boolean] | [string, JsonWebKey, boolean, boolean]
const algorithms: Vector[] = [
['ECDH-ES', KEYS.P256.jwk, true],
['ECDH-ES', KEYS.P384.jwk, true],
['ECDH-ES', KEYS.P521.jwk, !env.isDeno],
[
'ECDH-ES',
KEYS.X25519.jwk,
env.isDeno || env.isNode || env.isElectron || env.isWorkerd || env.isEdgeRuntime,
env.isDeno,
],
['ECDH-ES', KEYS.X448.jwk, env.isNode || env.isEdgeRuntime],
['EdDSA', KEYS.Ed25519.jwk, (env.isWebKit && env.isWebKitAbove17) || !env.isBrowser],
['EdDSA', KEYS.Ed448.jwk, env.isNode || env.isEdgeRuntime],
['ES256', KEYS.P256.jwk, true],
['ES256K', KEYS.secp256k1.jwk, env.isNodeCrypto],
['ES384', KEYS.P384.jwk, true],
['ES512', KEYS.P521.jwk, !env.isDeno],
['PS256', KEYS.RSA.jwk, true],
['PS384', KEYS.RSA.jwk, true],
['PS512', KEYS.RSA.jwk, true],
['RS256', KEYS.RSA.jwk, true],
['RS384', KEYS.RSA.jwk, true],
['RS512', KEYS.RSA.jwk, true],
['RSA-OAEP-256', KEYS.RSA.jwk, true],
['RSA-OAEP-384', KEYS.RSA.jwk, true],
['RSA-OAEP-512', KEYS.RSA.jwk, true],
['RSA-OAEP', KEYS.RSA.jwk, true],
]
function publicJwk(jwk: JsonWebKey) {
const { d, p, q, dp, dq, qi, k, ...result } = jwk
return result
}
for (const vector of algorithms.slice()) {
algorithms.push([vector[0], publicJwk(vector[1]), vector[2]])
}
function title(alg: string, jwk: JsonWebKey, works: boolean) {
let result = ''
if (!works) {
result = '[not supported] '
}
result += `${alg} `
if (alg === 'EdDSA' || alg === 'ECDH-ES') {
result += `${jwk.crv} `
}
result += jwk.d ? 'Private' : 'Public'
result += ' JWK Import'
return result
}
for (const vector of algorithms) {
const [alg, jwk] = vector
let [, , works, exportNotImplemented] = vector
const execute = async (t: typeof QUnit.assert) => {
const key = await lib.importJWK({ ...jwk, ext: true }, alg)
if (exportNotImplemented) {
try {
await lib.exportJWK(key)
throw new Error()
} catch (err) {
t.strictEqual((<Error>err).name, 'NotSupportedError')
}
} else {
const exported = await lib.exportJWK(key)
for (const prop of [...new Set([...Object.keys(jwk), ...Object.keys(exported)])]) {
t.strictEqual(exported[prop], jwk[<keyof JsonWebKey>prop], `${prop} mismatch`)
}
}
t.ok(1)
}
if (works) {
test(title(alg, jwk, works), execute)
} else {
test(title(alg, jwk, works), async (t) => {
await t.rejects(execute(t))
})
}
}
if (env.isNodeCrypto || env.isElectron) {
test('alg argument and jwk.alg is ignored', async (t) => {
const oct = {
k: 'FyCq1CKBflh3I5gikEjpYrdOXllzxB_yc02za8ERknI',
kty: 'oct',
}
await lib.importJWK(oct)
t.ok(1)
})
} else {
test('alg argument must be present if jwk does not have alg', async (t) => {
const oct = {
k: 'FyCq1CKBflh3I5gikEjpYrdOXllzxB_yc02za8ERknI',
kty: 'oct',
}
await t.rejects(
lib.importJWK(oct),
'"alg" argument is required when "jwk.alg" is not present',
)
await lib.importJWK(oct, 'HS256')
await lib.importJWK({ ...oct, alg: 'HS256' })
})
}
}