jose 6.0.13 → 6.1.1
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 +40 -11
- 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 +10 -5
- package/dist/webapi/jwks/local.js +4 -2
- 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 +10 -3
- package/dist/webapi/key/import.js +13 -3
- package/dist/webapi/lib/aesgcmkw.js +4 -4
- package/dist/webapi/lib/asn1.js +9 -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 +9 -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 -13
- package/dist/webapi/lib/is_key_like.js +3 -9
- 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 +19 -4
- package/dist/webapi/lib/jwt_claims_set.js +59 -6
- package/dist/webapi/lib/key_to_jwk.js +6 -2
- package/dist/webapi/lib/normalize_key.js +16 -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 +6 -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 +4 -2
- package/dist/webapi/lib/epoch.js +0 -1
- package/dist/webapi/lib/secs.js +0 -55
|
@@ -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();
|
|
@@ -23,5 +23,9 @@ export default async function keyToJWK(key) {
|
|
|
23
23
|
throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK');
|
|
24
24
|
}
|
|
25
25
|
const { ext, key_ops, alg, use, ...jwk } = await crypto.subtle.exportKey('jwk', key);
|
|
26
|
+
if (jwk.kty === 'AKP') {
|
|
27
|
+
;
|
|
28
|
+
jwk.alg = alg;
|
|
29
|
+
}
|
|
26
30
|
return jwk;
|
|
27
31
|
}
|
|
@@ -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) {
|
|
@@ -49,6 +49,18 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
49
49
|
isPublic ? 'verify' : 'sign',
|
|
50
50
|
]);
|
|
51
51
|
}
|
|
52
|
+
switch (keyObject.asymmetricKeyType) {
|
|
53
|
+
case 'ml-dsa-44':
|
|
54
|
+
case 'ml-dsa-65':
|
|
55
|
+
case 'ml-dsa-87': {
|
|
56
|
+
if (alg !== keyObject.asymmetricKeyType.toUpperCase()) {
|
|
57
|
+
throw new TypeError('given KeyObject instance cannot be used for this algorithm');
|
|
58
|
+
}
|
|
59
|
+
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
|
|
60
|
+
isPublic ? 'verify' : 'sign',
|
|
61
|
+
]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
52
64
|
if (keyObject.asymmetricKeyType === 'rsa') {
|
|
53
65
|
let hash;
|
|
54
66
|
switch (alg) {
|
|
@@ -130,7 +142,7 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
130
142
|
}
|
|
131
143
|
return cryptoKey;
|
|
132
144
|
};
|
|
133
|
-
export
|
|
145
|
+
export async function normalizeKey(key, alg) {
|
|
134
146
|
if (key instanceof Uint8Array) {
|
|
135
147
|
return key;
|
|
136
148
|
}
|
|
@@ -161,4 +173,4 @@ export default async (key, alg) => {
|
|
|
161
173
|
return handleJWK(key, key, alg, true);
|
|
162
174
|
}
|
|
163
175
|
throw new Error('unreachable');
|
|
164
|
-
}
|
|
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':
|
|
@@ -21,7 +21,11 @@ export default (alg, algorithm) => {
|
|
|
21
21
|
case 'Ed25519':
|
|
22
22
|
case 'EdDSA':
|
|
23
23
|
return { name: 'Ed25519' };
|
|
24
|
+
case 'ML-DSA-44':
|
|
25
|
+
case 'ML-DSA-65':
|
|
26
|
+
case 'ML-DSA-87':
|
|
27
|
+
return { name: alg };
|
|
24
28
|
default:
|
|
25
29
|
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
|
|
26
30
|
}
|
|
27
|
-
}
|
|
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
|
+
}
|
|
@@ -10,7 +10,7 @@ export function decode(input) {
|
|
|
10
10
|
if (encoded instanceof Uint8Array) {
|
|
11
11
|
encoded = decoder.decode(encoded);
|
|
12
12
|
}
|
|
13
|
-
encoded = encoded.replace(/-/g, '+').replace(/_/g, '/')
|
|
13
|
+
encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
|
|
14
14
|
try {
|
|
15
15
|
return decodeBase64(encoded);
|
|
16
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decode as b64u } from './base64url.js';
|
|
2
2
|
import { decoder } from '../lib/buffer_utils.js';
|
|
3
|
-
import isObject from '../lib/is_object.js';
|
|
3
|
+
import { isObject } from '../lib/is_object.js';
|
|
4
4
|
import { JWTInvalid } from './errors.js';
|
|
5
5
|
export function decodeJwt(jwt) {
|
|
6
6
|
if (typeof jwt !== 'string')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decode as b64u } from './base64url.js';
|
|
2
2
|
import { decoder } from '../lib/buffer_utils.js';
|
|
3
|
-
import isObject from '../lib/is_object.js';
|
|
3
|
+
import { isObject } from '../lib/is_object.js';
|
|
4
4
|
export function decodeProtectedHeader(token) {
|
|
5
5
|
let protectedB64u;
|
|
6
6
|
if (typeof token === 'string') {
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jose",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes",
|
|
5
5
|
"keywords": [
|
|
6
|
+
"akp",
|
|
6
7
|
"browser",
|
|
7
8
|
"bun",
|
|
8
9
|
"cloudflare",
|
|
@@ -29,8 +30,9 @@
|
|
|
29
30
|
"jwk",
|
|
30
31
|
"jwks",
|
|
31
32
|
"jws",
|
|
32
|
-
"jwt",
|
|
33
33
|
"jwt-decode",
|
|
34
|
+
"jwt",
|
|
35
|
+
"ml-dsa",
|
|
34
36
|
"netlify",
|
|
35
37
|
"next",
|
|
36
38
|
"nextjs",
|
package/dist/webapi/lib/epoch.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default (date) => Math.floor(date.getTime() / 1000);
|
package/dist/webapi/lib/secs.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
const minute = 60;
|
|
2
|
-
const hour = minute * 60;
|
|
3
|
-
const day = hour * 24;
|
|
4
|
-
const week = day * 7;
|
|
5
|
-
const year = day * 365.25;
|
|
6
|
-
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;
|
|
7
|
-
export default (str) => {
|
|
8
|
-
const matched = REGEX.exec(str);
|
|
9
|
-
if (!matched || (matched[4] && matched[1])) {
|
|
10
|
-
throw new TypeError('Invalid time period format');
|
|
11
|
-
}
|
|
12
|
-
const value = parseFloat(matched[2]);
|
|
13
|
-
const unit = matched[3].toLowerCase();
|
|
14
|
-
let numericDate;
|
|
15
|
-
switch (unit) {
|
|
16
|
-
case 'sec':
|
|
17
|
-
case 'secs':
|
|
18
|
-
case 'second':
|
|
19
|
-
case 'seconds':
|
|
20
|
-
case 's':
|
|
21
|
-
numericDate = Math.round(value);
|
|
22
|
-
break;
|
|
23
|
-
case 'minute':
|
|
24
|
-
case 'minutes':
|
|
25
|
-
case 'min':
|
|
26
|
-
case 'mins':
|
|
27
|
-
case 'm':
|
|
28
|
-
numericDate = Math.round(value * minute);
|
|
29
|
-
break;
|
|
30
|
-
case 'hour':
|
|
31
|
-
case 'hours':
|
|
32
|
-
case 'hr':
|
|
33
|
-
case 'hrs':
|
|
34
|
-
case 'h':
|
|
35
|
-
numericDate = Math.round(value * hour);
|
|
36
|
-
break;
|
|
37
|
-
case 'day':
|
|
38
|
-
case 'days':
|
|
39
|
-
case 'd':
|
|
40
|
-
numericDate = Math.round(value * day);
|
|
41
|
-
break;
|
|
42
|
-
case 'week':
|
|
43
|
-
case 'weeks':
|
|
44
|
-
case 'w':
|
|
45
|
-
numericDate = Math.round(value * week);
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
numericDate = Math.round(value * year);
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
if (matched[1] === '-' || matched[4] === 'ago') {
|
|
52
|
-
return -numericDate;
|
|
53
|
-
}
|
|
54
|
-
return numericDate;
|
|
55
|
-
};
|