jose 4.8.0 β 4.9.0
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 +9 -10
- package/dist/browser/index.js +1 -1
- package/dist/browser/jwe/flattened/decrypt.js +1 -1
- package/dist/browser/jwk/thumbprint.js +7 -1
- package/dist/browser/jws/flattened/verify.js +1 -1
- package/dist/browser/lib/crypto_key.js +1 -6
- package/dist/browser/runtime/asn1.js +3 -5
- package/dist/browser/runtime/env.js +0 -8
- package/dist/browser/runtime/generate.js +3 -7
- package/dist/browser/runtime/jwk_to_key.js +2 -6
- package/dist/browser/runtime/subtle_dsa.js +2 -2
- package/dist/node/cjs/index.js +2 -1
- package/dist/node/cjs/jwe/flattened/decrypt.js +1 -1
- package/dist/node/cjs/jwk/thumbprint.js +9 -2
- package/dist/node/cjs/jws/flattened/verify.js +1 -1
- package/dist/node/cjs/lib/crypto_key.js +0 -5
- package/dist/node/cjs/runtime/env.js +1 -5
- package/dist/node/cjs/runtime/key_to_jwk.js +4 -0
- package/dist/node/esm/index.js +1 -1
- package/dist/node/esm/jwe/flattened/decrypt.js +1 -1
- package/dist/node/esm/jwk/thumbprint.js +7 -1
- package/dist/node/esm/jws/flattened/verify.js +1 -1
- package/dist/node/esm/lib/crypto_key.js +1 -6
- package/dist/node/esm/runtime/env.js +0 -3
- package/dist/node/esm/runtime/key_to_jwk.js +4 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/jwe/compact/decrypt.d.ts +9 -7
- package/dist/types/jwe/compact/encrypt.d.ts +14 -20
- package/dist/types/jwe/flattened/decrypt.d.ts +12 -13
- package/dist/types/jwe/flattened/encrypt.d.ts +17 -26
- package/dist/types/jwe/general/decrypt.d.ts +13 -14
- package/dist/types/jwe/general/encrypt.d.ts +6 -15
- package/dist/types/jwk/embedded.d.ts +8 -7
- package/dist/types/jwk/thumbprint.d.ts +30 -7
- package/dist/types/jwks/local.d.ts +12 -15
- package/dist/types/jwks/remote.d.ts +22 -36
- package/dist/types/jws/compact/sign.d.ts +3 -6
- package/dist/types/jws/compact/verify.d.ts +11 -8
- package/dist/types/jws/flattened/sign.d.ts +3 -6
- package/dist/types/jws/flattened/verify.d.ts +12 -9
- package/dist/types/jws/general/sign.d.ts +7 -18
- package/dist/types/jws/general/verify.d.ts +14 -11
- package/dist/types/jwt/decrypt.d.ts +13 -12
- package/dist/types/jwt/encrypt.d.ts +15 -18
- package/dist/types/jwt/produce.d.ts +9 -14
- package/dist/types/jwt/sign.d.ts +2 -2
- package/dist/types/jwt/unsecured.d.ts +4 -4
- package/dist/types/jwt/verify.d.ts +15 -13
- package/dist/types/key/export.d.ts +13 -8
- package/dist/types/key/generate_key_pair.d.ts +14 -19
- package/dist/types/key/generate_secret.d.ts +3 -2
- package/dist/types/key/import.d.ts +50 -39
- package/dist/types/types.d.ts +196 -371
- package/dist/types/util/decode_jwt.d.ts +7 -6
- package/dist/types/util/decode_protected_header.d.ts +3 -2
- package/dist/types/util/errors.d.ts +20 -61
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@ The following specifications are implemented by `jose`
|
|
|
12
12
|
- JSON Web Algorithms (JWA) - [RFC7518][spec-jwa]
|
|
13
13
|
- JSON Web Token (JWT) - [RFC7519][spec-jwt]
|
|
14
14
|
- JSON Web Key Thumbprint - [RFC7638][spec-thumbprint]
|
|
15
|
+
- JSON Web Key Thumbprint URI - [RFC9278][spec-thumbprint-uri]
|
|
15
16
|
- JWS Unencoded Payload Option - [RFC7797][spec-b64]
|
|
16
17
|
- CFRG Elliptic Curve ECDH and Signatures - [RFC8037][spec-okp]
|
|
17
18
|
- secp256k1 EC Key curve support - [JOSE Registrations for WebAuthn Algorithms][spec-secp256k1]
|
|
@@ -19,9 +20,7 @@ The following specifications are implemented by `jose`
|
|
|
19
20
|
The test suite utilizes examples defined in [RFC7520][spec-cookbook] to confirm its JOSE
|
|
20
21
|
implementation is correct.
|
|
21
22
|
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
If you or your business use `jose`, please consider becoming a [sponsor][support-sponsor] so I can continue maintaining it and adding new features carefree.
|
|
23
|
+
## [π Help the project](https://github.com/sponsors/panva)
|
|
25
24
|
|
|
26
25
|
## Documentation
|
|
27
26
|
|
|
@@ -58,8 +57,9 @@ import * as jose from 'https://deno.land/x/jose/index.ts'
|
|
|
58
57
|
- Signing - [Compact](docs/classes/jws_compact_sign.CompactSign.md#readme), [Flattened](docs/classes/jws_flattened_sign.FlattenedSign.md#readme), [General](docs/classes/jws_general_sign.GeneralSign.md#readme)
|
|
59
58
|
- Verification - [Compact](docs/functions/jws_compact_verify.compactVerify.md#readme), [Flattened](docs/functions/jws_flattened_verify.flattenedVerify.md#readme), [General](docs/functions/jws_general_verify.generalVerify.md#readme)
|
|
60
59
|
- JSON Web Key (JWK)
|
|
61
|
-
- [
|
|
62
|
-
- [
|
|
60
|
+
- [Calculating JWK Thumbprint](docs/functions/jwk_thumbprint.calculateJwkThumbprint.md#readme)
|
|
61
|
+
- [Calculating JWK Thumbprint URI](docs/functions/jwk_thumbprint.calculateJwkThumbprintUri.md#readme)
|
|
62
|
+
- [Verification using a JWK Embedded in a JWS Header](docs/functions/jwk_embedded.EmbeddedJWK.md#readme)
|
|
63
63
|
- JSON Web Key Set (JWKS)
|
|
64
64
|
- [Verify using a local JWKSet](docs/functions/jwks_local.createLocalJWKSet.md#readme)
|
|
65
65
|
- [Verify using a remote JWKSet](docs/functions/jwks_remote.createRemoteJWKSet.md#readme)
|
|
@@ -91,10 +91,8 @@ import * as jose from 'https://deno.land/x/jose/index.ts'
|
|
|
91
91
|
|
|
92
92
|
| Version | Security Fixes π | Other Bug Fixes π | New Features β |
|
|
93
93
|
| ------- | --------- | -------- | -------- |
|
|
94
|
-
| [
|
|
95
|
-
| [
|
|
96
|
-
| [2.x.x](https://github.com/panva/jose/tree/v2.x) | β
| β
until 2022-04-30 | β |
|
|
97
|
-
| [1.x.x](https://github.com/panva/jose/tree/v1.x) | β
| β | β |
|
|
94
|
+
| [v4.x](https://github.com/panva/jose/tree/v4.x) | β
| β
| β
|
|
|
95
|
+
| [v3.x](https://github.com/panva/jose/tree/v3.x), [v2.x](https://github.com/panva/jose/tree/v2.x), [v1.x](https://github.com/panva/jose/tree/v1.x) | β
| β | β |
|
|
98
96
|
|
|
99
97
|
#### Semver?
|
|
100
98
|
|
|
@@ -108,7 +106,7 @@ import * as jose from 'https://deno.land/x/jose/index.ts'
|
|
|
108
106
|
- it supports JWK Key Format for all four key types (oct, RSA, EC and OKP)
|
|
109
107
|
- it is exclusively using native platform Key object representations (CryptoKey and KeyObject)
|
|
110
108
|
- there is JSON Web Encryption support
|
|
111
|
-
- it supports the
|
|
109
|
+
- it supports the General and Flattened JSON Serialization Syntaxes
|
|
112
110
|
- it supports the "crit" member validations to make sure extensions are handled correctly
|
|
113
111
|
|
|
114
112
|
#### How is it different from [`node-jose`](https://github.com/cisco/node-jose)?
|
|
@@ -146,6 +144,7 @@ install size should not be a cause for concern.
|
|
|
146
144
|
[spec-okp]: https://www.rfc-editor.org/rfc/rfc8037
|
|
147
145
|
[spec-secp256k1]: https://www.rfc-editor.org/rfc/rfc8812
|
|
148
146
|
[spec-thumbprint]: https://www.rfc-editor.org/rfc/rfc7638
|
|
147
|
+
[spec-thumbprint-uri]: https://www.rfc-editor.org/rfc/rfc9278
|
|
149
148
|
[support-sponsor]: https://github.com/sponsors/panva
|
|
150
149
|
[conditional-exports]: https://nodejs.org/api/packages.html#packages_conditional_exports
|
|
151
150
|
[webcrypto]: https://www.w3.org/TR/WebCryptoAPI/
|
package/dist/browser/index.js
CHANGED
|
@@ -14,7 +14,7 @@ export { FlattenedSign } from './jws/flattened/sign.js';
|
|
|
14
14
|
export { GeneralSign } from './jws/general/sign.js';
|
|
15
15
|
export { SignJWT } from './jwt/sign.js';
|
|
16
16
|
export { EncryptJWT } from './jwt/encrypt.js';
|
|
17
|
-
export { calculateJwkThumbprint } from './jwk/thumbprint.js';
|
|
17
|
+
export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.js';
|
|
18
18
|
export { EmbeddedJWK } from './jwk/embedded.js';
|
|
19
19
|
export { createLocalJWKSet } from './jwks/local.js';
|
|
20
20
|
export { createRemoteJWKSet } from './jwks/remote.js';
|
|
@@ -43,8 +43,8 @@ export async function flattenedDecrypt(jwe, key, options) {
|
|
|
43
43
|
}
|
|
44
44
|
let parsedProt;
|
|
45
45
|
if (jwe.protected) {
|
|
46
|
-
const protectedHeader = base64url(jwe.protected);
|
|
47
46
|
try {
|
|
47
|
+
const protectedHeader = base64url(jwe.protected);
|
|
48
48
|
parsedProt = JSON.parse(decoder.decode(protectedHeader));
|
|
49
49
|
}
|
|
50
50
|
catch (_b) {
|
|
@@ -8,10 +8,11 @@ const check = (value, description) => {
|
|
|
8
8
|
throw new JWKInvalid(`${description} missing or invalid`);
|
|
9
9
|
}
|
|
10
10
|
};
|
|
11
|
-
export async function calculateJwkThumbprint(jwk, digestAlgorithm
|
|
11
|
+
export async function calculateJwkThumbprint(jwk, digestAlgorithm) {
|
|
12
12
|
if (!isObject(jwk)) {
|
|
13
13
|
throw new TypeError('JWK must be an object');
|
|
14
14
|
}
|
|
15
|
+
digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256');
|
|
15
16
|
if (digestAlgorithm !== 'sha256' &&
|
|
16
17
|
digestAlgorithm !== 'sha384' &&
|
|
17
18
|
digestAlgorithm !== 'sha512') {
|
|
@@ -45,3 +46,8 @@ export async function calculateJwkThumbprint(jwk, digestAlgorithm = 'sha256') {
|
|
|
45
46
|
const data = encoder.encode(JSON.stringify(components));
|
|
46
47
|
return base64url(await digest(digestAlgorithm, data));
|
|
47
48
|
}
|
|
49
|
+
export async function calculateJwkThumbprintUri(jwk, digestAlgorithm) {
|
|
50
|
+
digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256');
|
|
51
|
+
const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm);
|
|
52
|
+
return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`;
|
|
53
|
+
}
|
|
@@ -29,8 +29,8 @@ export async function flattenedVerify(jws, key, options) {
|
|
|
29
29
|
}
|
|
30
30
|
let parsedProt = {};
|
|
31
31
|
if (jws.protected) {
|
|
32
|
-
const protectedHeader = base64url(jws.protected);
|
|
33
32
|
try {
|
|
33
|
+
const protectedHeader = base64url(jws.protected);
|
|
34
34
|
parsedProt = JSON.parse(decoder.decode(protectedHeader));
|
|
35
35
|
}
|
|
36
36
|
catch (_b) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers
|
|
1
|
+
import { isCloudflareWorkers } from '../runtime/env.js';
|
|
2
2
|
function unusable(name, prop = 'algorithm.name') {
|
|
3
3
|
return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
4
4
|
}
|
|
@@ -71,11 +71,6 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
71
71
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
72
72
|
break;
|
|
73
73
|
}
|
|
74
|
-
case isNodeJs() && 'EdDSA': {
|
|
75
|
-
if (key.algorithm.name !== 'NODE-ED25519' && key.algorithm.name !== 'NODE-ED448')
|
|
76
|
-
throw unusable('NODE-ED25519 or NODE-ED448');
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
74
|
case isCloudflareWorkers() && 'EdDSA': {
|
|
80
75
|
if (!isAlgorithm(key.algorithm, 'NODE-ED25519'))
|
|
81
76
|
throw unusable('NODE-ED25519');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers
|
|
1
|
+
import { isCloudflareWorkers } from './env.js';
|
|
2
2
|
import crypto, { isCryptoKey } from './webcrypto.js';
|
|
3
3
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
4
4
|
import { encodeBase64 } from './base64url.js';
|
|
@@ -44,10 +44,8 @@ const getNamedCurve = (keyData) => {
|
|
|
44
44
|
return 'P-384';
|
|
45
45
|
case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]):
|
|
46
46
|
return 'P-521';
|
|
47
|
-
case
|
|
47
|
+
case isCloudflareWorkers() && findOid(keyData, [0x2b, 0x65, 0x70]):
|
|
48
48
|
return 'Ed25519';
|
|
49
|
-
case isNodeJs() && findOid(keyData, [0x2b, 0x65, 0x71]):
|
|
50
|
-
return 'Ed448';
|
|
51
49
|
default:
|
|
52
50
|
throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type');
|
|
53
51
|
}
|
|
@@ -102,7 +100,7 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
|
102
100
|
algorithm = { name: 'ECDH', namedCurve: getNamedCurve(keyData) };
|
|
103
101
|
keyUsages = isPublic ? [] : ['deriveBits'];
|
|
104
102
|
break;
|
|
105
|
-
case
|
|
103
|
+
case isCloudflareWorkers() && 'EdDSA':
|
|
106
104
|
const namedCurve = getNamedCurve(keyData).toUpperCase();
|
|
107
105
|
algorithm = { name: `NODE-${namedCurve}`, namedCurve: `NODE-${namedCurve}` };
|
|
108
106
|
keyUsages = isPublic ? ['verify'] : ['sign'];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers
|
|
1
|
+
import { isCloudflareWorkers } 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';
|
|
@@ -101,19 +101,15 @@ export async function generateKeyPair(alg, options) {
|
|
|
101
101
|
algorithm = { name: 'ECDSA', namedCurve: 'P-521' };
|
|
102
102
|
keyUsages = ['sign', 'verify'];
|
|
103
103
|
break;
|
|
104
|
-
case
|
|
104
|
+
case isCloudflareWorkers() && 'EdDSA':
|
|
105
105
|
switch (options === null || options === void 0 ? void 0 : options.crv) {
|
|
106
106
|
case undefined:
|
|
107
107
|
case 'Ed25519':
|
|
108
108
|
algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' };
|
|
109
109
|
keyUsages = ['sign', 'verify'];
|
|
110
110
|
break;
|
|
111
|
-
case isNodeJs() && 'Ed448':
|
|
112
|
-
algorithm = { name: 'NODE-ED448', namedCurve: 'NODE-ED448' };
|
|
113
|
-
keyUsages = ['sign', 'verify'];
|
|
114
|
-
break;
|
|
115
111
|
default:
|
|
116
|
-
throw new JOSENotSupported('Invalid or unsupported crv option provided
|
|
112
|
+
throw new JOSENotSupported('Invalid or unsupported crv option provided');
|
|
117
113
|
}
|
|
118
114
|
break;
|
|
119
115
|
case 'ECDH-ES':
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers
|
|
1
|
+
import { isCloudflareWorkers } 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';
|
|
@@ -99,7 +99,7 @@ function subtleMapping(jwk) {
|
|
|
99
99
|
}
|
|
100
100
|
break;
|
|
101
101
|
}
|
|
102
|
-
case
|
|
102
|
+
case isCloudflareWorkers() && 'OKP':
|
|
103
103
|
if (jwk.alg !== 'EdDSA') {
|
|
104
104
|
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
105
105
|
}
|
|
@@ -108,10 +108,6 @@ function subtleMapping(jwk) {
|
|
|
108
108
|
algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' };
|
|
109
109
|
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
110
110
|
break;
|
|
111
|
-
case isNodeJs() && 'Ed448':
|
|
112
|
-
algorithm = { name: 'NODE-ED448', namedCurve: 'NODE-ED448' };
|
|
113
|
-
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
114
|
-
break;
|
|
115
111
|
default:
|
|
116
112
|
throw new JOSENotSupported('Invalid or unsupported JWK "crv" (Subtype of Key Pair) Parameter value');
|
|
117
113
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers
|
|
1
|
+
import { isCloudflareWorkers } from './env.js';
|
|
2
2
|
import { JOSENotSupported } from '../util/errors.js';
|
|
3
3
|
export default function subtleDsa(alg, algorithm) {
|
|
4
4
|
const hash = `SHA-${alg.slice(-3)}`;
|
|
@@ -19,7 +19,7 @@ export default function subtleDsa(alg, algorithm) {
|
|
|
19
19
|
case 'ES384':
|
|
20
20
|
case 'ES512':
|
|
21
21
|
return { hash, name: 'ECDSA', namedCurve: algorithm.namedCurve };
|
|
22
|
-
case
|
|
22
|
+
case isCloudflareWorkers() && 'EdDSA':
|
|
23
23
|
const { namedCurve } = algorithm;
|
|
24
24
|
return { name: namedCurve, namedCurve };
|
|
25
25
|
default:
|
package/dist/node/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.base64url = exports.generateSecret = exports.generateKeyPair = exports.errors = exports.decodeJwt = exports.decodeProtectedHeader = exports.importJWK = exports.importX509 = exports.importPKCS8 = exports.importSPKI = exports.exportJWK = exports.exportSPKI = exports.exportPKCS8 = exports.UnsecuredJWT = exports.createRemoteJWKSet = exports.createLocalJWKSet = exports.EmbeddedJWK = exports.calculateJwkThumbprint = exports.EncryptJWT = exports.SignJWT = exports.GeneralSign = exports.FlattenedSign = exports.CompactSign = exports.FlattenedEncrypt = exports.CompactEncrypt = exports.jwtDecrypt = exports.jwtVerify = exports.generalVerify = exports.flattenedVerify = exports.compactVerify = exports.GeneralEncrypt = exports.generalDecrypt = exports.flattenedDecrypt = exports.compactDecrypt = void 0;
|
|
3
|
+
exports.base64url = exports.generateSecret = exports.generateKeyPair = exports.errors = exports.decodeJwt = exports.decodeProtectedHeader = exports.importJWK = exports.importX509 = exports.importPKCS8 = exports.importSPKI = exports.exportJWK = exports.exportSPKI = exports.exportPKCS8 = exports.UnsecuredJWT = exports.createRemoteJWKSet = exports.createLocalJWKSet = exports.EmbeddedJWK = exports.calculateJwkThumbprintUri = exports.calculateJwkThumbprint = exports.EncryptJWT = exports.SignJWT = exports.GeneralSign = exports.FlattenedSign = exports.CompactSign = exports.FlattenedEncrypt = exports.CompactEncrypt = exports.jwtDecrypt = exports.jwtVerify = exports.generalVerify = exports.flattenedVerify = exports.compactVerify = exports.GeneralEncrypt = exports.generalDecrypt = exports.flattenedDecrypt = exports.compactDecrypt = void 0;
|
|
4
4
|
var decrypt_js_1 = require("./jwe/compact/decrypt.js");
|
|
5
5
|
Object.defineProperty(exports, "compactDecrypt", { enumerable: true, get: function () { return decrypt_js_1.compactDecrypt; } });
|
|
6
6
|
var decrypt_js_2 = require("./jwe/flattened/decrypt.js");
|
|
@@ -35,6 +35,7 @@ var encrypt_js_4 = require("./jwt/encrypt.js");
|
|
|
35
35
|
Object.defineProperty(exports, "EncryptJWT", { enumerable: true, get: function () { return encrypt_js_4.EncryptJWT; } });
|
|
36
36
|
var thumbprint_js_1 = require("./jwk/thumbprint.js");
|
|
37
37
|
Object.defineProperty(exports, "calculateJwkThumbprint", { enumerable: true, get: function () { return thumbprint_js_1.calculateJwkThumbprint; } });
|
|
38
|
+
Object.defineProperty(exports, "calculateJwkThumbprintUri", { enumerable: true, get: function () { return thumbprint_js_1.calculateJwkThumbprintUri; } });
|
|
38
39
|
var embedded_js_1 = require("./jwk/embedded.js");
|
|
39
40
|
Object.defineProperty(exports, "EmbeddedJWK", { enumerable: true, get: function () { return embedded_js_1.EmbeddedJWK; } });
|
|
40
41
|
var local_js_1 = require("./jwks/local.js");
|
|
@@ -46,8 +46,8 @@ async function flattenedDecrypt(jwe, key, options) {
|
|
|
46
46
|
}
|
|
47
47
|
let parsedProt;
|
|
48
48
|
if (jwe.protected) {
|
|
49
|
-
const protectedHeader = (0, base64url_js_1.decode)(jwe.protected);
|
|
50
49
|
try {
|
|
50
|
+
const protectedHeader = (0, base64url_js_1.decode)(jwe.protected);
|
|
51
51
|
parsedProt = JSON.parse(buffer_utils_js_1.decoder.decode(protectedHeader));
|
|
52
52
|
}
|
|
53
53
|
catch {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateJwkThumbprint = void 0;
|
|
3
|
+
exports.calculateJwkThumbprintUri = exports.calculateJwkThumbprint = void 0;
|
|
4
4
|
const digest_js_1 = require("../runtime/digest.js");
|
|
5
5
|
const base64url_js_1 = require("../runtime/base64url.js");
|
|
6
6
|
const errors_js_1 = require("../util/errors.js");
|
|
@@ -11,10 +11,11 @@ const check = (value, description) => {
|
|
|
11
11
|
throw new errors_js_1.JWKInvalid(`${description} missing or invalid`);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
|
-
async function calculateJwkThumbprint(jwk, digestAlgorithm
|
|
14
|
+
async function calculateJwkThumbprint(jwk, digestAlgorithm) {
|
|
15
15
|
if (!(0, is_object_js_1.default)(jwk)) {
|
|
16
16
|
throw new TypeError('JWK must be an object');
|
|
17
17
|
}
|
|
18
|
+
digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256');
|
|
18
19
|
if (digestAlgorithm !== 'sha256' &&
|
|
19
20
|
digestAlgorithm !== 'sha384' &&
|
|
20
21
|
digestAlgorithm !== 'sha512') {
|
|
@@ -49,3 +50,9 @@ async function calculateJwkThumbprint(jwk, digestAlgorithm = 'sha256') {
|
|
|
49
50
|
return (0, base64url_js_1.encode)(await (0, digest_js_1.default)(digestAlgorithm, data));
|
|
50
51
|
}
|
|
51
52
|
exports.calculateJwkThumbprint = calculateJwkThumbprint;
|
|
53
|
+
async function calculateJwkThumbprintUri(jwk, digestAlgorithm) {
|
|
54
|
+
digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256');
|
|
55
|
+
const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm);
|
|
56
|
+
return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`;
|
|
57
|
+
}
|
|
58
|
+
exports.calculateJwkThumbprintUri = calculateJwkThumbprintUri;
|
|
@@ -32,8 +32,8 @@ async function flattenedVerify(jws, key, options) {
|
|
|
32
32
|
}
|
|
33
33
|
let parsedProt = {};
|
|
34
34
|
if (jws.protected) {
|
|
35
|
-
const protectedHeader = (0, base64url_js_1.decode)(jws.protected);
|
|
36
35
|
try {
|
|
36
|
+
const protectedHeader = (0, base64url_js_1.decode)(jws.protected);
|
|
37
37
|
parsedProt = JSON.parse(buffer_utils_js_1.decoder.decode(protectedHeader));
|
|
38
38
|
}
|
|
39
39
|
catch {
|
|
@@ -74,11 +74,6 @@ function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
74
74
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
75
75
|
break;
|
|
76
76
|
}
|
|
77
|
-
case (0, env_js_1.isNodeJs)() && 'EdDSA': {
|
|
78
|
-
if (key.algorithm.name !== 'NODE-ED25519' && key.algorithm.name !== 'NODE-ED448')
|
|
79
|
-
throw unusable('NODE-ED25519 or NODE-ED448');
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
77
|
case (0, env_js_1.isCloudflareWorkers)() && 'EdDSA': {
|
|
83
78
|
if (!isAlgorithm(key.algorithm, 'NODE-ED25519'))
|
|
84
79
|
throw unusable('NODE-ED25519');
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.isCloudflareWorkers = void 0;
|
|
4
4
|
function isCloudflareWorkers() {
|
|
5
5
|
return false;
|
|
6
6
|
}
|
|
7
7
|
exports.isCloudflareWorkers = isCloudflareWorkers;
|
|
8
|
-
function isNodeJs() {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
exports.isNodeJs = isNodeJs;
|
|
@@ -35,6 +35,10 @@ const keyToJWK = (key) => {
|
|
|
35
35
|
throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array'));
|
|
36
36
|
}
|
|
37
37
|
if (jwkExportSupported) {
|
|
38
|
+
if (keyObject.type !== 'secret' &&
|
|
39
|
+
!['rsa', 'ec', 'ed25519', 'x25519', 'ed448', 'x448'].includes(keyObject.asymmetricKeyType)) {
|
|
40
|
+
throw new errors_js_1.JOSENotSupported('Unsupported key asymmetricKeyType');
|
|
41
|
+
}
|
|
38
42
|
return keyObject.export({ format: 'jwk' });
|
|
39
43
|
}
|
|
40
44
|
switch (keyObject.type) {
|
package/dist/node/esm/index.js
CHANGED
|
@@ -14,7 +14,7 @@ export { FlattenedSign } from './jws/flattened/sign.js';
|
|
|
14
14
|
export { GeneralSign } from './jws/general/sign.js';
|
|
15
15
|
export { SignJWT } from './jwt/sign.js';
|
|
16
16
|
export { EncryptJWT } from './jwt/encrypt.js';
|
|
17
|
-
export { calculateJwkThumbprint } from './jwk/thumbprint.js';
|
|
17
|
+
export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.js';
|
|
18
18
|
export { EmbeddedJWK } from './jwk/embedded.js';
|
|
19
19
|
export { createLocalJWKSet } from './jwks/local.js';
|
|
20
20
|
export { createRemoteJWKSet } from './jwks/remote.js';
|
|
@@ -43,8 +43,8 @@ export async function flattenedDecrypt(jwe, key, options) {
|
|
|
43
43
|
}
|
|
44
44
|
let parsedProt;
|
|
45
45
|
if (jwe.protected) {
|
|
46
|
-
const protectedHeader = base64url(jwe.protected);
|
|
47
46
|
try {
|
|
47
|
+
const protectedHeader = base64url(jwe.protected);
|
|
48
48
|
parsedProt = JSON.parse(decoder.decode(protectedHeader));
|
|
49
49
|
}
|
|
50
50
|
catch {
|
|
@@ -8,10 +8,11 @@ const check = (value, description) => {
|
|
|
8
8
|
throw new JWKInvalid(`${description} missing or invalid`);
|
|
9
9
|
}
|
|
10
10
|
};
|
|
11
|
-
export async function calculateJwkThumbprint(jwk, digestAlgorithm
|
|
11
|
+
export async function calculateJwkThumbprint(jwk, digestAlgorithm) {
|
|
12
12
|
if (!isObject(jwk)) {
|
|
13
13
|
throw new TypeError('JWK must be an object');
|
|
14
14
|
}
|
|
15
|
+
digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256');
|
|
15
16
|
if (digestAlgorithm !== 'sha256' &&
|
|
16
17
|
digestAlgorithm !== 'sha384' &&
|
|
17
18
|
digestAlgorithm !== 'sha512') {
|
|
@@ -45,3 +46,8 @@ export async function calculateJwkThumbprint(jwk, digestAlgorithm = 'sha256') {
|
|
|
45
46
|
const data = encoder.encode(JSON.stringify(components));
|
|
46
47
|
return base64url(await digest(digestAlgorithm, data));
|
|
47
48
|
}
|
|
49
|
+
export async function calculateJwkThumbprintUri(jwk, digestAlgorithm) {
|
|
50
|
+
digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256');
|
|
51
|
+
const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm);
|
|
52
|
+
return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`;
|
|
53
|
+
}
|
|
@@ -29,8 +29,8 @@ export async function flattenedVerify(jws, key, options) {
|
|
|
29
29
|
}
|
|
30
30
|
let parsedProt = {};
|
|
31
31
|
if (jws.protected) {
|
|
32
|
-
const protectedHeader = base64url(jws.protected);
|
|
33
32
|
try {
|
|
33
|
+
const protectedHeader = base64url(jws.protected);
|
|
34
34
|
parsedProt = JSON.parse(decoder.decode(protectedHeader));
|
|
35
35
|
}
|
|
36
36
|
catch {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isCloudflareWorkers
|
|
1
|
+
import { isCloudflareWorkers } from '../runtime/env.js';
|
|
2
2
|
function unusable(name, prop = 'algorithm.name') {
|
|
3
3
|
return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
4
4
|
}
|
|
@@ -71,11 +71,6 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
71
71
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
72
72
|
break;
|
|
73
73
|
}
|
|
74
|
-
case isNodeJs() && 'EdDSA': {
|
|
75
|
-
if (key.algorithm.name !== 'NODE-ED25519' && key.algorithm.name !== 'NODE-ED448')
|
|
76
|
-
throw unusable('NODE-ED25519 or NODE-ED448');
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
74
|
case isCloudflareWorkers() && 'EdDSA': {
|
|
80
75
|
if (!isAlgorithm(key.algorithm, 'NODE-ED25519'))
|
|
81
76
|
throw unusable('NODE-ED25519');
|
|
@@ -33,6 +33,10 @@ const keyToJWK = (key) => {
|
|
|
33
33
|
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
34
34
|
}
|
|
35
35
|
if (jwkExportSupported) {
|
|
36
|
+
if (keyObject.type !== 'secret' &&
|
|
37
|
+
!['rsa', 'ec', 'ed25519', 'x25519', 'ed448', 'x448'].includes(keyObject.asymmetricKeyType)) {
|
|
38
|
+
throw new JOSENotSupported('Unsupported key asymmetricKeyType');
|
|
39
|
+
}
|
|
36
40
|
return keyObject.export({ format: 'jwk' });
|
|
37
41
|
}
|
|
38
42
|
switch (keyObject.type) {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export { GeneralSign } from './jws/general/sign';
|
|
|
25
25
|
export type { Signature } from './jws/general/sign';
|
|
26
26
|
export { SignJWT } from './jwt/sign';
|
|
27
27
|
export { EncryptJWT } from './jwt/encrypt';
|
|
28
|
-
export { calculateJwkThumbprint } from './jwk/thumbprint';
|
|
28
|
+
export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint';
|
|
29
29
|
export { EmbeddedJWK } from './jwk/embedded';
|
|
30
30
|
export { createLocalJWKSet } from './jwks/local';
|
|
31
31
|
export { createRemoteJWKSet } from './jwks/remote';
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import type { KeyLike, DecryptOptions, CompactJWEHeaderParameters, GetKeyFunction, FlattenedJWE, CompactDecryptResult, ResolvedKey } from '../../types';
|
|
2
2
|
/**
|
|
3
|
-
* Interface for Compact JWE Decryption dynamic key resolution.
|
|
4
|
-
*
|
|
3
|
+
* Interface for Compact JWE Decryption dynamic key resolution. No token components have been
|
|
4
|
+
* verified at the time of this function call.
|
|
5
5
|
*/
|
|
6
6
|
export interface CompactDecryptGetKey extends GetKeyFunction<CompactJWEHeaderParameters, FlattenedJWE> {
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Decrypts a Compact JWE.
|
|
10
10
|
*
|
|
11
|
-
* @param jwe Compact JWE.
|
|
12
|
-
* @param key Private Key or Secret to decrypt the JWE with.
|
|
13
|
-
* @param options JWE Decryption options.
|
|
14
|
-
*
|
|
15
11
|
* @example Usage
|
|
12
|
+
*
|
|
16
13
|
* ```js
|
|
17
|
-
* const jwe =
|
|
14
|
+
* const jwe =
|
|
15
|
+
* 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.nyQ19eq9ogh9wA7fFtnI2oouzy5_8b5DeLkoRMfi2yijgfTs2zEnayCEofz_qhnL-nwszabd9qUeHv0-IwvhhJJS7GUJOU3ikiIe42qcIAFme1A_Fo9CTxw4XTOy-I5qanl8So91u6hwfyN1VxAqVLsSE7_23EC-gfGEg_5znew9PyXXsOIE-K_HH7IQowRrlZ1X_bM_Liu53RzDpLDvRz59mp3S8L56YqpM8FexFGTGpEaoTcEIst375qncYt3-79IVR7gZN1RWsWgjPatfvVbnh74PglQcATSf3UUhaW0OAKn6q7r3PDx6DIKQ35bgHQg5QopuN00eIfLQL2trGw.W3grIVj5HVuAb76X.6PcuDe5D6ttWFYyv0oqqdDXfI2R8wBg1F2Q80UUA_Gv8eEimNWfxIWdLxrjzgQGSvIhxmFKuLM0.a93_Ug3uZHuczj70Zavx8Q'
|
|
18
16
|
*
|
|
19
17
|
* const { plaintext, protectedHeader } = await jose.compactDecrypt(jwe, privateKey)
|
|
20
18
|
*
|
|
21
19
|
* console.log(protectedHeader)
|
|
22
20
|
* console.log(new TextDecoder().decode(plaintext))
|
|
23
21
|
* ```
|
|
22
|
+
*
|
|
23
|
+
* @param jwe Compact JWE.
|
|
24
|
+
* @param key Private Key or Secret to decrypt the JWE with.
|
|
25
|
+
* @param options JWE Decryption options.
|
|
24
26
|
*/
|
|
25
27
|
export declare function compactDecrypt(jwe: string | Uint8Array, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<CompactDecryptResult>;
|
|
26
28
|
/**
|
|
@@ -3,11 +3,10 @@ import type { KeyLike, JWEKeyManagementHeaderParameters, CompactJWEHeaderParamet
|
|
|
3
3
|
* The CompactEncrypt class is a utility for creating Compact JWE strings.
|
|
4
4
|
*
|
|
5
5
|
* @example Usage
|
|
6
|
+
*
|
|
6
7
|
* ```js
|
|
7
8
|
* const jwe = await new jose.CompactEncrypt(
|
|
8
|
-
* new TextEncoder().encode(
|
|
9
|
-
* 'Itβs a dangerous business, Frodo, going out your door.'
|
|
10
|
-
* )
|
|
9
|
+
* new TextEncoder().encode('Itβs a dangerous business, Frodo, going out your door.'),
|
|
11
10
|
* )
|
|
12
11
|
* .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' })
|
|
13
12
|
* .encrypt(publicKey)
|
|
@@ -17,29 +16,24 @@ import type { KeyLike, JWEKeyManagementHeaderParameters, CompactJWEHeaderParamet
|
|
|
17
16
|
*/
|
|
18
17
|
export declare class CompactEncrypt {
|
|
19
18
|
private _flattened;
|
|
20
|
-
/**
|
|
21
|
-
* @param plaintext Binary representation of the plaintext to encrypt.
|
|
22
|
-
*/
|
|
19
|
+
/** @param plaintext Binary representation of the plaintext to encrypt. */
|
|
23
20
|
constructor(plaintext: Uint8Array);
|
|
24
21
|
/**
|
|
25
|
-
* Sets a content encryption key to use, by default a random suitable one
|
|
26
|
-
*
|
|
22
|
+
* Sets a content encryption key to use, by default a random suitable one is generated for the JWE
|
|
23
|
+
* enc" (Encryption Algorithm) Header Parameter.
|
|
27
24
|
*
|
|
25
|
+
* @deprecated You should not use this method. It is only really intended for test and vector
|
|
26
|
+
* validation purposes.
|
|
28
27
|
* @param cek JWE Content Encryption Key.
|
|
29
|
-
*
|
|
30
|
-
* @deprecated You should not use this method. It is only really intended
|
|
31
|
-
* for test and vector validation purposes.
|
|
32
28
|
*/
|
|
33
29
|
setContentEncryptionKey(cek: Uint8Array): this;
|
|
34
30
|
/**
|
|
35
|
-
* Sets the JWE Initialization Vector to use for content encryption, by default
|
|
36
|
-
*
|
|
37
|
-
* Header Parameter.
|
|
31
|
+
* Sets the JWE Initialization Vector to use for content encryption, by default a random suitable
|
|
32
|
+
* one is generated for the JWE enc" (Encryption Algorithm) Header Parameter.
|
|
38
33
|
*
|
|
34
|
+
* @deprecated You should not use this method. It is only really intended for test and vector
|
|
35
|
+
* validation purposes.
|
|
39
36
|
* @param iv JWE Initialization Vector.
|
|
40
|
-
*
|
|
41
|
-
* @deprecated You should not use this method. It is only really intended
|
|
42
|
-
* for test and vector validation purposes.
|
|
43
37
|
*/
|
|
44
38
|
setInitializationVector(iv: Uint8Array): this;
|
|
45
39
|
/**
|
|
@@ -49,9 +43,9 @@ export declare class CompactEncrypt {
|
|
|
49
43
|
*/
|
|
50
44
|
setProtectedHeader(protectedHeader: CompactJWEHeaderParameters): this;
|
|
51
45
|
/**
|
|
52
|
-
* Sets the JWE Key Management parameters to be used when encrypting the Content
|
|
53
|
-
*
|
|
54
|
-
*
|
|
46
|
+
* Sets the JWE Key Management parameters to be used when encrypting the Content Encryption Key.
|
|
47
|
+
* You do not need to invoke this method, it is only really intended for test and vector
|
|
48
|
+
* validation purposes.
|
|
55
49
|
*
|
|
56
50
|
* @param parameters JWE Key Management parameters.
|
|
57
51
|
*/
|
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
import type { FlattenedDecryptResult, KeyLike, FlattenedJWE, JWEHeaderParameters, DecryptOptions, GetKeyFunction, ResolvedKey } from '../../types';
|
|
2
2
|
/**
|
|
3
|
-
* Interface for Flattened JWE Decryption dynamic key resolution.
|
|
4
|
-
*
|
|
3
|
+
* Interface for Flattened JWE Decryption dynamic key resolution. No token components have been
|
|
4
|
+
* verified at the time of this function call.
|
|
5
5
|
*/
|
|
6
6
|
export interface FlattenedDecryptGetKey extends GetKeyFunction<JWEHeaderParameters | undefined, FlattenedJWE> {
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Decrypts a Flattened JWE.
|
|
10
10
|
*
|
|
11
|
-
* @param jwe Flattened JWE.
|
|
12
|
-
* @param key Private Key or Secret to decrypt the JWE with.
|
|
13
|
-
* @param options JWE Decryption options.
|
|
14
|
-
*
|
|
15
11
|
* @example Usage
|
|
12
|
+
*
|
|
16
13
|
* ```js
|
|
17
14
|
* const jwe = {
|
|
18
15
|
* ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4',
|
|
19
16
|
* iv: '8Fy7A_IuoX5VXG9s',
|
|
20
17
|
* tag: 'W76IYV6arGRuDSaSyWrQNg',
|
|
21
|
-
* encrypted_key:
|
|
18
|
+
* encrypted_key:
|
|
19
|
+
* 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA',
|
|
22
20
|
* aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc',
|
|
23
|
-
* protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0'
|
|
21
|
+
* protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0',
|
|
24
22
|
* }
|
|
25
23
|
*
|
|
26
|
-
* const {
|
|
27
|
-
*
|
|
28
|
-
* protectedHeader,
|
|
29
|
-
* additionalAuthenticatedData
|
|
30
|
-
* } = await jose.flattenedDecrypt(jwe, privateKey)
|
|
24
|
+
* const { plaintext, protectedHeader, additionalAuthenticatedData } =
|
|
25
|
+
* await jose.flattenedDecrypt(jwe, privateKey)
|
|
31
26
|
*
|
|
32
27
|
* console.log(protectedHeader)
|
|
33
28
|
* const decoder = new TextDecoder()
|
|
34
29
|
* console.log(decoder.decode(plaintext))
|
|
35
30
|
* console.log(decoder.decode(additionalAuthenticatedData))
|
|
36
31
|
* ```
|
|
32
|
+
*
|
|
33
|
+
* @param jwe Flattened JWE.
|
|
34
|
+
* @param key Private Key or Secret to decrypt the JWE with.
|
|
35
|
+
* @param options JWE Decryption options.
|
|
37
36
|
*/
|
|
38
37
|
export declare function flattenedDecrypt(jwe: FlattenedJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<FlattenedDecryptResult>;
|
|
39
38
|
/**
|