jose 4.0.4 → 4.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/{runtime → lib}/aesgcmkw.js +8 -8
- package/dist/browser/lib/check_key_type.js +1 -1
- package/dist/browser/lib/crypto_key.js +46 -56
- package/dist/browser/lib/decrypt_key_management.js +1 -1
- package/dist/browser/lib/encrypt_key_management.js +1 -1
- package/dist/browser/{runtime → lib}/invalid_key_input.js +0 -0
- package/dist/browser/runtime/aeskw.js +1 -1
- package/dist/browser/runtime/asn1.js +6 -7
- package/dist/browser/runtime/base64url.js +2 -4
- package/dist/browser/runtime/bogus.js +1 -1
- package/dist/browser/runtime/decrypt.js +2 -2
- package/dist/browser/runtime/ecdhes.js +1 -1
- package/dist/browser/runtime/encrypt.js +2 -2
- package/dist/browser/runtime/env.js +11 -0
- package/dist/browser/runtime/fetch_jwks.js +3 -5
- package/dist/browser/runtime/generate.js +5 -5
- package/dist/browser/runtime/get_sign_verify_key.js +2 -2
- package/dist/browser/runtime/jwk_to_key.js +5 -5
- package/dist/browser/runtime/key_to_jwk.js +1 -1
- package/dist/browser/runtime/pbes2kw.js +11 -34
- package/dist/browser/runtime/rsaes.js +1 -1
- package/dist/browser/runtime/subtle_dsa.js +8 -27
- package/dist/browser/runtime/webcrypto.js +8 -4
- package/dist/node/cjs/{runtime → lib}/aesgcmkw.js +8 -8
- package/dist/node/cjs/lib/check_key_type.js +1 -1
- package/dist/node/cjs/lib/crypto_key.js +48 -58
- package/dist/node/cjs/lib/decrypt_key_management.js +1 -1
- package/dist/node/cjs/lib/encrypt_key_management.js +1 -1
- package/dist/node/cjs/{runtime → lib}/invalid_key_input.js +0 -11
- package/dist/node/cjs/runtime/aeskw.js +1 -1
- package/dist/node/cjs/runtime/asn1.js +1 -1
- package/dist/node/cjs/runtime/decrypt.js +1 -1
- package/dist/node/cjs/runtime/ecdhes.js +1 -1
- package/dist/node/cjs/runtime/encrypt.js +1 -1
- package/dist/node/cjs/runtime/{global.js → env.js} +0 -0
- package/dist/node/cjs/runtime/get_named_curve.js +1 -1
- package/dist/node/cjs/runtime/get_sign_verify_key.js +1 -1
- package/dist/node/cjs/runtime/key_to_jwk.js +1 -1
- package/dist/node/cjs/runtime/node_key.js +6 -10
- package/dist/node/cjs/runtime/pbes2kw.js +1 -1
- package/dist/node/cjs/runtime/rsaes.js +1 -1
- package/dist/node/esm/{runtime → lib}/aesgcmkw.js +8 -8
- package/dist/node/esm/lib/check_key_type.js +1 -1
- package/dist/node/esm/lib/crypto_key.js +46 -56
- package/dist/node/esm/lib/decrypt_key_management.js +1 -1
- package/dist/node/esm/lib/encrypt_key_management.js +1 -1
- package/dist/node/esm/{runtime → lib}/invalid_key_input.js +0 -11
- package/dist/node/esm/runtime/aeskw.js +1 -1
- package/dist/node/esm/runtime/asn1.js +1 -1
- package/dist/node/esm/runtime/decrypt.js +1 -1
- package/dist/node/esm/runtime/ecdhes.js +1 -1
- package/dist/node/esm/runtime/encrypt.js +1 -1
- package/dist/node/esm/runtime/{global.js → env.js} +0 -0
- package/dist/node/esm/runtime/get_named_curve.js +1 -1
- package/dist/node/esm/runtime/get_sign_verify_key.js +1 -1
- package/dist/node/esm/runtime/key_to_jwk.js +1 -1
- package/dist/node/esm/runtime/node_key.js +6 -10
- package/dist/node/esm/runtime/pbes2kw.js +1 -1
- package/dist/node/esm/runtime/rsaes.js +1 -1
- package/dist/types/jwks/remote.d.ts +4 -0
- package/package.json +4 -1
- package/dist/browser/runtime/global.js +0 -27
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import encrypt from '
|
|
2
|
-
import decrypt from '
|
|
3
|
-
import generateIv from '
|
|
4
|
-
import { encode as base64url } from '
|
|
5
|
-
export
|
|
1
|
+
import encrypt from '../runtime/encrypt.js';
|
|
2
|
+
import decrypt from '../runtime/decrypt.js';
|
|
3
|
+
import generateIv from './iv.js';
|
|
4
|
+
import { encode as base64url } from '../runtime/base64url.js';
|
|
5
|
+
export async function wrap(alg, key, cek, iv) {
|
|
6
6
|
const jweAlgorithm = alg.substr(0, 7);
|
|
7
7
|
iv || (iv = generateIv(jweAlgorithm));
|
|
8
8
|
const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
|
|
9
9
|
return { encryptedKey, iv: base64url(iv), tag: base64url(tag) };
|
|
10
|
-
}
|
|
11
|
-
export
|
|
10
|
+
}
|
|
11
|
+
export async function unwrap(alg, key, encryptedKey, iv, tag) {
|
|
12
12
|
const jweAlgorithm = alg.substr(0, 7);
|
|
13
13
|
return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
|
|
14
|
-
}
|
|
14
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { isCloudflareWorkers, isNodeJs } from '../runtime/
|
|
1
|
+
import { isCloudflareWorkers, isNodeJs } from '../runtime/env.js';
|
|
2
|
+
function unusable(name, prop = 'algorithm.name') {
|
|
3
|
+
return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
4
|
+
}
|
|
5
|
+
function isAlgorithm(algorithm, name) {
|
|
6
|
+
return algorithm.name === name;
|
|
7
|
+
}
|
|
2
8
|
function getHashLength(hash) {
|
|
3
|
-
return parseInt(hash
|
|
9
|
+
return parseInt(hash.name.substr(4), 10);
|
|
4
10
|
}
|
|
5
11
|
function getNamedCurve(alg) {
|
|
6
12
|
switch (alg) {
|
|
@@ -10,6 +16,8 @@ function getNamedCurve(alg) {
|
|
|
10
16
|
return 'P-384';
|
|
11
17
|
case 'ES512':
|
|
12
18
|
return 'P-521';
|
|
19
|
+
default:
|
|
20
|
+
throw new Error('unreachable');
|
|
13
21
|
}
|
|
14
22
|
}
|
|
15
23
|
function checkUsage(key, usages) {
|
|
@@ -33,65 +41,55 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
33
41
|
case 'HS256':
|
|
34
42
|
case 'HS384':
|
|
35
43
|
case 'HS512': {
|
|
36
|
-
if (key.algorithm
|
|
37
|
-
throw
|
|
38
|
-
}
|
|
44
|
+
if (!isAlgorithm(key.algorithm, 'HMAC'))
|
|
45
|
+
throw unusable('HMAC');
|
|
39
46
|
const expected = parseInt(alg.substr(2), 10);
|
|
40
47
|
const actual = getHashLength(key.algorithm.hash);
|
|
41
|
-
if (actual !== expected)
|
|
42
|
-
throw
|
|
43
|
-
}
|
|
48
|
+
if (actual !== expected)
|
|
49
|
+
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
44
50
|
break;
|
|
45
51
|
}
|
|
46
52
|
case 'RS256':
|
|
47
53
|
case 'RS384':
|
|
48
54
|
case 'RS512': {
|
|
49
|
-
if (key.algorithm
|
|
50
|
-
throw
|
|
51
|
-
}
|
|
55
|
+
if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))
|
|
56
|
+
throw unusable('RSASSA-PKCS1-v1_5');
|
|
52
57
|
const expected = parseInt(alg.substr(2), 10);
|
|
53
58
|
const actual = getHashLength(key.algorithm.hash);
|
|
54
|
-
if (actual !== expected)
|
|
55
|
-
throw
|
|
56
|
-
}
|
|
59
|
+
if (actual !== expected)
|
|
60
|
+
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
57
61
|
break;
|
|
58
62
|
}
|
|
59
63
|
case 'PS256':
|
|
60
64
|
case 'PS384':
|
|
61
65
|
case 'PS512': {
|
|
62
|
-
if (key.algorithm
|
|
63
|
-
throw
|
|
64
|
-
}
|
|
66
|
+
if (!isAlgorithm(key.algorithm, 'RSA-PSS'))
|
|
67
|
+
throw unusable('RSA-PSS');
|
|
65
68
|
const expected = parseInt(alg.substr(2), 10);
|
|
66
69
|
const actual = getHashLength(key.algorithm.hash);
|
|
67
|
-
if (actual !== expected)
|
|
68
|
-
throw
|
|
69
|
-
}
|
|
70
|
+
if (actual !== expected)
|
|
71
|
+
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
70
72
|
break;
|
|
71
73
|
}
|
|
72
74
|
case isNodeJs() && 'EdDSA': {
|
|
73
|
-
if (key.algorithm.name !== 'NODE-ED25519' && key.algorithm.name !== 'NODE-ED448')
|
|
74
|
-
throw
|
|
75
|
-
}
|
|
75
|
+
if (key.algorithm.name !== 'NODE-ED25519' && key.algorithm.name !== 'NODE-ED448')
|
|
76
|
+
throw unusable('NODE-ED25519 or NODE-ED448');
|
|
76
77
|
break;
|
|
77
78
|
}
|
|
78
79
|
case isCloudflareWorkers() && 'EdDSA': {
|
|
79
|
-
if (key.algorithm
|
|
80
|
-
throw
|
|
81
|
-
}
|
|
80
|
+
if (!isAlgorithm(key.algorithm, 'NODE-ED25519'))
|
|
81
|
+
throw unusable('NODE-ED25519');
|
|
82
82
|
break;
|
|
83
83
|
}
|
|
84
84
|
case 'ES256':
|
|
85
85
|
case 'ES384':
|
|
86
86
|
case 'ES512': {
|
|
87
|
-
if (key.algorithm
|
|
88
|
-
throw
|
|
89
|
-
}
|
|
87
|
+
if (!isAlgorithm(key.algorithm, 'ECDSA'))
|
|
88
|
+
throw unusable('ECDSA');
|
|
90
89
|
const expected = getNamedCurve(alg);
|
|
91
90
|
const actual = key.algorithm.namedCurve;
|
|
92
|
-
if (actual !== expected)
|
|
93
|
-
throw
|
|
94
|
-
}
|
|
91
|
+
if (actual !== expected)
|
|
92
|
+
throw unusable(expected, 'algorithm.namedCurve');
|
|
95
93
|
break;
|
|
96
94
|
}
|
|
97
95
|
default:
|
|
@@ -104,53 +102,45 @@ export function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
104
102
|
case 'A128GCM':
|
|
105
103
|
case 'A192GCM':
|
|
106
104
|
case 'A256GCM': {
|
|
107
|
-
if (key.algorithm
|
|
108
|
-
throw
|
|
109
|
-
}
|
|
105
|
+
if (!isAlgorithm(key.algorithm, 'AES-GCM'))
|
|
106
|
+
throw unusable('AES-GCM');
|
|
110
107
|
const expected = parseInt(alg.substr(1, 3), 10);
|
|
111
108
|
const actual = key.algorithm.length;
|
|
112
|
-
if (actual !== expected)
|
|
113
|
-
throw
|
|
114
|
-
}
|
|
109
|
+
if (actual !== expected)
|
|
110
|
+
throw unusable(expected, 'algorithm.length');
|
|
115
111
|
break;
|
|
116
112
|
}
|
|
117
113
|
case 'A128KW':
|
|
118
114
|
case 'A192KW':
|
|
119
115
|
case 'A256KW': {
|
|
120
|
-
if (key.algorithm
|
|
121
|
-
throw
|
|
122
|
-
}
|
|
116
|
+
if (!isAlgorithm(key.algorithm, 'AES-KW'))
|
|
117
|
+
throw unusable('AES-KW');
|
|
123
118
|
const expected = parseInt(alg.substr(1, 3), 10);
|
|
124
119
|
const actual = key.algorithm.length;
|
|
125
|
-
if (actual !== expected)
|
|
126
|
-
throw
|
|
127
|
-
}
|
|
120
|
+
if (actual !== expected)
|
|
121
|
+
throw unusable(expected, 'algorithm.length');
|
|
128
122
|
break;
|
|
129
123
|
}
|
|
130
124
|
case 'ECDH-ES':
|
|
131
|
-
if (key.algorithm
|
|
132
|
-
throw
|
|
133
|
-
}
|
|
125
|
+
if (!isAlgorithm(key.algorithm, 'ECDH'))
|
|
126
|
+
throw unusable('ECDH');
|
|
134
127
|
break;
|
|
135
128
|
case 'PBES2-HS256+A128KW':
|
|
136
129
|
case 'PBES2-HS384+A192KW':
|
|
137
130
|
case 'PBES2-HS512+A256KW':
|
|
138
|
-
if (key.algorithm
|
|
139
|
-
throw
|
|
140
|
-
}
|
|
131
|
+
if (!isAlgorithm(key.algorithm, 'PBKDF2'))
|
|
132
|
+
throw unusable('PBKDF2');
|
|
141
133
|
break;
|
|
142
134
|
case 'RSA-OAEP':
|
|
143
135
|
case 'RSA-OAEP-256':
|
|
144
136
|
case 'RSA-OAEP-384':
|
|
145
137
|
case 'RSA-OAEP-512': {
|
|
146
|
-
if (key.algorithm
|
|
147
|
-
throw
|
|
148
|
-
}
|
|
138
|
+
if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))
|
|
139
|
+
throw unusable('RSA-OAEP');
|
|
149
140
|
const expected = parseInt(alg.substr(9), 10) || 1;
|
|
150
141
|
const actual = getHashLength(key.algorithm.hash);
|
|
151
|
-
if (actual !== expected)
|
|
152
|
-
throw
|
|
153
|
-
}
|
|
142
|
+
if (actual !== expected)
|
|
143
|
+
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
154
144
|
break;
|
|
155
145
|
}
|
|
156
146
|
default:
|
|
@@ -2,13 +2,13 @@ import { unwrap as aesKw } from '../runtime/aeskw.js';
|
|
|
2
2
|
import * as ECDH from '../runtime/ecdhes.js';
|
|
3
3
|
import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js';
|
|
4
4
|
import { decrypt as rsaEs } from '../runtime/rsaes.js';
|
|
5
|
-
import { unwrap as aesGcmKw } from '../runtime/aesgcmkw.js';
|
|
6
5
|
import { decode as base64url } from '../runtime/base64url.js';
|
|
7
6
|
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
|
|
8
7
|
import { bitLength as cekLength } from '../lib/cek.js';
|
|
9
8
|
import { importJWK } from '../key/import.js';
|
|
10
9
|
import checkKeyType from './check_key_type.js';
|
|
11
10
|
import isObject from './is_object.js';
|
|
11
|
+
import { unwrap as aesGcmKw } from './aesgcmkw.js';
|
|
12
12
|
async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
13
13
|
checkKeyType(alg, key, 'decrypt');
|
|
14
14
|
switch (alg) {
|
|
@@ -2,12 +2,12 @@ import { wrap as aesKw } from '../runtime/aeskw.js';
|
|
|
2
2
|
import * as ECDH from '../runtime/ecdhes.js';
|
|
3
3
|
import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js';
|
|
4
4
|
import { encrypt as rsaEs } from '../runtime/rsaes.js';
|
|
5
|
-
import { wrap as aesGcmKw } from '../runtime/aesgcmkw.js';
|
|
6
5
|
import { encode as base64url } from '../runtime/base64url.js';
|
|
7
6
|
import generateCek, { bitLength as cekLength } from '../lib/cek.js';
|
|
8
7
|
import { JOSENotSupported } from '../util/errors.js';
|
|
9
8
|
import { exportJWK } from '../key/export.js';
|
|
10
9
|
import checkKeyType from './check_key_type.js';
|
|
10
|
+
import { wrap as aesGcmKw } from './aesgcmkw.js';
|
|
11
11
|
async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
|
|
12
12
|
let encryptedKey;
|
|
13
13
|
let parameters;
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import bogusWebCrypto from './bogus.js';
|
|
2
2
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
3
3
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
4
|
-
import invalidKeyInput from '
|
|
4
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
5
5
|
function checkKeySize(key, alg) {
|
|
6
6
|
if (key.algorithm.length !== parseInt(alg.substr(1, 3), 10)) {
|
|
7
7
|
throw new TypeError(`Invalid key size for alg: ${alg}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { isCloudflareWorkers, isNodeJs } from './env.js';
|
|
2
2
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
3
|
-
import invalidKeyInput from '
|
|
3
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
4
4
|
import { encodeBase64 } from './base64url.js';
|
|
5
5
|
import formatPEM from '../lib/format_pem.js';
|
|
6
6
|
import { JOSENotSupported } from '../util/errors.js';
|
|
@@ -54,8 +54,7 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
|
54
54
|
var _a;
|
|
55
55
|
let algorithm;
|
|
56
56
|
let keyUsages;
|
|
57
|
-
const keyData = new Uint8Array(
|
|
58
|
-
.atob(pem.replace(replace, ''))
|
|
57
|
+
const keyData = new Uint8Array(atob(pem.replace(replace, ''))
|
|
59
58
|
.split('')
|
|
60
59
|
.map((c) => c.charCodeAt(0)));
|
|
61
60
|
const isPublic = keyFormat === 'spki';
|
|
@@ -63,13 +62,13 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
|
63
62
|
case 'PS256':
|
|
64
63
|
case 'PS384':
|
|
65
64
|
case 'PS512':
|
|
66
|
-
algorithm = { name: 'RSA-PSS', hash:
|
|
65
|
+
algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.substr(-3)}` };
|
|
67
66
|
keyUsages = isPublic ? ['verify'] : ['sign'];
|
|
68
67
|
break;
|
|
69
68
|
case 'RS256':
|
|
70
69
|
case 'RS384':
|
|
71
70
|
case 'RS512':
|
|
72
|
-
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash:
|
|
71
|
+
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.substr(-3)}` };
|
|
73
72
|
keyUsages = isPublic ? ['verify'] : ['sign'];
|
|
74
73
|
break;
|
|
75
74
|
case 'RSA-OAEP':
|
|
@@ -78,7 +77,7 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
|
78
77
|
case 'RSA-OAEP-512':
|
|
79
78
|
algorithm = {
|
|
80
79
|
name: 'RSA-OAEP',
|
|
81
|
-
hash:
|
|
80
|
+
hash: `SHA-${parseInt(alg.substr(-3), 10) || 1}`,
|
|
82
81
|
};
|
|
83
82
|
keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'];
|
|
84
83
|
break;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { encoder, decoder } from '../lib/buffer_utils.js';
|
|
2
|
-
import globalThis from './global.js';
|
|
3
2
|
export const encodeBase64 = (input) => {
|
|
4
3
|
let unencoded = input;
|
|
5
4
|
if (typeof unencoded === 'string') {
|
|
@@ -10,14 +9,13 @@ export const encodeBase64 = (input) => {
|
|
|
10
9
|
for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) {
|
|
11
10
|
arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE)));
|
|
12
11
|
}
|
|
13
|
-
return
|
|
12
|
+
return btoa(arr.join(''));
|
|
14
13
|
};
|
|
15
14
|
export const encode = (input) => {
|
|
16
15
|
return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
17
16
|
};
|
|
18
17
|
export const decodeBase64 = (encoded) => {
|
|
19
|
-
return new Uint8Array(
|
|
20
|
-
.atob(encoded)
|
|
18
|
+
return new Uint8Array(atob(encoded)
|
|
21
19
|
.split('')
|
|
22
20
|
.map((c) => c.charCodeAt(0)));
|
|
23
21
|
};
|
|
@@ -5,7 +5,7 @@ import timingSafeEqual from './timing_safe_equal.js';
|
|
|
5
5
|
import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js';
|
|
6
6
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
7
7
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
8
|
-
import invalidKeyInput from '
|
|
8
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
9
9
|
async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
10
10
|
if (!(cek instanceof Uint8Array)) {
|
|
11
11
|
throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
|
|
@@ -13,7 +13,7 @@ async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
13
13
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
14
14
|
const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['decrypt']);
|
|
15
15
|
const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {
|
|
16
|
-
hash:
|
|
16
|
+
hash: `SHA-${keySize << 1}`,
|
|
17
17
|
name: 'HMAC',
|
|
18
18
|
}, false, ['sign']);
|
|
19
19
|
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
|
|
@@ -2,7 +2,7 @@ import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buf
|
|
|
2
2
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
3
3
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
4
4
|
import digest from './digest.js';
|
|
5
|
-
import invalidKeyInput from '
|
|
5
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
6
6
|
export const deriveKey = async (publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) => {
|
|
7
7
|
if (!isCryptoKey(publicKey)) {
|
|
8
8
|
throw new TypeError(invalidKeyInput(publicKey, 'CryptoKey'));
|
|
@@ -3,7 +3,7 @@ import checkIvLength from '../lib/check_iv_length.js';
|
|
|
3
3
|
import checkCekLength from './check_cek_length.js';
|
|
4
4
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
5
5
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
6
|
-
import invalidKeyInput from '
|
|
6
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
7
7
|
import { JOSENotSupported } from '../util/errors.js';
|
|
8
8
|
async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
9
9
|
if (!(cek instanceof Uint8Array)) {
|
|
@@ -12,7 +12,7 @@ async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
12
12
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
13
13
|
const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['encrypt']);
|
|
14
14
|
const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {
|
|
15
|
-
hash:
|
|
15
|
+
hash: `SHA-${keySize << 1}`,
|
|
16
16
|
name: 'HMAC',
|
|
17
17
|
}, false, ['sign']);
|
|
18
18
|
const ciphertext = new Uint8Array(await crypto.subtle.encrypt({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JOSEError, JWKSTimeout } from '../util/errors.js';
|
|
2
|
-
import
|
|
2
|
+
import { isCloudflareWorkers } from './env.js';
|
|
3
3
|
const fetchJwks = async (url, timeout) => {
|
|
4
4
|
let controller;
|
|
5
5
|
let id;
|
|
@@ -11,8 +11,7 @@ const fetchJwks = async (url, timeout) => {
|
|
|
11
11
|
controller.abort();
|
|
12
12
|
}, timeout);
|
|
13
13
|
}
|
|
14
|
-
const response = await
|
|
15
|
-
.fetch(url.href, {
|
|
14
|
+
const response = await fetch(url.href, {
|
|
16
15
|
signal: controller ? controller.signal : undefined,
|
|
17
16
|
redirect: 'manual',
|
|
18
17
|
method: 'GET',
|
|
@@ -23,8 +22,7 @@ const fetchJwks = async (url, timeout) => {
|
|
|
23
22
|
mode: 'cors',
|
|
24
23
|
}
|
|
25
24
|
: undefined),
|
|
26
|
-
})
|
|
27
|
-
.catch((err) => {
|
|
25
|
+
}).catch((err) => {
|
|
28
26
|
if (timedOut)
|
|
29
27
|
throw new JWKSTimeout();
|
|
30
28
|
throw err;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers, isNodeJs } from './
|
|
1
|
+
import { isCloudflareWorkers, isNodeJs } from './env.js';
|
|
2
2
|
import crypto from './webcrypto.js';
|
|
3
3
|
import { JOSENotSupported } from '../util/errors.js';
|
|
4
4
|
import random from './random.js';
|
|
@@ -12,7 +12,7 @@ export async function generateSecret(alg, options) {
|
|
|
12
12
|
case 'HS384':
|
|
13
13
|
case 'HS512':
|
|
14
14
|
length = parseInt(alg.substr(-3), 10);
|
|
15
|
-
algorithm = { name: 'HMAC', hash:
|
|
15
|
+
algorithm = { name: 'HMAC', hash: `SHA-${length}`, length };
|
|
16
16
|
keyUsages = ['sign', 'verify'];
|
|
17
17
|
break;
|
|
18
18
|
case 'A128CBC-HS256':
|
|
@@ -60,7 +60,7 @@ export async function generateKeyPair(alg, options) {
|
|
|
60
60
|
case 'PS512':
|
|
61
61
|
algorithm = {
|
|
62
62
|
name: 'RSA-PSS',
|
|
63
|
-
hash:
|
|
63
|
+
hash: `SHA-${alg.substr(-3)}`,
|
|
64
64
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
65
65
|
modulusLength: getModulusLengthOption(options),
|
|
66
66
|
};
|
|
@@ -71,7 +71,7 @@ export async function generateKeyPair(alg, options) {
|
|
|
71
71
|
case 'RS512':
|
|
72
72
|
algorithm = {
|
|
73
73
|
name: 'RSASSA-PKCS1-v1_5',
|
|
74
|
-
hash:
|
|
74
|
+
hash: `SHA-${alg.substr(-3)}`,
|
|
75
75
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
76
76
|
modulusLength: getModulusLengthOption(options),
|
|
77
77
|
};
|
|
@@ -83,7 +83,7 @@ export async function generateKeyPair(alg, options) {
|
|
|
83
83
|
case 'RSA-OAEP-512':
|
|
84
84
|
algorithm = {
|
|
85
85
|
name: 'RSA-OAEP',
|
|
86
|
-
hash:
|
|
86
|
+
hash: `SHA-${parseInt(alg.substr(-3), 10) || 1}`,
|
|
87
87
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
88
88
|
modulusLength: getModulusLengthOption(options),
|
|
89
89
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
2
2
|
import { checkSigCryptoKey } from '../lib/crypto_key.js';
|
|
3
|
-
import invalidKeyInput from '
|
|
3
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
4
4
|
export default function getCryptoKey(alg, key, usage) {
|
|
5
5
|
if (isCryptoKey(key)) {
|
|
6
6
|
checkSigCryptoKey(key, alg, usage);
|
|
@@ -10,7 +10,7 @@ export default function getCryptoKey(alg, key, usage) {
|
|
|
10
10
|
if (!alg.startsWith('HS')) {
|
|
11
11
|
throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
|
|
12
12
|
}
|
|
13
|
-
return crypto.subtle.importKey('raw', key, { hash:
|
|
13
|
+
return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.substr(-3)}`, name: 'HMAC' }, false, [usage]);
|
|
14
14
|
}
|
|
15
15
|
throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'Uint8Array'));
|
|
16
16
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers, isNodeJs } from './
|
|
1
|
+
import { isCloudflareWorkers, isNodeJs } from './env.js';
|
|
2
2
|
import crypto from './webcrypto.js';
|
|
3
3
|
import { JOSENotSupported } from '../util/errors.js';
|
|
4
4
|
import { decode as base64url } from './base64url.js';
|
|
@@ -11,7 +11,7 @@ function subtleMapping(jwk) {
|
|
|
11
11
|
case 'HS256':
|
|
12
12
|
case 'HS384':
|
|
13
13
|
case 'HS512':
|
|
14
|
-
algorithm = { name: 'HMAC', hash:
|
|
14
|
+
algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.substr(-3)}` };
|
|
15
15
|
keyUsages = ['sign', 'verify'];
|
|
16
16
|
break;
|
|
17
17
|
case 'A128CBC-HS256':
|
|
@@ -49,13 +49,13 @@ function subtleMapping(jwk) {
|
|
|
49
49
|
case 'PS256':
|
|
50
50
|
case 'PS384':
|
|
51
51
|
case 'PS512':
|
|
52
|
-
algorithm = { name: 'RSA-PSS', hash:
|
|
52
|
+
algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.substr(-3)}` };
|
|
53
53
|
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
54
54
|
break;
|
|
55
55
|
case 'RS256':
|
|
56
56
|
case 'RS384':
|
|
57
57
|
case 'RS512':
|
|
58
|
-
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash:
|
|
58
|
+
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.substr(-3)}` };
|
|
59
59
|
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
60
60
|
break;
|
|
61
61
|
case 'RSA-OAEP':
|
|
@@ -64,7 +64,7 @@ function subtleMapping(jwk) {
|
|
|
64
64
|
case 'RSA-OAEP-512':
|
|
65
65
|
algorithm = {
|
|
66
66
|
name: 'RSA-OAEP',
|
|
67
|
-
hash:
|
|
67
|
+
hash: `SHA-${parseInt(jwk.alg.substr(-3), 10) || 1}`,
|
|
68
68
|
};
|
|
69
69
|
keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];
|
|
70
70
|
break;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
2
|
-
import invalidKeyInput from '
|
|
2
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
3
3
|
import { encode as base64url } from './base64url.js';
|
|
4
4
|
const keyToJWK = async (key) => {
|
|
5
5
|
if (key instanceof Uint8Array) {
|
|
@@ -5,7 +5,7 @@ import { wrap, unwrap } from './aeskw.js';
|
|
|
5
5
|
import checkP2s from '../lib/check_p2s.js';
|
|
6
6
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
7
7
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
8
|
-
import invalidKeyInput from '
|
|
8
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
9
9
|
function getCryptoKey(key, alg) {
|
|
10
10
|
if (key instanceof Uint8Array) {
|
|
11
11
|
return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']);
|
|
@@ -16,12 +16,12 @@ function getCryptoKey(key, alg) {
|
|
|
16
16
|
}
|
|
17
17
|
throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'Uint8Array'));
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
async function deriveKey(p2s, alg, p2c, key) {
|
|
20
20
|
checkP2s(p2s);
|
|
21
21
|
const salt = concatSalt(alg, p2s);
|
|
22
22
|
const keylen = parseInt(alg.substr(13, 3), 10);
|
|
23
23
|
const subtleAlg = {
|
|
24
|
-
hash:
|
|
24
|
+
hash: `SHA-${alg.substr(8, 3)}`,
|
|
25
25
|
iterations: p2c,
|
|
26
26
|
name: 'PBKDF2',
|
|
27
27
|
salt,
|
|
@@ -31,43 +31,20 @@ export const encrypt = async (alg, key, cek, p2c = Math.floor(Math.random() * 20
|
|
|
31
31
|
name: 'AES-KW',
|
|
32
32
|
};
|
|
33
33
|
const cryptoKey = await getCryptoKey(key, alg);
|
|
34
|
-
let derived;
|
|
35
34
|
if (cryptoKey.usages.includes('deriveBits')) {
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
else if (cryptoKey.usages.includes('deriveKey')) {
|
|
39
|
-
derived = await crypto.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ['wrapKey']);
|
|
35
|
+
return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen));
|
|
40
36
|
}
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
if (cryptoKey.usages.includes('deriveKey')) {
|
|
38
|
+
return crypto.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ['wrapKey', 'unwrapKey']);
|
|
43
39
|
}
|
|
40
|
+
throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"');
|
|
41
|
+
}
|
|
42
|
+
export const encrypt = async (alg, key, cek, p2c = Math.floor(Math.random() * 2049) + 2048, p2s = random(new Uint8Array(16))) => {
|
|
43
|
+
const derived = await deriveKey(p2s, alg, p2c, key);
|
|
44
44
|
const encryptedKey = await wrap(alg.substr(-6), derived, cek);
|
|
45
45
|
return { encryptedKey, p2c, p2s: base64url(p2s) };
|
|
46
46
|
};
|
|
47
47
|
export const decrypt = async (alg, key, encryptedKey, p2c, p2s) => {
|
|
48
|
-
|
|
49
|
-
const salt = concatSalt(alg, p2s);
|
|
50
|
-
const keylen = parseInt(alg.substr(13, 3), 10);
|
|
51
|
-
const subtleAlg = {
|
|
52
|
-
hash: { name: `SHA-${alg.substr(8, 3)}` },
|
|
53
|
-
iterations: p2c,
|
|
54
|
-
name: 'PBKDF2',
|
|
55
|
-
salt,
|
|
56
|
-
};
|
|
57
|
-
const wrapAlg = {
|
|
58
|
-
length: keylen,
|
|
59
|
-
name: 'AES-KW',
|
|
60
|
-
};
|
|
61
|
-
const cryptoKey = await getCryptoKey(key, alg);
|
|
62
|
-
let derived;
|
|
63
|
-
if (cryptoKey.usages.includes('deriveBits')) {
|
|
64
|
-
derived = new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen));
|
|
65
|
-
}
|
|
66
|
-
else if (cryptoKey.usages.includes('deriveKey')) {
|
|
67
|
-
derived = await crypto.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ['unwrapKey']);
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"');
|
|
71
|
-
}
|
|
48
|
+
const derived = await deriveKey(p2s, alg, p2c, key);
|
|
72
49
|
return unwrap(alg.substr(-6), derived, encryptedKey);
|
|
73
50
|
};
|
|
@@ -3,7 +3,7 @@ import bogusWebCrypto from './bogus.js';
|
|
|
3
3
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
4
4
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
5
5
|
import checkKeyLength from './check_key_length.js';
|
|
6
|
-
import invalidKeyInput from '
|
|
6
|
+
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
7
7
|
export const encrypt = async (alg, key, cek) => {
|
|
8
8
|
if (!isCryptoKey(key)) {
|
|
9
9
|
throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
|