jose 4.5.3 → 4.6.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/dist/browser/jwe/general/encrypt.js +8 -1
- package/dist/browser/jwks/local.js +2 -1
- package/dist/browser/lib/buffer_utils.js +5 -11
- package/dist/browser/lib/crypto_key.js +1 -1
- package/dist/browser/lib/decrypt_key_management.js +1 -1
- package/dist/browser/lib/encrypt_key_management.js +1 -1
- package/dist/browser/lib/jwt_claims_set.js +2 -7
- package/dist/browser/runtime/base64url.js +6 -3
- package/dist/browser/runtime/ecdhes.js +2 -5
- package/dist/browser/runtime/pbes2kw.js +1 -1
- package/dist/node/cjs/jwe/general/encrypt.js +8 -1
- package/dist/node/cjs/jwks/local.js +2 -1
- package/dist/node/cjs/lib/buffer_utils.js +5 -11
- package/dist/node/cjs/lib/crypto_key.js +1 -1
- 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/lib/jwt_claims_set.js +2 -7
- package/dist/node/cjs/runtime/ecdhes.js +2 -2
- package/dist/node/cjs/runtime/generate.js +3 -2
- package/dist/node/cjs/runtime/pbes2kw.js +1 -1
- package/dist/node/esm/jwe/general/encrypt.js +8 -1
- package/dist/node/esm/jwks/local.js +2 -1
- package/dist/node/esm/lib/buffer_utils.js +5 -11
- package/dist/node/esm/lib/crypto_key.js +1 -1
- 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/lib/jwt_claims_set.js +2 -7
- package/dist/node/esm/runtime/ecdhes.js +2 -2
- package/dist/node/esm/runtime/generate.js +3 -2
- package/dist/node/esm/runtime/pbes2kw.js +1 -1
- package/dist/types/jwe/compact/decrypt.d.ts +26 -0
- package/dist/types/jwe/compact/encrypt.d.ts +56 -0
- package/dist/types/jwe/flattened/decrypt.d.ts +39 -0
- package/dist/types/jwe/flattened/encrypt.d.ts +77 -0
- package/dist/types/jwe/general/decrypt.d.ts +43 -0
- package/dist/types/jwe/general/encrypt.d.ts +63 -0
- package/dist/types/jwk/embedded.d.ts +20 -0
- package/dist/types/jwk/thumbprint.d.ts +19 -0
- package/dist/types/jwks/local.d.ts +42 -0
- package/dist/types/jwks/remote.d.ts +44 -0
- package/dist/types/jws/compact/sign.d.ts +30 -0
- package/dist/types/jws/compact/verify.d.ts +29 -0
- package/dist/types/jws/flattened/sign.d.ts +35 -0
- package/dist/types/jws/flattened/verify.d.ts +34 -0
- package/dist/types/jws/general/sign.d.ts +50 -0
- package/dist/types/jws/general/verify.d.ts +37 -0
- package/dist/types/jwt/decrypt.d.ts +32 -0
- package/dist/types/jwt/encrypt.d.ts +68 -0
- package/dist/types/jwt/produce.d.ts +46 -0
- package/dist/types/jwt/sign.d.ts +28 -0
- package/dist/types/jwt/unsecured.d.ts +34 -0
- package/dist/types/jwt/verify.d.ts +35 -0
- package/dist/types/key/export.d.ts +38 -0
- package/dist/types/key/generate_key_pair.d.ts +38 -0
- package/dist/types/key/generate_secret.d.ts +20 -0
- package/dist/types/key/import.d.ts +96 -0
- package/dist/types/types.d.ts +499 -2
- package/dist/types/util/base64url.d.ts +10 -0
- package/dist/types/util/decode_jwt.d.ts +14 -0
- package/dist/types/util/decode_protected_header.d.ts +11 -0
- package/dist/types/util/errors.d.ts +65 -0
- package/package.json +1 -1
|
@@ -133,6 +133,12 @@ export class GeneralEncrypt {
|
|
|
133
133
|
const recipient = this._recipients[i];
|
|
134
134
|
const target = {};
|
|
135
135
|
jwe.recipients.push(target);
|
|
136
|
+
const joseHeader = {
|
|
137
|
+
...this._protectedHeader,
|
|
138
|
+
...this._unprotectedHeader,
|
|
139
|
+
...recipient.unprotectedHeader,
|
|
140
|
+
};
|
|
141
|
+
const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined;
|
|
136
142
|
if (i === 0) {
|
|
137
143
|
const flattened = await new FlattenedEncrypt(this._plaintext)
|
|
138
144
|
.setAdditionalAuthenticatedData(this._aad)
|
|
@@ -140,6 +146,7 @@ export class GeneralEncrypt {
|
|
|
140
146
|
.setProtectedHeader(this._protectedHeader)
|
|
141
147
|
.setSharedUnprotectedHeader(this._unprotectedHeader)
|
|
142
148
|
.setUnprotectedHeader(recipient.unprotectedHeader)
|
|
149
|
+
.setKeyManagementParameters({ p2c })
|
|
143
150
|
.encrypt(recipient.key, {
|
|
144
151
|
...recipient.options,
|
|
145
152
|
...options,
|
|
@@ -161,7 +168,7 @@ export class GeneralEncrypt {
|
|
|
161
168
|
}
|
|
162
169
|
const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) ||
|
|
163
170
|
((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) ||
|
|
164
|
-
((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek);
|
|
171
|
+
((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c });
|
|
165
172
|
target.encrypted_key = base64url(encryptedKey);
|
|
166
173
|
if (recipient.unprotectedHeader || parameters)
|
|
167
174
|
target.header = { ...recipient.unprotectedHeader, ...parameters };
|
|
@@ -39,8 +39,9 @@ export class LocalJWKSet {
|
|
|
39
39
|
}
|
|
40
40
|
async getKey(protectedHeader, token) {
|
|
41
41
|
const { alg, kid } = { ...protectedHeader, ...token.header };
|
|
42
|
+
const kty = getKtyFromAlg(alg);
|
|
42
43
|
const candidates = this._jwks.keys.filter((jwk) => {
|
|
43
|
-
let candidate =
|
|
44
|
+
let candidate = kty === jwk.kty;
|
|
44
45
|
if (candidate && typeof kid === 'string') {
|
|
45
46
|
candidate = kid === jwk.kid;
|
|
46
47
|
}
|
|
@@ -39,19 +39,13 @@ export function lengthAndInput(input) {
|
|
|
39
39
|
}
|
|
40
40
|
export async function concatKdf(secret, bits, value) {
|
|
41
41
|
const iterations = Math.ceil((bits >> 3) / 32);
|
|
42
|
-
|
|
43
|
-
for (let iter =
|
|
42
|
+
const res = new Uint8Array(iterations * 32);
|
|
43
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
44
44
|
const buf = new Uint8Array(4 + secret.length + value.length);
|
|
45
|
-
buf.set(uint32be(iter));
|
|
45
|
+
buf.set(uint32be(iter + 1));
|
|
46
46
|
buf.set(secret, 4);
|
|
47
47
|
buf.set(value, 4 + secret.length);
|
|
48
|
-
|
|
49
|
-
res = await digest('sha256', buf);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
res = concat(res, await digest('sha256', buf));
|
|
53
|
-
}
|
|
48
|
+
res.set(await digest('sha256', buf), iter * 32);
|
|
54
49
|
}
|
|
55
|
-
|
|
56
|
-
return res;
|
|
50
|
+
return res.slice(0, bits >> 3);
|
|
57
51
|
}
|
|
@@ -26,7 +26,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
|
26
26
|
if (!isObject(joseHeader.epk))
|
|
27
27
|
throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
28
28
|
if (!ECDH.ecdhAllowed(key))
|
|
29
|
-
throw new JOSENotSupported('ECDH
|
|
29
|
+
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
30
30
|
const epk = await importJWK(joseHeader.epk, alg);
|
|
31
31
|
let partyUInfo;
|
|
32
32
|
let partyVInfo;
|
|
@@ -23,7 +23,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
23
23
|
case 'ECDH-ES+A192KW':
|
|
24
24
|
case 'ECDH-ES+A256KW': {
|
|
25
25
|
if (!ECDH.ecdhAllowed(key)) {
|
|
26
|
-
throw new JOSENotSupported('ECDH
|
|
26
|
+
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
27
27
|
}
|
|
28
28
|
const { apu, apv } = providedParameters;
|
|
29
29
|
let { epk: ephemeralKey } = providedParameters;
|
|
@@ -58,13 +58,8 @@ export default (protectedHeader, encodedPayload, options = {}) => {
|
|
|
58
58
|
}
|
|
59
59
|
const { currentDate } = options;
|
|
60
60
|
const now = epoch(currentDate || new Date());
|
|
61
|
-
if (payload.iat !== undefined || options.maxTokenAge) {
|
|
62
|
-
|
|
63
|
-
throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid');
|
|
64
|
-
}
|
|
65
|
-
if (payload.exp === undefined && payload.iat > now + tolerance) {
|
|
66
|
-
throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed');
|
|
67
|
-
}
|
|
61
|
+
if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') {
|
|
62
|
+
throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid');
|
|
68
63
|
}
|
|
69
64
|
if (payload.nbf !== undefined) {
|
|
70
65
|
if (typeof payload.nbf !== 'number') {
|
|
@@ -15,9 +15,12 @@ export const encode = (input) => {
|
|
|
15
15
|
return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
16
16
|
};
|
|
17
17
|
export const decodeBase64 = (encoded) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const binary = atob(encoded);
|
|
19
|
+
const bytes = new Uint8Array(binary.length);
|
|
20
|
+
for (let i = 0; i < binary.length; i++) {
|
|
21
|
+
bytes[i] = binary.charCodeAt(i);
|
|
22
|
+
}
|
|
23
|
+
return bytes;
|
|
21
24
|
};
|
|
22
25
|
export const decode = (input) => {
|
|
23
26
|
let encoded = input;
|
|
@@ -7,15 +7,12 @@ export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu
|
|
|
7
7
|
if (!isCryptoKey(publicKey)) {
|
|
8
8
|
throw new TypeError(invalidKeyInput(publicKey, ...types));
|
|
9
9
|
}
|
|
10
|
-
checkEncCryptoKey(publicKey, 'ECDH
|
|
10
|
+
checkEncCryptoKey(publicKey, 'ECDH');
|
|
11
11
|
if (!isCryptoKey(privateKey)) {
|
|
12
12
|
throw new TypeError(invalidKeyInput(privateKey, ...types));
|
|
13
13
|
}
|
|
14
|
-
checkEncCryptoKey(privateKey, 'ECDH
|
|
14
|
+
checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits');
|
|
15
15
|
const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
|
|
16
|
-
if (!privateKey.usages.includes('deriveBits')) {
|
|
17
|
-
throw new TypeError('ECDH-ES private key "usages" must include "deriveBits"');
|
|
18
|
-
}
|
|
19
16
|
const sharedSecret = new Uint8Array(await crypto.subtle.deriveBits({
|
|
20
17
|
name: 'ECDH',
|
|
21
18
|
public: publicKey,
|
|
@@ -40,7 +40,7 @@ async function deriveKey(p2s, alg, p2c, key) {
|
|
|
40
40
|
}
|
|
41
41
|
throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"');
|
|
42
42
|
}
|
|
43
|
-
export const encrypt = async (alg, key, cek, p2c =
|
|
43
|
+
export const encrypt = async (alg, key, cek, p2c = 2048, p2s = random(new Uint8Array(16))) => {
|
|
44
44
|
const derived = await deriveKey(p2s, alg, p2c, key);
|
|
45
45
|
const encryptedKey = await wrap(alg.slice(-6), derived, cek);
|
|
46
46
|
return { encryptedKey, p2c, p2s: base64url(p2s) };
|
|
@@ -136,6 +136,12 @@ class GeneralEncrypt {
|
|
|
136
136
|
const recipient = this._recipients[i];
|
|
137
137
|
const target = {};
|
|
138
138
|
jwe.recipients.push(target);
|
|
139
|
+
const joseHeader = {
|
|
140
|
+
...this._protectedHeader,
|
|
141
|
+
...this._unprotectedHeader,
|
|
142
|
+
...recipient.unprotectedHeader,
|
|
143
|
+
};
|
|
144
|
+
const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined;
|
|
139
145
|
if (i === 0) {
|
|
140
146
|
const flattened = await new encrypt_js_1.FlattenedEncrypt(this._plaintext)
|
|
141
147
|
.setAdditionalAuthenticatedData(this._aad)
|
|
@@ -143,6 +149,7 @@ class GeneralEncrypt {
|
|
|
143
149
|
.setProtectedHeader(this._protectedHeader)
|
|
144
150
|
.setSharedUnprotectedHeader(this._unprotectedHeader)
|
|
145
151
|
.setUnprotectedHeader(recipient.unprotectedHeader)
|
|
152
|
+
.setKeyManagementParameters({ p2c })
|
|
146
153
|
.encrypt(recipient.key, {
|
|
147
154
|
...recipient.options,
|
|
148
155
|
...options,
|
|
@@ -164,7 +171,7 @@ class GeneralEncrypt {
|
|
|
164
171
|
}
|
|
165
172
|
const { encryptedKey, parameters } = await (0, encrypt_key_management_js_1.default)(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) ||
|
|
166
173
|
((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) ||
|
|
167
|
-
((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek);
|
|
174
|
+
((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c });
|
|
168
175
|
target.encrypted_key = (0, base64url_js_1.encode)(encryptedKey);
|
|
169
176
|
if (recipient.unprotectedHeader || parameters)
|
|
170
177
|
target.header = { ...recipient.unprotectedHeader, ...parameters };
|
|
@@ -43,8 +43,9 @@ class LocalJWKSet {
|
|
|
43
43
|
}
|
|
44
44
|
async getKey(protectedHeader, token) {
|
|
45
45
|
const { alg, kid } = { ...protectedHeader, ...token.header };
|
|
46
|
+
const kty = getKtyFromAlg(alg);
|
|
46
47
|
const candidates = this._jwks.keys.filter((jwk) => {
|
|
47
|
-
let candidate =
|
|
48
|
+
let candidate = kty === jwk.kty;
|
|
48
49
|
if (candidate && typeof kid === 'string') {
|
|
49
50
|
candidate = kid === jwk.kid;
|
|
50
51
|
}
|
|
@@ -47,20 +47,14 @@ function lengthAndInput(input) {
|
|
|
47
47
|
exports.lengthAndInput = lengthAndInput;
|
|
48
48
|
async function concatKdf(secret, bits, value) {
|
|
49
49
|
const iterations = Math.ceil((bits >> 3) / 32);
|
|
50
|
-
|
|
51
|
-
for (let iter =
|
|
50
|
+
const res = new Uint8Array(iterations * 32);
|
|
51
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
52
52
|
const buf = new Uint8Array(4 + secret.length + value.length);
|
|
53
|
-
buf.set(uint32be(iter));
|
|
53
|
+
buf.set(uint32be(iter + 1));
|
|
54
54
|
buf.set(secret, 4);
|
|
55
55
|
buf.set(value, 4 + secret.length);
|
|
56
|
-
|
|
57
|
-
res = await (0, digest_js_1.default)('sha256', buf);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
res = concat(res, await (0, digest_js_1.default)('sha256', buf));
|
|
61
|
-
}
|
|
56
|
+
res.set(await (0, digest_js_1.default)('sha256', buf), iter * 32);
|
|
62
57
|
}
|
|
63
|
-
|
|
64
|
-
return res;
|
|
58
|
+
return res.slice(0, bits >> 3);
|
|
65
59
|
}
|
|
66
60
|
exports.concatKdf = concatKdf;
|
|
@@ -28,7 +28,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
|
28
28
|
if (!(0, is_object_js_1.default)(joseHeader.epk))
|
|
29
29
|
throw new errors_js_1.JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
30
30
|
if (!ECDH.ecdhAllowed(key))
|
|
31
|
-
throw new errors_js_1.JOSENotSupported('ECDH
|
|
31
|
+
throw new errors_js_1.JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
32
32
|
const epk = await (0, import_js_1.importJWK)(joseHeader.epk, alg);
|
|
33
33
|
let partyUInfo;
|
|
34
34
|
let partyVInfo;
|
|
@@ -25,7 +25,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
25
25
|
case 'ECDH-ES+A192KW':
|
|
26
26
|
case 'ECDH-ES+A256KW': {
|
|
27
27
|
if (!ECDH.ecdhAllowed(key)) {
|
|
28
|
-
throw new errors_js_1.JOSENotSupported('ECDH
|
|
28
|
+
throw new errors_js_1.JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
29
29
|
}
|
|
30
30
|
const { apu, apv } = providedParameters;
|
|
31
31
|
let { epk: ephemeralKey } = providedParameters;
|
|
@@ -60,13 +60,8 @@ exports.default = (protectedHeader, encodedPayload, options = {}) => {
|
|
|
60
60
|
}
|
|
61
61
|
const { currentDate } = options;
|
|
62
62
|
const now = (0, epoch_js_1.default)(currentDate || new Date());
|
|
63
|
-
if (payload.iat !== undefined || options.maxTokenAge) {
|
|
64
|
-
|
|
65
|
-
throw new errors_js_1.JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid');
|
|
66
|
-
}
|
|
67
|
-
if (payload.exp === undefined && payload.iat > now + tolerance) {
|
|
68
|
-
throw new errors_js_1.JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed');
|
|
69
|
-
}
|
|
63
|
+
if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') {
|
|
64
|
+
throw new errors_js_1.JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid');
|
|
70
65
|
}
|
|
71
66
|
if (payload.nbf !== undefined) {
|
|
72
67
|
if (typeof payload.nbf !== 'number') {
|
|
@@ -15,7 +15,7 @@ const generateKeyPair = (0, util_1.promisify)(crypto_1.generateKeyPair);
|
|
|
15
15
|
async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) {
|
|
16
16
|
let publicKey;
|
|
17
17
|
if ((0, webcrypto_js_1.isCryptoKey)(publicKee)) {
|
|
18
|
-
(0, crypto_key_js_1.checkEncCryptoKey)(publicKee, 'ECDH
|
|
18
|
+
(0, crypto_key_js_1.checkEncCryptoKey)(publicKee, 'ECDH');
|
|
19
19
|
publicKey = crypto_1.KeyObject.from(publicKee);
|
|
20
20
|
}
|
|
21
21
|
else if ((0, is_key_object_js_1.default)(publicKee)) {
|
|
@@ -26,7 +26,7 @@ async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu = new
|
|
|
26
26
|
}
|
|
27
27
|
let privateKey;
|
|
28
28
|
if ((0, webcrypto_js_1.isCryptoKey)(privateKee)) {
|
|
29
|
-
(0, crypto_key_js_1.checkEncCryptoKey)(privateKee, 'ECDH
|
|
29
|
+
(0, crypto_key_js_1.checkEncCryptoKey)(privateKee, 'ECDH', 'deriveBits');
|
|
30
30
|
privateKey = crypto_1.KeyObject.from(privateKee);
|
|
31
31
|
}
|
|
32
32
|
else if ((0, is_key_object_js_1.default)(privateKee)) {
|
|
@@ -84,12 +84,13 @@ async function generateKeyPair(alg, options) {
|
|
|
84
84
|
case 'ECDH-ES+A128KW':
|
|
85
85
|
case 'ECDH-ES+A192KW':
|
|
86
86
|
case 'ECDH-ES+A256KW':
|
|
87
|
-
|
|
87
|
+
const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256';
|
|
88
|
+
switch (crv) {
|
|
88
89
|
case undefined:
|
|
89
90
|
case 'P-256':
|
|
90
91
|
case 'P-384':
|
|
91
92
|
case 'P-521':
|
|
92
|
-
return generate('ec', { namedCurve:
|
|
93
|
+
return generate('ec', { namedCurve: crv });
|
|
93
94
|
case 'X25519':
|
|
94
95
|
return generate('x25519');
|
|
95
96
|
case 'X448':
|
|
@@ -27,7 +27,7 @@ function getPassword(key, alg) {
|
|
|
27
27
|
}
|
|
28
28
|
throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array'));
|
|
29
29
|
}
|
|
30
|
-
const encrypt = async (alg, key, cek, p2c =
|
|
30
|
+
const encrypt = async (alg, key, cek, p2c = 2048, p2s = (0, random_js_1.default)(new Uint8Array(16))) => {
|
|
31
31
|
(0, check_p2s_js_1.default)(p2s);
|
|
32
32
|
const salt = (0, buffer_utils_js_1.p2s)(alg, p2s);
|
|
33
33
|
const keylen = parseInt(alg.slice(13, 16), 10) >> 3;
|
|
@@ -133,6 +133,12 @@ export class GeneralEncrypt {
|
|
|
133
133
|
const recipient = this._recipients[i];
|
|
134
134
|
const target = {};
|
|
135
135
|
jwe.recipients.push(target);
|
|
136
|
+
const joseHeader = {
|
|
137
|
+
...this._protectedHeader,
|
|
138
|
+
...this._unprotectedHeader,
|
|
139
|
+
...recipient.unprotectedHeader,
|
|
140
|
+
};
|
|
141
|
+
const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined;
|
|
136
142
|
if (i === 0) {
|
|
137
143
|
const flattened = await new FlattenedEncrypt(this._plaintext)
|
|
138
144
|
.setAdditionalAuthenticatedData(this._aad)
|
|
@@ -140,6 +146,7 @@ export class GeneralEncrypt {
|
|
|
140
146
|
.setProtectedHeader(this._protectedHeader)
|
|
141
147
|
.setSharedUnprotectedHeader(this._unprotectedHeader)
|
|
142
148
|
.setUnprotectedHeader(recipient.unprotectedHeader)
|
|
149
|
+
.setKeyManagementParameters({ p2c })
|
|
143
150
|
.encrypt(recipient.key, {
|
|
144
151
|
...recipient.options,
|
|
145
152
|
...options,
|
|
@@ -161,7 +168,7 @@ export class GeneralEncrypt {
|
|
|
161
168
|
}
|
|
162
169
|
const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) ||
|
|
163
170
|
((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) ||
|
|
164
|
-
((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek);
|
|
171
|
+
((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c });
|
|
165
172
|
target.encrypted_key = base64url(encryptedKey);
|
|
166
173
|
if (recipient.unprotectedHeader || parameters)
|
|
167
174
|
target.header = { ...recipient.unprotectedHeader, ...parameters };
|
|
@@ -39,8 +39,9 @@ export class LocalJWKSet {
|
|
|
39
39
|
}
|
|
40
40
|
async getKey(protectedHeader, token) {
|
|
41
41
|
const { alg, kid } = { ...protectedHeader, ...token.header };
|
|
42
|
+
const kty = getKtyFromAlg(alg);
|
|
42
43
|
const candidates = this._jwks.keys.filter((jwk) => {
|
|
43
|
-
let candidate =
|
|
44
|
+
let candidate = kty === jwk.kty;
|
|
44
45
|
if (candidate && typeof kid === 'string') {
|
|
45
46
|
candidate = kid === jwk.kid;
|
|
46
47
|
}
|
|
@@ -39,19 +39,13 @@ export function lengthAndInput(input) {
|
|
|
39
39
|
}
|
|
40
40
|
export async function concatKdf(secret, bits, value) {
|
|
41
41
|
const iterations = Math.ceil((bits >> 3) / 32);
|
|
42
|
-
|
|
43
|
-
for (let iter =
|
|
42
|
+
const res = new Uint8Array(iterations * 32);
|
|
43
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
44
44
|
const buf = new Uint8Array(4 + secret.length + value.length);
|
|
45
|
-
buf.set(uint32be(iter));
|
|
45
|
+
buf.set(uint32be(iter + 1));
|
|
46
46
|
buf.set(secret, 4);
|
|
47
47
|
buf.set(value, 4 + secret.length);
|
|
48
|
-
|
|
49
|
-
res = await digest('sha256', buf);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
res = concat(res, await digest('sha256', buf));
|
|
53
|
-
}
|
|
48
|
+
res.set(await digest('sha256', buf), iter * 32);
|
|
54
49
|
}
|
|
55
|
-
|
|
56
|
-
return res;
|
|
50
|
+
return res.slice(0, bits >> 3);
|
|
57
51
|
}
|
|
@@ -26,7 +26,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
|
26
26
|
if (!isObject(joseHeader.epk))
|
|
27
27
|
throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
28
28
|
if (!ECDH.ecdhAllowed(key))
|
|
29
|
-
throw new JOSENotSupported('ECDH
|
|
29
|
+
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
30
30
|
const epk = await importJWK(joseHeader.epk, alg);
|
|
31
31
|
let partyUInfo;
|
|
32
32
|
let partyVInfo;
|
|
@@ -23,7 +23,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
23
23
|
case 'ECDH-ES+A192KW':
|
|
24
24
|
case 'ECDH-ES+A256KW': {
|
|
25
25
|
if (!ECDH.ecdhAllowed(key)) {
|
|
26
|
-
throw new JOSENotSupported('ECDH
|
|
26
|
+
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
27
27
|
}
|
|
28
28
|
const { apu, apv } = providedParameters;
|
|
29
29
|
let { epk: ephemeralKey } = providedParameters;
|
|
@@ -58,13 +58,8 @@ export default (protectedHeader, encodedPayload, options = {}) => {
|
|
|
58
58
|
}
|
|
59
59
|
const { currentDate } = options;
|
|
60
60
|
const now = epoch(currentDate || new Date());
|
|
61
|
-
if (payload.iat !== undefined || options.maxTokenAge) {
|
|
62
|
-
|
|
63
|
-
throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid');
|
|
64
|
-
}
|
|
65
|
-
if (payload.exp === undefined && payload.iat > now + tolerance) {
|
|
66
|
-
throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed');
|
|
67
|
-
}
|
|
61
|
+
if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') {
|
|
62
|
+
throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid');
|
|
68
63
|
}
|
|
69
64
|
if (payload.nbf !== undefined) {
|
|
70
65
|
if (typeof payload.nbf !== 'number') {
|
|
@@ -12,7 +12,7 @@ const generateKeyPair = promisify(generateKeyPairCb);
|
|
|
12
12
|
export async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) {
|
|
13
13
|
let publicKey;
|
|
14
14
|
if (isCryptoKey(publicKee)) {
|
|
15
|
-
checkEncCryptoKey(publicKee, 'ECDH
|
|
15
|
+
checkEncCryptoKey(publicKee, 'ECDH');
|
|
16
16
|
publicKey = KeyObject.from(publicKee);
|
|
17
17
|
}
|
|
18
18
|
else if (isKeyObject(publicKee)) {
|
|
@@ -23,7 +23,7 @@ export async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu
|
|
|
23
23
|
}
|
|
24
24
|
let privateKey;
|
|
25
25
|
if (isCryptoKey(privateKee)) {
|
|
26
|
-
checkEncCryptoKey(privateKee, 'ECDH
|
|
26
|
+
checkEncCryptoKey(privateKee, 'ECDH', 'deriveBits');
|
|
27
27
|
privateKey = KeyObject.from(privateKee);
|
|
28
28
|
}
|
|
29
29
|
else if (isKeyObject(privateKee)) {
|
|
@@ -80,12 +80,13 @@ export async function generateKeyPair(alg, options) {
|
|
|
80
80
|
case 'ECDH-ES+A128KW':
|
|
81
81
|
case 'ECDH-ES+A192KW':
|
|
82
82
|
case 'ECDH-ES+A256KW':
|
|
83
|
-
|
|
83
|
+
const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256';
|
|
84
|
+
switch (crv) {
|
|
84
85
|
case undefined:
|
|
85
86
|
case 'P-256':
|
|
86
87
|
case 'P-384':
|
|
87
88
|
case 'P-521':
|
|
88
|
-
return generate('ec', { namedCurve:
|
|
89
|
+
return generate('ec', { namedCurve: crv });
|
|
89
90
|
case 'X25519':
|
|
90
91
|
return generate('x25519');
|
|
91
92
|
case 'X448':
|
|
@@ -24,7 +24,7 @@ function getPassword(key, alg) {
|
|
|
24
24
|
}
|
|
25
25
|
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
26
26
|
}
|
|
27
|
-
export const encrypt = async (alg, key, cek, p2c =
|
|
27
|
+
export const encrypt = async (alg, key, cek, p2c = 2048, p2s = random(new Uint8Array(16))) => {
|
|
28
28
|
checkP2s(p2s);
|
|
29
29
|
const salt = concatSalt(alg, p2s);
|
|
30
30
|
const keylen = parseInt(alg.slice(13, 16), 10) >> 3;
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
import type { KeyLike, DecryptOptions, CompactJWEHeaderParameters, GetKeyFunction, FlattenedJWE, CompactDecryptResult, ResolvedKey } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for Compact JWE Decryption dynamic key resolution.
|
|
4
|
+
* No token components have been verified at the time of this function call.
|
|
5
|
+
*/
|
|
2
6
|
export interface CompactDecryptGetKey extends GetKeyFunction<CompactJWEHeaderParameters, FlattenedJWE> {
|
|
3
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Decrypts a Compact JWE.
|
|
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
|
+
* @example Usage
|
|
16
|
+
* ```js
|
|
17
|
+
* const jwe = 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.nyQ19eq9ogh9wA7fFtnI2oouzy5_8b5DeLkoRMfi2yijgfTs2zEnayCEofz_qhnL-nwszabd9qUeHv0-IwvhhJJS7GUJOU3ikiIe42qcIAFme1A_Fo9CTxw4XTOy-I5qanl8So91u6hwfyN1VxAqVLsSE7_23EC-gfGEg_5znew9PyXXsOIE-K_HH7IQowRrlZ1X_bM_Liu53RzDpLDvRz59mp3S8L56YqpM8FexFGTGpEaoTcEIst375qncYt3-79IVR7gZN1RWsWgjPatfvVbnh74PglQcATSf3UUhaW0OAKn6q7r3PDx6DIKQ35bgHQg5QopuN00eIfLQL2trGw.W3grIVj5HVuAb76X.6PcuDe5D6ttWFYyv0oqqdDXfI2R8wBg1F2Q80UUA_Gv8eEimNWfxIWdLxrjzgQGSvIhxmFKuLM0.a93_Ug3uZHuczj70Zavx8Q'
|
|
18
|
+
*
|
|
19
|
+
* const { plaintext, protectedHeader } = await jose.compactDecrypt(jwe, privateKey)
|
|
20
|
+
*
|
|
21
|
+
* console.log(protectedHeader)
|
|
22
|
+
* console.log(new TextDecoder().decode(plaintext))
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
4
25
|
export declare function compactDecrypt(jwe: string | Uint8Array, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<CompactDecryptResult>;
|
|
26
|
+
/**
|
|
27
|
+
* @param jwe Compact JWE.
|
|
28
|
+
* @param getKey Function resolving Private Key or Secret to decrypt the JWE with.
|
|
29
|
+
* @param options JWE Decryption options.
|
|
30
|
+
*/
|
|
5
31
|
export declare function compactDecrypt(jwe: string | Uint8Array, getKey: CompactDecryptGetKey, options?: DecryptOptions): Promise<CompactDecryptResult & ResolvedKey>;
|
|
@@ -1,10 +1,66 @@
|
|
|
1
1
|
import type { KeyLike, JWEKeyManagementHeaderParameters, CompactJWEHeaderParameters, EncryptOptions } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* The CompactEncrypt class is a utility for creating Compact JWE strings.
|
|
4
|
+
*
|
|
5
|
+
* @example Usage
|
|
6
|
+
* ```js
|
|
7
|
+
* const jwe = await new jose.CompactEncrypt(
|
|
8
|
+
* new TextEncoder().encode(
|
|
9
|
+
* 'It’s a dangerous business, Frodo, going out your door.'
|
|
10
|
+
* )
|
|
11
|
+
* )
|
|
12
|
+
* .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' })
|
|
13
|
+
* .encrypt(publicKey)
|
|
14
|
+
*
|
|
15
|
+
* console.log(jwe)
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
2
18
|
export declare class CompactEncrypt {
|
|
3
19
|
private _flattened;
|
|
20
|
+
/**
|
|
21
|
+
* @param plaintext Binary representation of the plaintext to encrypt.
|
|
22
|
+
*/
|
|
4
23
|
constructor(plaintext: Uint8Array);
|
|
24
|
+
/**
|
|
25
|
+
* Sets a content encryption key to use, by default a random suitable one
|
|
26
|
+
* is generated for the JWE enc" (Encryption Algorithm) Header Parameter.
|
|
27
|
+
*
|
|
28
|
+
* @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
|
+
*/
|
|
5
33
|
setContentEncryptionKey(cek: Uint8Array): this;
|
|
34
|
+
/**
|
|
35
|
+
* Sets the JWE Initialization Vector to use for content encryption, by default
|
|
36
|
+
* a random suitable one is generated for the JWE enc" (Encryption Algorithm)
|
|
37
|
+
* Header Parameter.
|
|
38
|
+
*
|
|
39
|
+
* @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
|
+
*/
|
|
6
44
|
setInitializationVector(iv: Uint8Array): this;
|
|
45
|
+
/**
|
|
46
|
+
* Sets the JWE Protected Header on the CompactEncrypt object.
|
|
47
|
+
*
|
|
48
|
+
* @param protectedHeader JWE Protected Header object.
|
|
49
|
+
*/
|
|
7
50
|
setProtectedHeader(protectedHeader: CompactJWEHeaderParameters): this;
|
|
51
|
+
/**
|
|
52
|
+
* Sets the JWE Key Management parameters to be used when encrypting the Content
|
|
53
|
+
* Encryption Key. You do not need to invoke this method, it is only really
|
|
54
|
+
* intended for test and vector validation purposes.
|
|
55
|
+
*
|
|
56
|
+
* @param parameters JWE Key Management parameters.
|
|
57
|
+
*/
|
|
8
58
|
setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this;
|
|
59
|
+
/**
|
|
60
|
+
* Encrypts and resolves the value of the Compact JWE string.
|
|
61
|
+
*
|
|
62
|
+
* @param key Public Key or Secret to encrypt the JWE with.
|
|
63
|
+
* @param options JWE Encryption options.
|
|
64
|
+
*/
|
|
9
65
|
encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise<string>;
|
|
10
66
|
}
|
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
import type { FlattenedDecryptResult, KeyLike, FlattenedJWE, JWEHeaderParameters, DecryptOptions, GetKeyFunction, ResolvedKey } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for Flattened JWE Decryption dynamic key resolution.
|
|
4
|
+
* No token components have been verified at the time of this function call.
|
|
5
|
+
*/
|
|
2
6
|
export interface FlattenedDecryptGetKey extends GetKeyFunction<JWEHeaderParameters | undefined, FlattenedJWE> {
|
|
3
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Decrypts a Flattened JWE.
|
|
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
|
+
* @example Usage
|
|
16
|
+
* ```js
|
|
17
|
+
* const jwe = {
|
|
18
|
+
* ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4',
|
|
19
|
+
* iv: '8Fy7A_IuoX5VXG9s',
|
|
20
|
+
* tag: 'W76IYV6arGRuDSaSyWrQNg',
|
|
21
|
+
* encrypted_key: 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA',
|
|
22
|
+
* aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc',
|
|
23
|
+
* protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0'
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* const {
|
|
27
|
+
* plaintext,
|
|
28
|
+
* protectedHeader,
|
|
29
|
+
* additionalAuthenticatedData
|
|
30
|
+
* } = await jose.flattenedDecrypt(jwe, privateKey)
|
|
31
|
+
*
|
|
32
|
+
* console.log(protectedHeader)
|
|
33
|
+
* const decoder = new TextDecoder()
|
|
34
|
+
* console.log(decoder.decode(plaintext))
|
|
35
|
+
* console.log(decoder.decode(additionalAuthenticatedData))
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
4
38
|
export declare function flattenedDecrypt(jwe: FlattenedJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<FlattenedDecryptResult>;
|
|
39
|
+
/**
|
|
40
|
+
* @param jwe Flattened JWE.
|
|
41
|
+
* @param getKey Function resolving Private Key or Secret to decrypt the JWE with.
|
|
42
|
+
* @param options JWE Decryption options.
|
|
43
|
+
*/
|
|
5
44
|
export declare function flattenedDecrypt(jwe: FlattenedJWE, getKey: FlattenedDecryptGetKey, options?: DecryptOptions): Promise<FlattenedDecryptResult & ResolvedKey>;
|