-
-
Notifications
You must be signed in to change notification settings - Fork 371
Expand file tree
/
Copy pathgenerate_secret.ts
More file actions
105 lines (99 loc) · 3.27 KB
/
Copy pathgenerate_secret.ts
File metadata and controls
105 lines (99 loc) · 3.27 KB
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
/**
* Symmetric key generation
*
* @module
*/
import { JOSENotSupported } from '../util/errors.js'
import type * as types from '../types.d.ts'
/** Secret generation function options. */
export interface GenerateSecretOptions {
/**
* The value to use as {@link !SubtleCrypto.generateKey} `extractable` argument. Default is false.
*
* > [!NOTE]\
* > Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
* > {@link !CryptoKey} this option has no effect for them.
*/
extractable?: boolean
}
/**
* JWA Algorithm Identifier for symmetric secret generation.
*
* The {@link https://github.com/panva/jose/issues/114 Algorithm Selection Guide} should be consulted
* as a quick reference if you're having trouble selecting an appropriate algorithm for your needs.
*
* See {@link https://github.com/panva/jose/issues/210 Algorithm Key Requirements} for usage support
* details.
*/
export type SecretKeyAlgorithm =
| `HS${'256' | '384' | '512'}`
| `A${'128' | '192' | '256'}${'GCM' | 'KW' | 'GCMKW'}`
| `A128CBC-HS256`
| `A192CBC-HS384`
| `A256CBC-HS512`
/**
* Generates a symmetric secret key for a given JWA algorithm identifier.
*
* > [!NOTE]\
* > The secret key is generated with `extractable` set to `false` by default.
*
* > [!NOTE]\
* > Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
* > {@link !CryptoKey} this method yields a {@link !Uint8Array} for them instead.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/generate/secret'`.
*
* @example
*
* ```js
* const secret = await jose.generateSecret('HS256')
* console.log(secret)
* ```
*
* @param alg JWA Algorithm Identifier to be used with the generated secret. See
* {@link https://github.com/panva/jose/issues/210 Algorithm Key Requirements}.
* @param options Additional options passed down to the secret generation.
*/
export async function generateSecret(
alg: SecretKeyAlgorithm,
options?: GenerateSecretOptions,
): Promise<types.CryptoKey | Uint8Array> {
let length: number
let algorithm: AesKeyGenParams | HmacKeyGenParams
let keyUsages: KeyUsage[]
switch (alg) {
case 'HS256':
case 'HS384':
case 'HS512':
length = parseInt(alg.slice(-3), 10)
algorithm = { name: 'HMAC', hash: `SHA-${length}`, length }
keyUsages = ['sign', 'verify']
break
case 'A128CBC-HS256':
case 'A192CBC-HS384':
case 'A256CBC-HS512':
length = parseInt(alg.slice(-3), 10)
return crypto.getRandomValues(new Uint8Array(length >> 3))
case 'A128KW':
case 'A192KW':
case 'A256KW':
length = parseInt(alg.slice(1, 4), 10)
algorithm = { name: 'AES-KW', length }
keyUsages = ['wrapKey', 'unwrapKey']
break
case 'A128GCMKW':
case 'A192GCMKW':
case 'A256GCMKW':
case 'A128GCM':
case 'A192GCM':
case 'A256GCM':
length = parseInt(alg.slice(1, 4), 10)
algorithm = { name: 'AES-GCM', length }
keyUsages = ['encrypt', 'decrypt']
break
default:
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')
}
return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages)
}