jose 6.1.0 → 6.1.2
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/README.md +3 -2
- package/dist/types/jwe/compact/encrypt.d.ts +4 -4
- package/dist/types/jwe/flattened/encrypt.d.ts +4 -4
- package/dist/types/jwe/general/encrypt.d.ts +9 -0
- package/dist/types/jwt/encrypt.d.ts +4 -4
- package/dist/types/types.d.ts +14 -5
- package/dist/webapi/jwe/flattened/decrypt.js +12 -12
- package/dist/webapi/jwe/flattened/encrypt.js +17 -13
- package/dist/webapi/jwe/general/decrypt.js +1 -1
- package/dist/webapi/jwe/general/encrypt.js +16 -16
- package/dist/webapi/jwk/embedded.js +1 -1
- package/dist/webapi/jwk/thumbprint.js +5 -5
- package/dist/webapi/jwks/local.js +1 -1
- package/dist/webapi/jwks/remote.js +2 -2
- package/dist/webapi/jws/flattened/sign.js +23 -17
- package/dist/webapi/jws/flattened/verify.js +13 -9
- package/dist/webapi/jws/general/verify.js +1 -1
- package/dist/webapi/key/export.js +1 -1
- package/dist/webapi/key/generate_key_pair.js +3 -3
- package/dist/webapi/key/import.js +5 -5
- package/dist/webapi/lib/aesgcmkw.js +4 -4
- package/dist/webapi/lib/asn1.js +3 -7
- package/dist/webapi/lib/buffer_utils.js +11 -0
- package/dist/webapi/lib/cek.js +2 -2
- package/dist/webapi/lib/check_cek_length.js +2 -2
- package/dist/webapi/lib/check_iv_length.js +2 -2
- package/dist/webapi/lib/check_key_length.js +2 -2
- package/dist/webapi/lib/check_key_type.js +13 -17
- package/dist/webapi/lib/crypto_key.js +2 -6
- package/dist/webapi/lib/decrypt.js +7 -7
- package/dist/webapi/lib/decrypt_key_management.js +4 -4
- package/dist/webapi/lib/digest.js +2 -2
- package/dist/webapi/lib/ecdhes.js +5 -5
- package/dist/webapi/lib/encrypt.js +8 -8
- package/dist/webapi/lib/encrypt_key_management.js +4 -4
- package/dist/webapi/lib/get_sign_verify_key.js +3 -3
- package/dist/webapi/lib/invalid_key_input.js +2 -6
- package/dist/webapi/lib/is_disjoint.js +2 -2
- package/dist/webapi/lib/is_jwk.js +6 -14
- package/dist/webapi/lib/is_key_like.js +11 -8
- package/dist/webapi/lib/is_object.js +3 -5
- package/dist/webapi/lib/iv.js +1 -1
- package/dist/webapi/lib/jwk_to_key.js +2 -2
- package/dist/webapi/lib/jwt_claims_set.js +59 -6
- package/dist/webapi/lib/key_to_jwk.js +2 -2
- package/dist/webapi/lib/normalize_key.js +4 -4
- package/dist/webapi/lib/pbes2kw.js +5 -3
- package/dist/webapi/lib/rsaes.js +1 -1
- package/dist/webapi/lib/sign.js +6 -6
- package/dist/webapi/lib/subtle_dsa.js +2 -2
- package/dist/webapi/lib/validate_algorithms.js +2 -2
- package/dist/webapi/lib/validate_crit.js +2 -2
- package/dist/webapi/lib/verify.js +6 -6
- package/dist/webapi/util/base64url.js +1 -1
- package/dist/webapi/util/decode_jwt.js +1 -1
- package/dist/webapi/util/decode_protected_header.js +1 -1
- package/package.json +1 -1
- package/dist/webapi/lib/epoch.js +0 -1
- package/dist/webapi/lib/secs.js +0 -55
package/dist/webapi/lib/cek.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JOSENotSupported } from '../util/errors.js';
|
|
2
|
-
export function
|
|
2
|
+
export function cekLength(alg) {
|
|
3
3
|
switch (alg) {
|
|
4
4
|
case 'A128GCM':
|
|
5
5
|
return 128;
|
|
@@ -16,4 +16,4 @@ export function bitLength(alg) {
|
|
|
16
16
|
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
export
|
|
19
|
+
export const generateCek = (alg) => crypto.getRandomValues(new Uint8Array(cekLength(alg) >> 3));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JWEInvalid } from '../util/errors.js';
|
|
2
|
-
export
|
|
2
|
+
export function checkCekLength(cek, expected) {
|
|
3
3
|
const actual = cek.byteLength << 3;
|
|
4
4
|
if (actual !== expected) {
|
|
5
5
|
throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`);
|
|
6
6
|
}
|
|
7
|
-
}
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JWEInvalid } from '../util/errors.js';
|
|
2
2
|
import { bitLength } from './iv.js';
|
|
3
|
-
export
|
|
3
|
+
export function checkIvLength(enc, iv) {
|
|
4
4
|
if (iv.length << 3 !== bitLength(enc)) {
|
|
5
5
|
throw new JWEInvalid('Invalid Initialization Vector length');
|
|
6
6
|
}
|
|
7
|
-
}
|
|
7
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export
|
|
1
|
+
export function checkKeyLength(alg, key) {
|
|
2
2
|
if (alg.startsWith('RS') || alg.startsWith('PS')) {
|
|
3
3
|
const { modulusLength } = key.algorithm;
|
|
4
4
|
if (typeof modulusLength !== 'number' || modulusLength < 2048) {
|
|
5
5
|
throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
}
|
|
8
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { withAlg as invalidKeyInput } from './invalid_key_input.js';
|
|
2
|
-
import isKeyLike from './is_key_like.js';
|
|
2
|
+
import { isKeyLike } from './is_key_like.js';
|
|
3
3
|
import * as jwk from './is_jwk.js';
|
|
4
4
|
const tag = (key) => key?.[Symbol.toStringTag];
|
|
5
5
|
const jwkMatchesOp = (alg, key, usage) => {
|
|
@@ -96,8 +96,6 @@ const asymmetricTypeCheck = (alg, key, usage) => {
|
|
|
96
96
|
throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
|
|
97
97
|
case 'decrypt':
|
|
98
98
|
throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
|
|
99
|
-
default:
|
|
100
|
-
break;
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
101
|
if (key.type === 'private') {
|
|
@@ -106,21 +104,19 @@ const asymmetricTypeCheck = (alg, key, usage) => {
|
|
|
106
104
|
throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`);
|
|
107
105
|
case 'encrypt':
|
|
108
106
|
throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
|
|
109
|
-
default:
|
|
110
|
-
break;
|
|
111
107
|
}
|
|
112
108
|
}
|
|
113
109
|
};
|
|
114
|
-
export
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
110
|
+
export function checkKeyType(alg, key, usage) {
|
|
111
|
+
switch (alg.substring(0, 2)) {
|
|
112
|
+
case 'A1':
|
|
113
|
+
case 'A2':
|
|
114
|
+
case 'di':
|
|
115
|
+
case 'HS':
|
|
116
|
+
case 'PB':
|
|
117
|
+
symmetricTypeCheck(alg, key, usage);
|
|
118
|
+
break;
|
|
119
|
+
default:
|
|
120
|
+
asymmetricTypeCheck(alg, key, usage);
|
|
122
121
|
}
|
|
123
|
-
|
|
124
|
-
asymmetricTypeCheck(alg, key, usage);
|
|
125
|
-
}
|
|
126
|
-
};
|
|
122
|
+
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
4
|
-
function isAlgorithm(algorithm, name) {
|
|
5
|
-
return algorithm.name === name;
|
|
6
|
-
}
|
|
1
|
+
const unusable = (name, prop = 'algorithm.name') => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
2
|
+
const isAlgorithm = (algorithm, name) => algorithm.name === name;
|
|
7
3
|
function getHashLength(hash) {
|
|
8
4
|
return parseInt(hash.name.slice(4), 10);
|
|
9
5
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { concat, uint64be } from './buffer_utils.js';
|
|
2
|
-
import checkIvLength from './check_iv_length.js';
|
|
3
|
-
import checkCekLength from './check_cek_length.js';
|
|
2
|
+
import { checkIvLength } from './check_iv_length.js';
|
|
3
|
+
import { checkCekLength } from './check_cek_length.js';
|
|
4
4
|
import { JOSENotSupported, JWEDecryptionFailed, JWEInvalid } from '../util/errors.js';
|
|
5
5
|
import { checkEncCryptoKey } from './crypto_key.js';
|
|
6
|
-
import invalidKeyInput from './invalid_key_input.js';
|
|
6
|
+
import { invalidKeyInput } from './invalid_key_input.js';
|
|
7
7
|
import { isCryptoKey } from './is_key_like.js';
|
|
8
8
|
async function timingSafeEqual(a, b) {
|
|
9
9
|
if (!(a instanceof Uint8Array)) {
|
|
@@ -46,7 +46,7 @@ async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
46
46
|
}
|
|
47
47
|
let plaintext;
|
|
48
48
|
try {
|
|
49
|
-
plaintext = new Uint8Array(await crypto.subtle.decrypt({ iv, name: 'AES-CBC' }, encKey, ciphertext));
|
|
49
|
+
plaintext = new Uint8Array(await crypto.subtle.decrypt({ iv: iv, name: 'AES-CBC' }, encKey, ciphertext));
|
|
50
50
|
}
|
|
51
51
|
catch {
|
|
52
52
|
}
|
|
@@ -67,7 +67,7 @@ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
67
67
|
try {
|
|
68
68
|
return new Uint8Array(await crypto.subtle.decrypt({
|
|
69
69
|
additionalData: aad,
|
|
70
|
-
iv,
|
|
70
|
+
iv: iv,
|
|
71
71
|
name: 'AES-GCM',
|
|
72
72
|
tagLength: 128,
|
|
73
73
|
}, encKey, concat(ciphertext, tag)));
|
|
@@ -76,7 +76,7 @@ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
76
76
|
throw new JWEDecryptionFailed();
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
export
|
|
79
|
+
export async function decrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
80
80
|
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
81
81
|
throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'KeyObject', 'Uint8Array', 'JSON Web Key'));
|
|
82
82
|
}
|
|
@@ -103,4 +103,4 @@ export default async (enc, cek, ciphertext, iv, tag, aad) => {
|
|
|
103
103
|
default:
|
|
104
104
|
throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
|
|
105
105
|
}
|
|
106
|
-
}
|
|
106
|
+
}
|
|
@@ -4,12 +4,12 @@ import * as pbes2kw from './pbes2kw.js';
|
|
|
4
4
|
import * as rsaes from './rsaes.js';
|
|
5
5
|
import { decode as b64u } from '../util/base64url.js';
|
|
6
6
|
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
|
|
7
|
-
import {
|
|
7
|
+
import { cekLength } from '../lib/cek.js';
|
|
8
8
|
import { importJWK } from '../key/import.js';
|
|
9
|
-
import isObject from './is_object.js';
|
|
9
|
+
import { isObject } from './is_object.js';
|
|
10
10
|
import { unwrap as aesGcmKw } from './aesgcmkw.js';
|
|
11
11
|
import { assertCryptoKey } from './is_key_like.js';
|
|
12
|
-
export
|
|
12
|
+
export async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) {
|
|
13
13
|
switch (alg) {
|
|
14
14
|
case 'dir': {
|
|
15
15
|
if (encryptedKey !== undefined)
|
|
@@ -124,4 +124,4 @@ export default async (alg, key, encryptedKey, joseHeader, options) => {
|
|
|
124
124
|
throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
-
}
|
|
127
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { encode, concat, uint32be } from './buffer_utils.js';
|
|
2
2
|
import { checkEncCryptoKey } from './crypto_key.js';
|
|
3
|
-
import digest from './digest.js';
|
|
3
|
+
import { digest } from './digest.js';
|
|
4
4
|
function lengthAndInput(input) {
|
|
5
5
|
return concat(uint32be(input.length), input);
|
|
6
6
|
}
|
|
@@ -19,14 +19,14 @@ async function concatKdf(Z, L, OtherInfo) {
|
|
|
19
19
|
}
|
|
20
20
|
return dk.slice(0, dkLen);
|
|
21
21
|
}
|
|
22
|
-
export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(
|
|
22
|
+
export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(), apv = new Uint8Array()) {
|
|
23
23
|
checkEncCryptoKey(publicKey, 'ECDH');
|
|
24
24
|
checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits');
|
|
25
|
-
const algorithmID = lengthAndInput(
|
|
25
|
+
const algorithmID = lengthAndInput(encode(algorithm));
|
|
26
26
|
const partyUInfo = lengthAndInput(apu);
|
|
27
27
|
const partyVInfo = lengthAndInput(apv);
|
|
28
28
|
const suppPubInfo = uint32be(keyLength);
|
|
29
|
-
const suppPrivInfo = new Uint8Array(
|
|
29
|
+
const suppPrivInfo = new Uint8Array();
|
|
30
30
|
const otherInfo = concat(algorithmID, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo);
|
|
31
31
|
const Z = new Uint8Array(await crypto.subtle.deriveBits({
|
|
32
32
|
name: publicKey.algorithm.name,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { concat, uint64be } from './buffer_utils.js';
|
|
2
|
-
import checkIvLength from './check_iv_length.js';
|
|
3
|
-
import checkCekLength from './check_cek_length.js';
|
|
2
|
+
import { checkIvLength } from './check_iv_length.js';
|
|
3
|
+
import { checkCekLength } from './check_cek_length.js';
|
|
4
4
|
import { checkEncCryptoKey } from './crypto_key.js';
|
|
5
|
-
import invalidKeyInput from './invalid_key_input.js';
|
|
6
|
-
import generateIv from './iv.js';
|
|
5
|
+
import { invalidKeyInput } from './invalid_key_input.js';
|
|
6
|
+
import { generateIv } from './iv.js';
|
|
7
7
|
import { JOSENotSupported } from '../util/errors.js';
|
|
8
8
|
import { isCryptoKey } from './is_key_like.js';
|
|
9
9
|
async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
@@ -17,7 +17,7 @@ async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
17
17
|
name: 'HMAC',
|
|
18
18
|
}, false, ['sign']);
|
|
19
19
|
const ciphertext = new Uint8Array(await crypto.subtle.encrypt({
|
|
20
|
-
iv,
|
|
20
|
+
iv: iv,
|
|
21
21
|
name: 'AES-CBC',
|
|
22
22
|
}, encKey, plaintext));
|
|
23
23
|
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
|
|
@@ -35,7 +35,7 @@ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
35
35
|
}
|
|
36
36
|
const encrypted = new Uint8Array(await crypto.subtle.encrypt({
|
|
37
37
|
additionalData: aad,
|
|
38
|
-
iv,
|
|
38
|
+
iv: iv,
|
|
39
39
|
name: 'AES-GCM',
|
|
40
40
|
tagLength: 128,
|
|
41
41
|
}, encKey, plaintext));
|
|
@@ -43,7 +43,7 @@ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
43
43
|
const ciphertext = encrypted.slice(0, -16);
|
|
44
44
|
return { ciphertext, tag, iv };
|
|
45
45
|
}
|
|
46
|
-
export
|
|
46
|
+
export async function encrypt(enc, plaintext, cek, iv, aad) {
|
|
47
47
|
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
48
48
|
throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'KeyObject', 'Uint8Array', 'JSON Web Key'));
|
|
49
49
|
}
|
|
@@ -71,4 +71,4 @@ export default async (enc, plaintext, cek, iv, aad) => {
|
|
|
71
71
|
default:
|
|
72
72
|
throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
|
|
73
73
|
}
|
|
74
|
-
}
|
|
74
|
+
}
|
|
@@ -3,13 +3,13 @@ import * as ecdhes from './ecdhes.js';
|
|
|
3
3
|
import * as pbes2kw from './pbes2kw.js';
|
|
4
4
|
import * as rsaes from './rsaes.js';
|
|
5
5
|
import { encode as b64u } from '../util/base64url.js';
|
|
6
|
-
import normalizeKey from './normalize_key.js';
|
|
7
|
-
import generateCek,
|
|
6
|
+
import { normalizeKey } from './normalize_key.js';
|
|
7
|
+
import { generateCek, cekLength } from '../lib/cek.js';
|
|
8
8
|
import { JOSENotSupported } from '../util/errors.js';
|
|
9
9
|
import { exportJWK } from '../key/export.js';
|
|
10
10
|
import { wrap as aesGcmKw } from './aesgcmkw.js';
|
|
11
11
|
import { assertCryptoKey } from './is_key_like.js';
|
|
12
|
-
export
|
|
12
|
+
export async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
|
|
13
13
|
let encryptedKey;
|
|
14
14
|
let parameters;
|
|
15
15
|
let cek;
|
|
@@ -89,4 +89,4 @@ export default async (alg, enc, key, providedCek, providedParameters = {}) => {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
return { cek, encryptedKey, parameters };
|
|
92
|
-
}
|
|
92
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { checkSigCryptoKey } from './crypto_key.js';
|
|
2
|
-
import invalidKeyInput from './invalid_key_input.js';
|
|
3
|
-
export
|
|
2
|
+
import { invalidKeyInput } from './invalid_key_input.js';
|
|
3
|
+
export async function getSigKey(alg, key, usage) {
|
|
4
4
|
if (key instanceof Uint8Array) {
|
|
5
5
|
if (!alg.startsWith('HS')) {
|
|
6
6
|
throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));
|
|
@@ -9,4 +9,4 @@ export default async (alg, key, usage) => {
|
|
|
9
9
|
}
|
|
10
10
|
checkSigCryptoKey(key, alg, usage);
|
|
11
11
|
return key;
|
|
12
|
-
}
|
|
12
|
+
}
|
|
@@ -23,9 +23,5 @@ function message(msg, actual, ...types) {
|
|
|
23
23
|
}
|
|
24
24
|
return msg;
|
|
25
25
|
}
|
|
26
|
-
export
|
|
27
|
-
|
|
28
|
-
};
|
|
29
|
-
export function withAlg(alg, actual, ...types) {
|
|
30
|
-
return message(`Key for the ${alg} algorithm must be `, actual, ...types);
|
|
31
|
-
}
|
|
26
|
+
export const invalidKeyInput = (actual, ...types) => message('Key must be ', actual, ...types);
|
|
27
|
+
export const withAlg = (alg, actual, ...types) => message(`Key for the ${alg} algorithm must be `, actual, ...types);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export function isDisjoint(...headers) {
|
|
2
2
|
const sources = headers.filter(Boolean);
|
|
3
3
|
if (sources.length === 0 || sources.length === 1) {
|
|
4
4
|
return true;
|
|
@@ -18,4 +18,4 @@ export default (...headers) => {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
return true;
|
|
21
|
-
}
|
|
21
|
+
}
|
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
import isObject from './is_object.js';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
((key.kty === 'AKP' && typeof key.priv === 'string') || typeof key.d === 'string'));
|
|
8
|
-
}
|
|
9
|
-
export function isPublicJWK(key) {
|
|
10
|
-
return key.kty !== 'oct' && typeof key.d === 'undefined' && typeof key.priv === 'undefined';
|
|
11
|
-
}
|
|
12
|
-
export function isSecretJWK(key) {
|
|
13
|
-
return key.kty === 'oct' && typeof key.k === 'string';
|
|
14
|
-
}
|
|
1
|
+
import { isObject } from './is_object.js';
|
|
2
|
+
export const isJWK = (key) => isObject(key) && typeof key.kty === 'string';
|
|
3
|
+
export const isPrivateJWK = (key) => key.kty !== 'oct' &&
|
|
4
|
+
((key.kty === 'AKP' && typeof key.priv === 'string') || typeof key.d === 'string');
|
|
5
|
+
export const isPublicJWK = (key) => key.kty !== 'oct' && key.d === undefined && key.priv === undefined;
|
|
6
|
+
export const isSecretJWK = (key) => key.kty === 'oct' && typeof key.k === 'string';
|
|
@@ -3,12 +3,15 @@ export function assertCryptoKey(key) {
|
|
|
3
3
|
throw new Error('CryptoKey instance expected');
|
|
4
4
|
}
|
|
5
5
|
}
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
export const isCryptoKey = (key) => {
|
|
7
|
+
if (key?.[Symbol.toStringTag] === 'CryptoKey')
|
|
8
|
+
return true;
|
|
9
|
+
try {
|
|
10
|
+
return key instanceof CryptoKey;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
14
15
|
};
|
|
16
|
+
export const isKeyObject = (key) => key?.[Symbol.toStringTag] === 'KeyObject';
|
|
17
|
+
export const isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
4
|
-
export default (input) => {
|
|
1
|
+
const isObjectLike = (value) => typeof value === 'object' && value !== null;
|
|
2
|
+
export function isObject(input) {
|
|
5
3
|
if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {
|
|
6
4
|
return false;
|
|
7
5
|
}
|
|
@@ -13,4 +11,4 @@ export default (input) => {
|
|
|
13
11
|
proto = Object.getPrototypeOf(proto);
|
|
14
12
|
}
|
|
15
13
|
return Object.getPrototypeOf(input) === proto;
|
|
16
|
-
}
|
|
14
|
+
}
|
package/dist/webapi/lib/iv.js
CHANGED
|
@@ -16,4 +16,4 @@ export function bitLength(alg) {
|
|
|
16
16
|
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
export
|
|
19
|
+
export const generateIv = (alg) => crypto.getRandomValues(new Uint8Array(bitLength(alg) >> 3));
|
|
@@ -95,7 +95,7 @@ function subtleMapping(jwk) {
|
|
|
95
95
|
}
|
|
96
96
|
return { algorithm, keyUsages };
|
|
97
97
|
}
|
|
98
|
-
export
|
|
98
|
+
export async function jwkToKey(jwk) {
|
|
99
99
|
if (!jwk.alg) {
|
|
100
100
|
throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
|
|
101
101
|
}
|
|
@@ -106,4 +106,4 @@ export default async (jwk) => {
|
|
|
106
106
|
}
|
|
107
107
|
delete keyData.use;
|
|
108
108
|
return crypto.subtle.importKey('jwk', keyData, algorithm, jwk.ext ?? (jwk.d || jwk.priv ? false : true), jwk.key_ops ?? keyUsages);
|
|
109
|
-
}
|
|
109
|
+
}
|
|
@@ -1,9 +1,62 @@
|
|
|
1
1
|
import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';
|
|
2
|
-
import { decoder } from './buffer_utils.js';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { encoder, decoder } from './buffer_utils.js';
|
|
3
|
+
import { isObject } from './is_object.js';
|
|
4
|
+
const epoch = (date) => Math.floor(date.getTime() / 1000);
|
|
5
|
+
const minute = 60;
|
|
6
|
+
const hour = minute * 60;
|
|
7
|
+
const day = hour * 24;
|
|
8
|
+
const week = day * 7;
|
|
9
|
+
const year = day * 365.25;
|
|
10
|
+
const REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
|
|
11
|
+
export function secs(str) {
|
|
12
|
+
const matched = REGEX.exec(str);
|
|
13
|
+
if (!matched || (matched[4] && matched[1])) {
|
|
14
|
+
throw new TypeError('Invalid time period format');
|
|
15
|
+
}
|
|
16
|
+
const value = parseFloat(matched[2]);
|
|
17
|
+
const unit = matched[3].toLowerCase();
|
|
18
|
+
let numericDate;
|
|
19
|
+
switch (unit) {
|
|
20
|
+
case 'sec':
|
|
21
|
+
case 'secs':
|
|
22
|
+
case 'second':
|
|
23
|
+
case 'seconds':
|
|
24
|
+
case 's':
|
|
25
|
+
numericDate = Math.round(value);
|
|
26
|
+
break;
|
|
27
|
+
case 'minute':
|
|
28
|
+
case 'minutes':
|
|
29
|
+
case 'min':
|
|
30
|
+
case 'mins':
|
|
31
|
+
case 'm':
|
|
32
|
+
numericDate = Math.round(value * minute);
|
|
33
|
+
break;
|
|
34
|
+
case 'hour':
|
|
35
|
+
case 'hours':
|
|
36
|
+
case 'hr':
|
|
37
|
+
case 'hrs':
|
|
38
|
+
case 'h':
|
|
39
|
+
numericDate = Math.round(value * hour);
|
|
40
|
+
break;
|
|
41
|
+
case 'day':
|
|
42
|
+
case 'days':
|
|
43
|
+
case 'd':
|
|
44
|
+
numericDate = Math.round(value * day);
|
|
45
|
+
break;
|
|
46
|
+
case 'week':
|
|
47
|
+
case 'weeks':
|
|
48
|
+
case 'w':
|
|
49
|
+
numericDate = Math.round(value * week);
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
numericDate = Math.round(value * year);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (matched[1] === '-' || matched[4] === 'ago') {
|
|
56
|
+
return -numericDate;
|
|
57
|
+
}
|
|
58
|
+
return numericDate;
|
|
59
|
+
}
|
|
7
60
|
function validateInput(label, input) {
|
|
8
61
|
if (!Number.isFinite(input)) {
|
|
9
62
|
throw new TypeError(`Invalid ${label} input`);
|
|
@@ -169,7 +222,7 @@ export class JWTClaimsBuilder {
|
|
|
169
222
|
}
|
|
170
223
|
}
|
|
171
224
|
set iat(value) {
|
|
172
|
-
if (
|
|
225
|
+
if (value === undefined) {
|
|
173
226
|
this.#payload.iat = epoch(new Date());
|
|
174
227
|
}
|
|
175
228
|
else if (value instanceof Date) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import invalidKeyInput from './invalid_key_input.js';
|
|
1
|
+
import { invalidKeyInput } from './invalid_key_input.js';
|
|
2
2
|
import { encode as b64u } from '../util/base64url.js';
|
|
3
3
|
import { isCryptoKey, isKeyObject } from './is_key_like.js';
|
|
4
|
-
export
|
|
4
|
+
export async function keyToJWK(key) {
|
|
5
5
|
if (isKeyObject(key)) {
|
|
6
6
|
if (key.type === 'secret') {
|
|
7
7
|
key = key.export();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isJWK } from './is_jwk.js';
|
|
2
2
|
import { decode } from '../util/base64url.js';
|
|
3
|
-
import
|
|
3
|
+
import { jwkToKey } from './jwk_to_key.js';
|
|
4
4
|
import { isCryptoKey, isKeyObject } from './is_key_like.js';
|
|
5
5
|
let cache;
|
|
6
6
|
const handleJWK = async (key, jwk, alg, freeze = false) => {
|
|
@@ -9,7 +9,7 @@ const handleJWK = async (key, jwk, alg, freeze = false) => {
|
|
|
9
9
|
if (cached?.[alg]) {
|
|
10
10
|
return cached[alg];
|
|
11
11
|
}
|
|
12
|
-
const cryptoKey = await
|
|
12
|
+
const cryptoKey = await jwkToKey({ ...jwk, alg });
|
|
13
13
|
if (freeze)
|
|
14
14
|
Object.freeze(key);
|
|
15
15
|
if (!cached) {
|
|
@@ -142,7 +142,7 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
142
142
|
}
|
|
143
143
|
return cryptoKey;
|
|
144
144
|
};
|
|
145
|
-
export
|
|
145
|
+
export async function normalizeKey(key, alg) {
|
|
146
146
|
if (key instanceof Uint8Array) {
|
|
147
147
|
return key;
|
|
148
148
|
}
|
|
@@ -173,4 +173,4 @@ export default async (key, alg) => {
|
|
|
173
173
|
return handleJWK(key, key, alg, true);
|
|
174
174
|
}
|
|
175
175
|
throw new Error('unreachable');
|
|
176
|
-
}
|
|
176
|
+
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { encode as b64u } from '../util/base64url.js';
|
|
2
2
|
import * as aeskw from './aeskw.js';
|
|
3
3
|
import { checkEncCryptoKey } from './crypto_key.js';
|
|
4
|
-
import { concat,
|
|
4
|
+
import { concat, encode } from './buffer_utils.js';
|
|
5
5
|
import { JWEInvalid } from '../util/errors.js';
|
|
6
6
|
function getCryptoKey(key, alg) {
|
|
7
7
|
if (key instanceof Uint8Array) {
|
|
8
|
-
return crypto.subtle.importKey('raw', key, 'PBKDF2', false, [
|
|
8
|
+
return crypto.subtle.importKey('raw', key, 'PBKDF2', false, [
|
|
9
|
+
'deriveBits',
|
|
10
|
+
]);
|
|
9
11
|
}
|
|
10
12
|
checkEncCryptoKey(key, alg, 'deriveBits');
|
|
11
13
|
return key;
|
|
12
14
|
}
|
|
13
|
-
const concatSalt = (alg, p2sInput) => concat(
|
|
15
|
+
const concatSalt = (alg, p2sInput) => concat(encode(alg), Uint8Array.of(0x00), p2sInput);
|
|
14
16
|
async function deriveKey(p2s, alg, p2c, key) {
|
|
15
17
|
if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
|
|
16
18
|
throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets');
|
package/dist/webapi/lib/rsaes.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { checkEncCryptoKey } from './crypto_key.js';
|
|
2
|
-
import checkKeyLength from './check_key_length.js';
|
|
2
|
+
import { checkKeyLength } from './check_key_length.js';
|
|
3
3
|
import { JOSENotSupported } from '../util/errors.js';
|
|
4
4
|
const subtleAlgorithm = (alg) => {
|
|
5
5
|
switch (alg) {
|
package/dist/webapi/lib/sign.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import subtleAlgorithm from './subtle_dsa.js';
|
|
2
|
-
import checkKeyLength from './check_key_length.js';
|
|
3
|
-
import
|
|
4
|
-
export
|
|
5
|
-
const cryptoKey = await
|
|
1
|
+
import { subtleAlgorithm } from './subtle_dsa.js';
|
|
2
|
+
import { checkKeyLength } from './check_key_length.js';
|
|
3
|
+
import { getSigKey } from './get_sign_verify_key.js';
|
|
4
|
+
export async function sign(alg, key, data) {
|
|
5
|
+
const cryptoKey = await getSigKey(alg, key, 'sign');
|
|
6
6
|
checkKeyLength(alg, cryptoKey);
|
|
7
7
|
const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data);
|
|
8
8
|
return new Uint8Array(signature);
|
|
9
|
-
}
|
|
9
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JOSENotSupported } from '../util/errors.js';
|
|
2
|
-
export
|
|
2
|
+
export function subtleAlgorithm(alg, algorithm) {
|
|
3
3
|
const hash = `SHA-${alg.slice(-3)}`;
|
|
4
4
|
switch (alg) {
|
|
5
5
|
case 'HS256':
|
|
@@ -28,4 +28,4 @@ export default (alg, algorithm) => {
|
|
|
28
28
|
default:
|
|
29
29
|
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
|
|
30
30
|
}
|
|
31
|
-
}
|
|
31
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export function validateAlgorithms(option, algorithms) {
|
|
2
2
|
if (algorithms !== undefined &&
|
|
3
3
|
(!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {
|
|
4
4
|
throw new TypeError(`"${option}" option must be an array of strings`);
|
|
@@ -7,4 +7,4 @@ export default (option, algorithms) => {
|
|
|
7
7
|
return undefined;
|
|
8
8
|
}
|
|
9
9
|
return new Set(algorithms);
|
|
10
|
-
}
|
|
10
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.js';
|
|
2
|
-
export
|
|
2
|
+
export function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
|
|
3
3
|
if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {
|
|
4
4
|
throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
|
|
5
5
|
}
|
|
@@ -30,4 +30,4 @@ export default (Err, recognizedDefault, recognizedOption, protectedHeader, joseH
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
return new Set(protectedHeader.crit);
|
|
33
|
-
}
|
|
33
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import subtleAlgorithm from './subtle_dsa.js';
|
|
2
|
-
import checkKeyLength from './check_key_length.js';
|
|
3
|
-
import
|
|
4
|
-
export
|
|
5
|
-
const cryptoKey = await
|
|
1
|
+
import { subtleAlgorithm } from './subtle_dsa.js';
|
|
2
|
+
import { checkKeyLength } from './check_key_length.js';
|
|
3
|
+
import { getSigKey } from './get_sign_verify_key.js';
|
|
4
|
+
export async function verify(alg, key, signature, data) {
|
|
5
|
+
const cryptoKey = await getSigKey(alg, key, 'verify');
|
|
6
6
|
checkKeyLength(alg, cryptoKey);
|
|
7
7
|
const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm);
|
|
8
8
|
try {
|
|
@@ -11,4 +11,4 @@ export default async (alg, key, signature, data) => {
|
|
|
11
11
|
catch {
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
|
-
}
|
|
14
|
+
}
|