/
jwk_to_key.ts
136 lines (118 loc) · 4.29 KB
/
jwk_to_key.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { Buffer } from 'buffer'
import { createPrivateKey, createPublicKey, createSecretKey } from 'crypto'
import type { KeyObject, PublicKeyInput, PrivateKeyInput } from 'crypto'
import type { JWKImportFunction } from '../interfaces.d'
import { decode as base64url } from './base64url.js'
import { JOSENotSupported } from '../../util/errors.js'
import { setCurve } from './get_named_curve.js'
import { setModulusLength } from './check_modulus_length.js'
import Asn1SequenceEncoder from './asn1_sequence_encoder.js'
import type { JWK } from '../../types.d'
import { jwkImport } from './flags.js'
const parse: JWKImportFunction = (jwk: JWK): KeyObject => {
if (jwkImport && jwk.kty !== 'oct') {
return jwk.d
? createPrivateKey({ format: 'jwk', key: jwk })
: createPublicKey({ format: 'jwk', key: jwk })
}
switch (jwk.kty) {
case 'oct': {
return createSecretKey(base64url(jwk.k!))
}
case 'RSA': {
const enc = new Asn1SequenceEncoder()
const isPrivate = jwk.d !== undefined
const modulus = Buffer.from(jwk.n!, 'base64')
const exponent = Buffer.from(jwk.e!, 'base64')
if (isPrivate) {
enc.zero()
enc.unsignedInteger(modulus)
enc.unsignedInteger(exponent)
enc.unsignedInteger(Buffer.from(jwk.d!, 'base64'))
enc.unsignedInteger(Buffer.from(jwk.p!, 'base64'))
enc.unsignedInteger(Buffer.from(jwk.q!, 'base64'))
enc.unsignedInteger(Buffer.from(jwk.dp!, 'base64'))
enc.unsignedInteger(Buffer.from(jwk.dq!, 'base64'))
enc.unsignedInteger(Buffer.from(jwk.qi!, 'base64'))
} else {
enc.unsignedInteger(modulus)
enc.unsignedInteger(exponent)
}
const der = enc.end()
const createInput: PublicKeyInput & PrivateKeyInput = {
key: der,
format: 'der',
type: 'pkcs1',
}
const keyObject = isPrivate ? createPrivateKey(createInput) : createPublicKey(createInput)
setModulusLength(keyObject, modulus.length << 3)
return keyObject
}
case 'EC': {
const enc = new Asn1SequenceEncoder()
const isPrivate = jwk.d !== undefined
const pub = Buffer.concat([
Buffer.alloc(1, 4),
Buffer.from(jwk.x!, 'base64'),
Buffer.from(jwk.y!, 'base64'),
])
if (isPrivate) {
enc.zero()
const enc$1 = new Asn1SequenceEncoder()
enc$1.oidFor('ecPublicKey')
enc$1.oidFor(jwk.crv!)
enc.add(enc$1.end())
const enc$2 = new Asn1SequenceEncoder()
enc$2.one()
enc$2.octStr(Buffer.from(jwk.d!, 'base64'))
const enc$3 = new Asn1SequenceEncoder()
enc$3.bitStr(pub)
const f2 = enc$3.end(Buffer.from([0xa1]))
enc$2.add(f2)
const f = enc$2.end()
const enc$4 = new Asn1SequenceEncoder()
enc$4.add(f)
const f3 = enc$4.end(Buffer.from([0x04]))
enc.add(f3)
const der = enc.end()
const keyObject = createPrivateKey({ key: der, format: 'der', type: 'pkcs8' })
setCurve(keyObject, jwk.crv!)
return keyObject
}
const enc$1 = new Asn1SequenceEncoder()
enc$1.oidFor('ecPublicKey')
enc$1.oidFor(jwk.crv!)
enc.add(enc$1.end())
enc.bitStr(pub)
const der = enc.end()
const keyObject = createPublicKey({ key: der, format: 'der', type: 'spki' })
setCurve(keyObject, jwk.crv!)
return keyObject
}
case 'OKP': {
const enc = new Asn1SequenceEncoder()
const isPrivate = jwk.d !== undefined
if (isPrivate) {
enc.zero()
const enc$1 = new Asn1SequenceEncoder()
enc$1.oidFor(jwk.crv!)
enc.add(enc$1.end())
const enc$2 = new Asn1SequenceEncoder()
enc$2.octStr(Buffer.from(jwk.d!, 'base64'))
const f = enc$2.end(Buffer.from([0x04]))
enc.add(f)
const der = enc.end()
return createPrivateKey({ key: der, format: 'der', type: 'pkcs8' })
}
const enc$1 = new Asn1SequenceEncoder()
enc$1.oidFor(jwk.crv!)
enc.add(enc$1.end())
enc.bitStr(Buffer.from(jwk.x!, 'base64'))
const der = enc.end()
return createPublicKey({ key: der, format: 'der', type: 'spki' })
}
default:
throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value')
}
}
export default parse