jose 4.2.0 → 4.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/browser/jwe/general/encrypt.js +33 -23
- package/dist/browser/jwks/remote.js +16 -12
- package/dist/browser/jws/general/sign.js +25 -29
- package/dist/browser/lib/cek.js +5 -6
- package/dist/browser/lib/decrypt_key_management.js +1 -1
- package/dist/browser/lib/encrypt_key_management.js +1 -1
- package/dist/browser/lib/iv.js +4 -11
- package/dist/browser/runtime/aeskw.js +2 -1
- package/dist/browser/runtime/asn1.js +2 -1
- package/dist/browser/runtime/decrypt.js +2 -1
- package/dist/browser/runtime/ecdhes.js +5 -4
- package/dist/browser/runtime/encrypt.js +2 -1
- package/dist/browser/runtime/get_sign_verify_key.js +3 -2
- package/dist/browser/runtime/key_to_jwk.js +2 -1
- package/dist/browser/runtime/pbes2kw.js +2 -1
- package/dist/browser/runtime/rsaes.js +3 -2
- package/dist/node/cjs/jwe/general/encrypt.js +33 -23
- package/dist/node/cjs/jwks/remote.js +16 -12
- package/dist/node/cjs/jws/general/sign.js +25 -29
- package/dist/node/cjs/lib/cek.js +5 -6
- 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/iv.js +4 -11
- package/dist/node/cjs/runtime/aeskw.js +4 -3
- package/dist/node/cjs/runtime/asn1.js +2 -1
- package/dist/node/cjs/runtime/decrypt.js +5 -4
- package/dist/node/cjs/runtime/ecdhes.js +5 -4
- package/dist/node/cjs/runtime/encrypt.js +5 -4
- package/dist/node/cjs/runtime/get_named_curve.js +2 -1
- package/dist/node/cjs/runtime/get_sign_verify_key.js +3 -2
- package/dist/node/cjs/runtime/key_to_jwk.js +2 -1
- package/dist/node/cjs/runtime/pbes2kw.js +2 -1
- package/dist/node/cjs/runtime/rsaes.js +4 -3
- package/dist/node/esm/jwe/general/encrypt.js +33 -23
- package/dist/node/esm/jwks/remote.js +16 -12
- package/dist/node/esm/jws/general/sign.js +25 -29
- package/dist/node/esm/lib/cek.js +5 -6
- 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/iv.js +4 -11
- package/dist/node/esm/runtime/aeskw.js +4 -3
- package/dist/node/esm/runtime/asn1.js +2 -1
- package/dist/node/esm/runtime/decrypt.js +5 -4
- package/dist/node/esm/runtime/ecdhes.js +5 -4
- package/dist/node/esm/runtime/encrypt.js +5 -4
- package/dist/node/esm/runtime/get_named_curve.js +2 -1
- package/dist/node/esm/runtime/get_sign_verify_key.js +3 -2
- package/dist/node/esm/runtime/key_to_jwk.js +2 -1
- package/dist/node/esm/runtime/pbes2kw.js +2 -1
- package/dist/node/esm/runtime/rsaes.js +4 -3
- package/dist/types/index.d.ts +1 -1
- package/dist/types/jwe/compact/decrypt.d.ts +2 -2
- package/dist/types/jwe/compact/encrypt.d.ts +2 -2
- package/dist/types/jwe/general/encrypt.d.ts +3 -0
- package/dist/types/jws/compact/sign.d.ts +2 -2
- package/dist/types/jws/compact/verify.d.ts +2 -2
- package/dist/types/jws/general/sign.d.ts +3 -0
- package/dist/types/jwt/decrypt.d.ts +2 -2
- package/dist/types/jwt/encrypt.d.ts +2 -2
- package/dist/types/jwt/sign.d.ts +2 -2
- package/dist/types/jwt/verify.d.ts +2 -2
- package/dist/types/types.d.ts +19 -17
- package/package.json +1 -1
|
@@ -5,20 +5,27 @@ import isDisjoint from '../../lib/is_disjoint.js';
|
|
|
5
5
|
import encryptKeyManagement from '../../lib/encrypt_key_management.js';
|
|
6
6
|
import { encode as base64url } from '../../runtime/base64url.js';
|
|
7
7
|
import validateCrit from '../../lib/validate_crit.js';
|
|
8
|
-
const recipientRef = new WeakMap();
|
|
9
8
|
class IndividualRecipient {
|
|
9
|
+
constructor(enc, key, options) {
|
|
10
|
+
this.parent = enc;
|
|
11
|
+
this.key = key;
|
|
12
|
+
this.options = options;
|
|
13
|
+
}
|
|
10
14
|
setUnprotectedHeader(unprotectedHeader) {
|
|
11
|
-
if (this.
|
|
15
|
+
if (this.unprotectedHeader) {
|
|
12
16
|
throw new TypeError('setUnprotectedHeader can only be called once');
|
|
13
17
|
}
|
|
14
|
-
this.
|
|
18
|
+
this.unprotectedHeader = unprotectedHeader;
|
|
15
19
|
return this;
|
|
16
20
|
}
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
addRecipient(...args) {
|
|
22
|
+
return this.parent.addRecipient(...args);
|
|
23
|
+
}
|
|
24
|
+
encrypt(...args) {
|
|
25
|
+
return this.parent.encrypt(...args);
|
|
19
26
|
}
|
|
20
|
-
|
|
21
|
-
return
|
|
27
|
+
done() {
|
|
28
|
+
return this.parent;
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
31
|
export class GeneralEncrypt {
|
|
@@ -27,8 +34,7 @@ export class GeneralEncrypt {
|
|
|
27
34
|
this._plaintext = plaintext;
|
|
28
35
|
}
|
|
29
36
|
addRecipient(key, options) {
|
|
30
|
-
const recipient = new IndividualRecipient();
|
|
31
|
-
recipientRef.set(recipient, { key, options: { crit: options === null || options === void 0 ? void 0 : options.crit } });
|
|
37
|
+
const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit });
|
|
32
38
|
this._recipients.push(recipient);
|
|
33
39
|
return recipient;
|
|
34
40
|
}
|
|
@@ -51,19 +57,19 @@ export class GeneralEncrypt {
|
|
|
51
57
|
return this;
|
|
52
58
|
}
|
|
53
59
|
async encrypt(options) {
|
|
54
|
-
var _a, _b;
|
|
60
|
+
var _a, _b, _c;
|
|
55
61
|
if (!this._recipients.length) {
|
|
56
62
|
throw new JWEInvalid('at least one recipient must be added');
|
|
57
63
|
}
|
|
58
64
|
options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw };
|
|
59
65
|
if (this._recipients.length === 1) {
|
|
60
|
-
const
|
|
66
|
+
const [recipient] = this._recipients;
|
|
61
67
|
const flattened = await new FlattenedEncrypt(this._plaintext)
|
|
62
68
|
.setAdditionalAuthenticatedData(this._aad)
|
|
63
69
|
.setProtectedHeader(this._protectedHeader)
|
|
64
70
|
.setSharedUnprotectedHeader(this._unprotectedHeader)
|
|
65
|
-
.setUnprotectedHeader(unprotectedHeader)
|
|
66
|
-
.encrypt(key, { ...
|
|
71
|
+
.setUnprotectedHeader(recipient.unprotectedHeader)
|
|
72
|
+
.encrypt(recipient.key, { ...recipient.options, ...options });
|
|
67
73
|
let jwe = {
|
|
68
74
|
ciphertext: flattened.ciphertext,
|
|
69
75
|
iv: flattened.iv,
|
|
@@ -85,14 +91,13 @@ export class GeneralEncrypt {
|
|
|
85
91
|
let enc;
|
|
86
92
|
for (let i = 0; i < this._recipients.length; i++) {
|
|
87
93
|
const recipient = this._recipients[i];
|
|
88
|
-
|
|
89
|
-
if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, unprotectedHeader)) {
|
|
94
|
+
if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) {
|
|
90
95
|
throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
|
|
91
96
|
}
|
|
92
97
|
const joseHeader = {
|
|
93
98
|
...this._protectedHeader,
|
|
94
99
|
...this._unprotectedHeader,
|
|
95
|
-
...unprotectedHeader,
|
|
100
|
+
...recipient.unprotectedHeader,
|
|
96
101
|
};
|
|
97
102
|
const { alg } = joseHeader;
|
|
98
103
|
if (typeof alg !== 'string' || !alg) {
|
|
@@ -110,7 +115,7 @@ export class GeneralEncrypt {
|
|
|
110
115
|
else if (enc !== joseHeader.enc) {
|
|
111
116
|
throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients');
|
|
112
117
|
}
|
|
113
|
-
validateCrit(JWEInvalid, new Map(),
|
|
118
|
+
validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader);
|
|
114
119
|
if (joseHeader.zip !== undefined) {
|
|
115
120
|
if (!this._protectedHeader || !this._protectedHeader.zip) {
|
|
116
121
|
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
|
|
@@ -128,15 +133,18 @@ export class GeneralEncrypt {
|
|
|
128
133
|
const recipient = this._recipients[i];
|
|
129
134
|
const target = {};
|
|
130
135
|
jwe.recipients.push(target);
|
|
131
|
-
const { unprotectedHeader, options: recipientOpts, key } = recipientRef.get(recipient);
|
|
132
136
|
if (i === 0) {
|
|
133
137
|
const flattened = await new FlattenedEncrypt(this._plaintext)
|
|
134
138
|
.setAdditionalAuthenticatedData(this._aad)
|
|
135
139
|
.setContentEncryptionKey(cek)
|
|
136
140
|
.setProtectedHeader(this._protectedHeader)
|
|
137
141
|
.setSharedUnprotectedHeader(this._unprotectedHeader)
|
|
138
|
-
.setUnprotectedHeader(unprotectedHeader)
|
|
139
|
-
.encrypt(key, {
|
|
142
|
+
.setUnprotectedHeader(recipient.unprotectedHeader)
|
|
143
|
+
.encrypt(recipient.key, {
|
|
144
|
+
...recipient.options,
|
|
145
|
+
...options,
|
|
146
|
+
[unprotected]: true,
|
|
147
|
+
});
|
|
140
148
|
jwe.ciphertext = flattened.ciphertext;
|
|
141
149
|
jwe.iv = flattened.iv;
|
|
142
150
|
jwe.tag = flattened.tag;
|
|
@@ -151,10 +159,12 @@ export class GeneralEncrypt {
|
|
|
151
159
|
target.header = flattened.header;
|
|
152
160
|
continue;
|
|
153
161
|
}
|
|
154
|
-
const { encryptedKey, parameters } = await encryptKeyManagement((
|
|
162
|
+
const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) ||
|
|
163
|
+
((_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);
|
|
155
165
|
target.encrypted_key = base64url(encryptedKey);
|
|
156
|
-
if (unprotectedHeader || parameters)
|
|
157
|
-
target.header = { ...unprotectedHeader, ...parameters };
|
|
166
|
+
if (recipient.unprotectedHeader || parameters)
|
|
167
|
+
target.header = { ...recipient.unprotectedHeader, ...parameters };
|
|
158
168
|
}
|
|
159
169
|
return jwe;
|
|
160
170
|
}
|
|
@@ -37,17 +37,21 @@ class RemoteJWKSet {
|
|
|
37
37
|
}
|
|
38
38
|
return Date.now() < this._cooldownStarted + this._cooldownDuration;
|
|
39
39
|
}
|
|
40
|
-
async getKey(protectedHeader) {
|
|
40
|
+
async getKey(protectedHeader, token) {
|
|
41
|
+
const joseHeader = {
|
|
42
|
+
...protectedHeader,
|
|
43
|
+
...token.header,
|
|
44
|
+
};
|
|
41
45
|
if (!this._jwks) {
|
|
42
46
|
await this.reload();
|
|
43
47
|
}
|
|
44
48
|
const candidates = this._jwks.keys.filter((jwk) => {
|
|
45
|
-
let candidate = jwk.kty === getKtyFromAlg(
|
|
46
|
-
if (candidate && typeof
|
|
47
|
-
candidate =
|
|
49
|
+
let candidate = jwk.kty === getKtyFromAlg(joseHeader.alg);
|
|
50
|
+
if (candidate && typeof joseHeader.kid === 'string') {
|
|
51
|
+
candidate = joseHeader.kid === jwk.kid;
|
|
48
52
|
}
|
|
49
53
|
if (candidate && typeof jwk.alg === 'string') {
|
|
50
|
-
candidate =
|
|
54
|
+
candidate = joseHeader.alg === jwk.alg;
|
|
51
55
|
}
|
|
52
56
|
if (candidate && typeof jwk.use === 'string') {
|
|
53
57
|
candidate = jwk.use === 'sig';
|
|
@@ -55,11 +59,11 @@ class RemoteJWKSet {
|
|
|
55
59
|
if (candidate && Array.isArray(jwk.key_ops)) {
|
|
56
60
|
candidate = jwk.key_ops.includes('verify');
|
|
57
61
|
}
|
|
58
|
-
if (candidate &&
|
|
62
|
+
if (candidate && joseHeader.alg === 'EdDSA') {
|
|
59
63
|
candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448';
|
|
60
64
|
}
|
|
61
65
|
if (candidate) {
|
|
62
|
-
switch (
|
|
66
|
+
switch (joseHeader.alg) {
|
|
63
67
|
case 'ES256':
|
|
64
68
|
candidate = jwk.crv === 'P-256';
|
|
65
69
|
break;
|
|
@@ -81,7 +85,7 @@ class RemoteJWKSet {
|
|
|
81
85
|
if (length === 0) {
|
|
82
86
|
if (this.coolingDown() === false) {
|
|
83
87
|
await this.reload();
|
|
84
|
-
return this.getKey(protectedHeader);
|
|
88
|
+
return this.getKey(protectedHeader, token);
|
|
85
89
|
}
|
|
86
90
|
throw new JWKSNoMatchingKey();
|
|
87
91
|
}
|
|
@@ -89,14 +93,14 @@ class RemoteJWKSet {
|
|
|
89
93
|
throw new JWKSMultipleMatchingKeys();
|
|
90
94
|
}
|
|
91
95
|
const cached = this._cached.get(jwk) || this._cached.set(jwk, {}).get(jwk);
|
|
92
|
-
if (cached[
|
|
93
|
-
const keyObject = await importJWK({ ...jwk, ext: true },
|
|
96
|
+
if (cached[joseHeader.alg] === undefined) {
|
|
97
|
+
const keyObject = await importJWK({ ...jwk, ext: true }, joseHeader.alg);
|
|
94
98
|
if (keyObject instanceof Uint8Array || keyObject.type !== 'public') {
|
|
95
99
|
throw new JWKSInvalid('JSON Web Key Set members must be public keys');
|
|
96
100
|
}
|
|
97
|
-
cached[
|
|
101
|
+
cached[joseHeader.alg] = keyObject;
|
|
98
102
|
}
|
|
99
|
-
return cached[
|
|
103
|
+
return cached[joseHeader.alg];
|
|
100
104
|
}
|
|
101
105
|
async reload() {
|
|
102
106
|
if (!this._pendingFetch) {
|
|
@@ -1,32 +1,33 @@
|
|
|
1
1
|
import { FlattenedSign } from '../flattened/sign.js';
|
|
2
2
|
import { JWSInvalid } from '../../util/errors.js';
|
|
3
|
-
const signatureRef = new WeakMap();
|
|
4
3
|
class IndividualSignature {
|
|
4
|
+
constructor(sig, key, options) {
|
|
5
|
+
this.parent = sig;
|
|
6
|
+
this.key = key;
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
5
9
|
setProtectedHeader(protectedHeader) {
|
|
6
|
-
if (this.
|
|
10
|
+
if (this.protectedHeader) {
|
|
7
11
|
throw new TypeError('setProtectedHeader can only be called once');
|
|
8
12
|
}
|
|
9
|
-
this.
|
|
13
|
+
this.protectedHeader = protectedHeader;
|
|
10
14
|
return this;
|
|
11
15
|
}
|
|
12
16
|
setUnprotectedHeader(unprotectedHeader) {
|
|
13
|
-
if (this.
|
|
17
|
+
if (this.unprotectedHeader) {
|
|
14
18
|
throw new TypeError('setUnprotectedHeader can only be called once');
|
|
15
19
|
}
|
|
16
|
-
this.
|
|
20
|
+
this.unprotectedHeader = unprotectedHeader;
|
|
17
21
|
return this;
|
|
18
22
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
get _protectedHeader() {
|
|
23
|
-
return signatureRef.get(this).protectedHeader;
|
|
23
|
+
addSignature(...args) {
|
|
24
|
+
return this.parent.addSignature(...args);
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
sign(...args) {
|
|
27
|
+
return this.parent.sign(...args);
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
return
|
|
29
|
+
done() {
|
|
30
|
+
return this.parent;
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
export class GeneralSign {
|
|
@@ -35,8 +36,7 @@ export class GeneralSign {
|
|
|
35
36
|
this._payload = payload;
|
|
36
37
|
}
|
|
37
38
|
addSignature(key, options) {
|
|
38
|
-
const signature = new IndividualSignature();
|
|
39
|
-
signatureRef.set(signature, { key, options });
|
|
39
|
+
const signature = new IndividualSignature(this, key, options);
|
|
40
40
|
this._signatures.push(signature);
|
|
41
41
|
return signature;
|
|
42
42
|
}
|
|
@@ -48,23 +48,19 @@ export class GeneralSign {
|
|
|
48
48
|
signatures: [],
|
|
49
49
|
payload: '',
|
|
50
50
|
};
|
|
51
|
-
let
|
|
52
|
-
|
|
53
|
-
const { protectedHeader, unprotectedHeader, options, key } = signatureRef.get(sig);
|
|
51
|
+
for (let i = 0; i < this._signatures.length; i++) {
|
|
52
|
+
const signature = this._signatures[i];
|
|
54
53
|
const flattened = new FlattenedSign(this._payload);
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
flattened.setProtectedHeader(signature.protectedHeader);
|
|
55
|
+
flattened.setUnprotectedHeader(signature.unprotectedHeader);
|
|
56
|
+
const { payload, ...rest } = await flattened.sign(signature.key, signature.options);
|
|
57
|
+
if (i === 0) {
|
|
58
|
+
jws.payload = payload;
|
|
57
59
|
}
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
+
else if (jws.payload !== payload) {
|
|
61
|
+
throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)');
|
|
60
62
|
}
|
|
61
|
-
const { payload, ...rest } = await flattened.sign(key, options);
|
|
62
|
-
payloads.add(payload);
|
|
63
|
-
jws.payload = payload;
|
|
64
63
|
jws.signatures.push(rest);
|
|
65
|
-
}));
|
|
66
|
-
if (payloads.size !== 1) {
|
|
67
|
-
throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)');
|
|
68
64
|
}
|
|
69
65
|
return jws;
|
|
70
66
|
}
|
package/dist/node/esm/lib/cek.js
CHANGED
|
@@ -2,18 +2,17 @@ import { JOSENotSupported } from '../util/errors.js';
|
|
|
2
2
|
import random from '../runtime/random.js';
|
|
3
3
|
export function bitLength(alg) {
|
|
4
4
|
switch (alg) {
|
|
5
|
-
case 'A128CBC-HS256':
|
|
6
|
-
return 256;
|
|
7
|
-
case 'A192CBC-HS384':
|
|
8
|
-
return 384;
|
|
9
|
-
case 'A256CBC-HS512':
|
|
10
|
-
return 512;
|
|
11
5
|
case 'A128GCM':
|
|
12
6
|
return 128;
|
|
13
7
|
case 'A192GCM':
|
|
14
8
|
return 192;
|
|
15
9
|
case 'A256GCM':
|
|
10
|
+
case 'A128CBC-HS256':
|
|
16
11
|
return 256;
|
|
12
|
+
case 'A192CBC-HS384':
|
|
13
|
+
return 384;
|
|
14
|
+
case 'A256CBC-HS512':
|
|
15
|
+
return 512;
|
|
17
16
|
default:
|
|
18
17
|
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
|
19
18
|
}
|
|
@@ -40,7 +40,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
|
40
40
|
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
41
41
|
partyVInfo = base64url(joseHeader.apv);
|
|
42
42
|
}
|
|
43
|
-
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, parseInt(alg.substr(-5, 3), 10)
|
|
43
|
+
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.substr(-5, 3), 10), partyUInfo, partyVInfo);
|
|
44
44
|
if (alg === 'ECDH-ES')
|
|
45
45
|
return sharedSecret;
|
|
46
46
|
if (encryptedKey === undefined)
|
|
@@ -29,7 +29,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
29
29
|
let { epk: ephemeralKey } = providedParameters;
|
|
30
30
|
ephemeralKey || (ephemeralKey = await ECDH.generateEpk(key));
|
|
31
31
|
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
|
|
32
|
-
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, parseInt(alg.substr(-5, 3), 10)
|
|
32
|
+
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.substr(-5, 3), 10), apu, apv);
|
|
33
33
|
parameters = { epk: { x, y, crv, kty } };
|
|
34
34
|
if (apu)
|
|
35
35
|
parameters.apu = base64url(apu);
|
package/dist/node/esm/lib/iv.js
CHANGED
|
@@ -2,24 +2,17 @@ import { JOSENotSupported } from '../util/errors.js';
|
|
|
2
2
|
import random from '../runtime/random.js';
|
|
3
3
|
export function bitLength(alg) {
|
|
4
4
|
switch (alg) {
|
|
5
|
-
case 'A128CBC-HS256':
|
|
6
|
-
return 128;
|
|
7
5
|
case 'A128GCM':
|
|
8
|
-
return 96;
|
|
9
6
|
case 'A128GCMKW':
|
|
10
|
-
return 96;
|
|
11
|
-
case 'A192CBC-HS384':
|
|
12
|
-
return 128;
|
|
13
7
|
case 'A192GCM':
|
|
14
|
-
return 96;
|
|
15
8
|
case 'A192GCMKW':
|
|
16
|
-
return 96;
|
|
17
|
-
case 'A256CBC-HS512':
|
|
18
|
-
return 128;
|
|
19
9
|
case 'A256GCM':
|
|
20
|
-
return 96;
|
|
21
10
|
case 'A256GCMKW':
|
|
22
11
|
return 96;
|
|
12
|
+
case 'A128CBC-HS256':
|
|
13
|
+
case 'A192CBC-HS384':
|
|
14
|
+
case 'A256CBC-HS512':
|
|
15
|
+
return 128;
|
|
23
16
|
default:
|
|
24
17
|
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
|
25
18
|
}
|
|
@@ -8,6 +8,7 @@ import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
|
8
8
|
import isKeyObject from './is_key_object.js';
|
|
9
9
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
10
10
|
import supported from './ciphers.js';
|
|
11
|
+
import { types } from './is_key_like.js';
|
|
11
12
|
function checkKeySize(key, alg) {
|
|
12
13
|
if (key.symmetricKeySize << 3 !== parseInt(alg.substr(1, 3), 10)) {
|
|
13
14
|
throw new TypeError(`Invalid key size for alg: ${alg}`);
|
|
@@ -24,9 +25,9 @@ function ensureKeyObject(key, alg, usage) {
|
|
|
24
25
|
checkEncCryptoKey(key, alg, usage);
|
|
25
26
|
return KeyObject.from(key);
|
|
26
27
|
}
|
|
27
|
-
throw new TypeError(invalidKeyInput(key,
|
|
28
|
+
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
28
29
|
}
|
|
29
|
-
export const wrap =
|
|
30
|
+
export const wrap = (alg, key, cek) => {
|
|
30
31
|
const size = parseInt(alg.substr(1, 3), 10);
|
|
31
32
|
const algorithm = `aes${size}-wrap`;
|
|
32
33
|
if (!supported(algorithm)) {
|
|
@@ -37,7 +38,7 @@ export const wrap = async (alg, key, cek) => {
|
|
|
37
38
|
const cipher = createCipheriv(algorithm, keyObject, Buffer.alloc(8, 0xa6));
|
|
38
39
|
return concat(cipher.update(cek), cipher.final());
|
|
39
40
|
};
|
|
40
|
-
export const unwrap =
|
|
41
|
+
export const unwrap = (alg, key, encryptedKey) => {
|
|
41
42
|
const size = parseInt(alg.substr(1, 3), 10);
|
|
42
43
|
const algorithm = `aes${size}-wrap`;
|
|
43
44
|
if (!supported(algorithm)) {
|
|
@@ -3,6 +3,7 @@ import { Buffer } from 'buffer';
|
|
|
3
3
|
import { isCryptoKey } from './webcrypto.js';
|
|
4
4
|
import isKeyObject from './is_key_object.js';
|
|
5
5
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
6
|
+
import { types } from './is_key_like.js';
|
|
6
7
|
const genericExport = (keyType, keyFormat, key) => {
|
|
7
8
|
let keyObject;
|
|
8
9
|
if (isCryptoKey(key)) {
|
|
@@ -15,7 +16,7 @@ const genericExport = (keyType, keyFormat, key) => {
|
|
|
15
16
|
keyObject = key;
|
|
16
17
|
}
|
|
17
18
|
else {
|
|
18
|
-
throw new TypeError(invalidKeyInput(key,
|
|
19
|
+
throw new TypeError(invalidKeyInput(key, ...types));
|
|
19
20
|
}
|
|
20
21
|
if (keyObject.type !== keyType) {
|
|
21
22
|
throw new TypeError(`key is not a ${keyType} key`);
|
|
@@ -10,7 +10,8 @@ import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
|
10
10
|
import isKeyObject from './is_key_object.js';
|
|
11
11
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
12
12
|
import supported from './ciphers.js';
|
|
13
|
-
|
|
13
|
+
import { types } from './is_key_like.js';
|
|
14
|
+
function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
14
15
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
15
16
|
if (isKeyObject(cek)) {
|
|
16
17
|
cek = cek.export();
|
|
@@ -44,7 +45,7 @@ async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
44
45
|
}
|
|
45
46
|
return plaintext;
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
+
function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
48
49
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
49
50
|
const algorithm = `aes-${keySize}-gcm`;
|
|
50
51
|
if (!supported(algorithm)) {
|
|
@@ -64,7 +65,7 @@ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
64
65
|
throw new JWEDecryptionFailed();
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
|
-
const decrypt =
|
|
68
|
+
const decrypt = (enc, cek, ciphertext, iv, tag, aad) => {
|
|
68
69
|
let key;
|
|
69
70
|
if (isCryptoKey(cek)) {
|
|
70
71
|
checkEncCryptoKey(cek, enc, 'decrypt');
|
|
@@ -74,7 +75,7 @@ const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
|
|
|
74
75
|
key = cek;
|
|
75
76
|
}
|
|
76
77
|
else {
|
|
77
|
-
throw new TypeError(invalidKeyInput(cek,
|
|
78
|
+
throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array'));
|
|
78
79
|
}
|
|
79
80
|
checkCekLength(enc, key);
|
|
80
81
|
checkIvLength(enc, iv);
|
|
@@ -8,8 +8,9 @@ import { isCryptoKey } from './webcrypto.js';
|
|
|
8
8
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
9
9
|
import isKeyObject from './is_key_object.js';
|
|
10
10
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
11
|
+
import { types } from './is_key_like.js';
|
|
11
12
|
const generateKeyPair = promisify(generateKeyPairCb);
|
|
12
|
-
export const deriveKey =
|
|
13
|
+
export const deriveKey = (publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) => {
|
|
13
14
|
let publicKey;
|
|
14
15
|
if (isCryptoKey(publicKee)) {
|
|
15
16
|
checkEncCryptoKey(publicKee, 'ECDH-ES');
|
|
@@ -19,7 +20,7 @@ export const deriveKey = async (publicKee, privateKee, algorithm, keyLength, apu
|
|
|
19
20
|
publicKey = publicKee;
|
|
20
21
|
}
|
|
21
22
|
else {
|
|
22
|
-
throw new TypeError(invalidKeyInput(publicKee,
|
|
23
|
+
throw new TypeError(invalidKeyInput(publicKee, ...types));
|
|
23
24
|
}
|
|
24
25
|
let privateKey;
|
|
25
26
|
if (isCryptoKey(privateKee)) {
|
|
@@ -30,7 +31,7 @@ export const deriveKey = async (publicKee, privateKee, algorithm, keyLength, apu
|
|
|
30
31
|
privateKey = privateKee;
|
|
31
32
|
}
|
|
32
33
|
else {
|
|
33
|
-
throw new TypeError(invalidKeyInput(privateKee,
|
|
34
|
+
throw new TypeError(invalidKeyInput(privateKee, ...types));
|
|
34
35
|
}
|
|
35
36
|
const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
|
|
36
37
|
const sharedSecret = diffieHellman({ privateKey, publicKey });
|
|
@@ -45,7 +46,7 @@ export const generateEpk = async (kee) => {
|
|
|
45
46
|
key = kee;
|
|
46
47
|
}
|
|
47
48
|
else {
|
|
48
|
-
throw new TypeError(invalidKeyInput(kee,
|
|
49
|
+
throw new TypeError(invalidKeyInput(kee, ...types));
|
|
49
50
|
}
|
|
50
51
|
switch (key.asymmetricKeyType) {
|
|
51
52
|
case 'x25519':
|
|
@@ -9,7 +9,8 @@ import isKeyObject from './is_key_object.js';
|
|
|
9
9
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
10
10
|
import { JOSENotSupported } from '../util/errors.js';
|
|
11
11
|
import supported from './ciphers.js';
|
|
12
|
-
|
|
12
|
+
import { types } from './is_key_like.js';
|
|
13
|
+
function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
13
14
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
14
15
|
if (isKeyObject(cek)) {
|
|
15
16
|
cek = cek.export();
|
|
@@ -26,7 +27,7 @@ async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
26
27
|
const tag = cbcTag(aad, iv, ciphertext, macSize, macKey, keySize);
|
|
27
28
|
return { ciphertext, tag };
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
function gcmEncrypt(enc, plaintext, cek, iv, aad) {
|
|
30
31
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
31
32
|
const algorithm = `aes-${keySize}-gcm`;
|
|
32
33
|
if (!supported(algorithm)) {
|
|
@@ -41,7 +42,7 @@ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
41
42
|
const tag = cipher.getAuthTag();
|
|
42
43
|
return { ciphertext, tag };
|
|
43
44
|
}
|
|
44
|
-
const encrypt =
|
|
45
|
+
const encrypt = (enc, plaintext, cek, iv, aad) => {
|
|
45
46
|
let key;
|
|
46
47
|
if (isCryptoKey(cek)) {
|
|
47
48
|
checkEncCryptoKey(cek, enc, 'encrypt');
|
|
@@ -51,7 +52,7 @@ const encrypt = async (enc, plaintext, cek, iv, aad) => {
|
|
|
51
52
|
key = cek;
|
|
52
53
|
}
|
|
53
54
|
else {
|
|
54
|
-
throw new TypeError(invalidKeyInput(cek,
|
|
55
|
+
throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array'));
|
|
55
56
|
}
|
|
56
57
|
checkCekLength(enc, key);
|
|
57
58
|
checkIvLength(enc, iv);
|
|
@@ -4,6 +4,7 @@ import { JOSENotSupported } from '../util/errors.js';
|
|
|
4
4
|
import { isCryptoKey } from './webcrypto.js';
|
|
5
5
|
import isKeyObject from './is_key_object.js';
|
|
6
6
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
7
|
+
import { types } from './is_key_like.js';
|
|
7
8
|
const p256 = Buffer.from([42, 134, 72, 206, 61, 3, 1, 7]);
|
|
8
9
|
const p384 = Buffer.from([43, 129, 4, 0, 34]);
|
|
9
10
|
const p521 = Buffer.from([43, 129, 4, 0, 35]);
|
|
@@ -33,7 +34,7 @@ const getNamedCurve = (kee, raw) => {
|
|
|
33
34
|
key = kee;
|
|
34
35
|
}
|
|
35
36
|
else {
|
|
36
|
-
throw new TypeError(invalidKeyInput(kee,
|
|
37
|
+
throw new TypeError(invalidKeyInput(kee, ...types));
|
|
37
38
|
}
|
|
38
39
|
if (key.type === 'secret') {
|
|
39
40
|
throw new TypeError('only "private" or "public" type keys can be used for this operation');
|
|
@@ -3,10 +3,11 @@ import { isCryptoKey } from './webcrypto.js';
|
|
|
3
3
|
import { checkSigCryptoKey } from '../lib/crypto_key.js';
|
|
4
4
|
import getSecretKey from './secret_key.js';
|
|
5
5
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
6
|
+
import { types } from './is_key_like.js';
|
|
6
7
|
export default function getSignVerifyKey(alg, key, usage) {
|
|
7
8
|
if (key instanceof Uint8Array) {
|
|
8
9
|
if (!alg.startsWith('HS')) {
|
|
9
|
-
throw new TypeError(invalidKeyInput(key,
|
|
10
|
+
throw new TypeError(invalidKeyInput(key, ...types));
|
|
10
11
|
}
|
|
11
12
|
return getSecretKey(key);
|
|
12
13
|
}
|
|
@@ -17,5 +18,5 @@ export default function getSignVerifyKey(alg, key, usage) {
|
|
|
17
18
|
checkSigCryptoKey(key, alg, usage);
|
|
18
19
|
return KeyObject.from(key);
|
|
19
20
|
}
|
|
20
|
-
throw new TypeError(invalidKeyInput(key,
|
|
21
|
+
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
21
22
|
}
|
|
@@ -6,6 +6,7 @@ import getNamedCurve from './get_named_curve.js';
|
|
|
6
6
|
import { isCryptoKey } from './webcrypto.js';
|
|
7
7
|
import isKeyObject from './is_key_object.js';
|
|
8
8
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
9
|
+
import { types } from './is_key_like.js';
|
|
9
10
|
const [major, minor] = process.version
|
|
10
11
|
.substr(1)
|
|
11
12
|
.split('.')
|
|
@@ -29,7 +30,7 @@ const keyToJWK = (key) => {
|
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
else {
|
|
32
|
-
throw new TypeError(invalidKeyInput(key,
|
|
33
|
+
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
33
34
|
}
|
|
34
35
|
if (jwkExportSupported) {
|
|
35
36
|
return keyObject.export({ format: 'jwk' });
|
|
@@ -9,6 +9,7 @@ import { isCryptoKey } from './webcrypto.js';
|
|
|
9
9
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
10
10
|
import isKeyObject from './is_key_object.js';
|
|
11
11
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
12
|
+
import { types } from './is_key_like.js';
|
|
12
13
|
const pbkdf2 = promisify(pbkdf2cb);
|
|
13
14
|
function getPassword(key, alg) {
|
|
14
15
|
if (isKeyObject(key)) {
|
|
@@ -21,7 +22,7 @@ function getPassword(key, alg) {
|
|
|
21
22
|
checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey');
|
|
22
23
|
return KeyObject.from(key).export();
|
|
23
24
|
}
|
|
24
|
-
throw new TypeError(invalidKeyInput(key,
|
|
25
|
+
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
25
26
|
}
|
|
26
27
|
export const encrypt = async (alg, key, cek, p2c = Math.floor(Math.random() * 2049) + 2048, p2s = random(new Uint8Array(16))) => {
|
|
27
28
|
checkP2s(p2s);
|
|
@@ -4,6 +4,7 @@ import { isCryptoKey } from './webcrypto.js';
|
|
|
4
4
|
import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
5
5
|
import isKeyObject from './is_key_object.js';
|
|
6
6
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
7
|
+
import { types } from './is_key_like.js';
|
|
7
8
|
const checkKey = (key, alg) => {
|
|
8
9
|
if (key.asymmetricKeyType !== 'rsa') {
|
|
9
10
|
throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa');
|
|
@@ -45,16 +46,16 @@ function ensureKeyObject(key, alg, ...usages) {
|
|
|
45
46
|
checkEncCryptoKey(key, alg, ...usages);
|
|
46
47
|
return KeyObject.from(key);
|
|
47
48
|
}
|
|
48
|
-
throw new TypeError(invalidKeyInput(key,
|
|
49
|
+
throw new TypeError(invalidKeyInput(key, ...types));
|
|
49
50
|
}
|
|
50
|
-
export const encrypt =
|
|
51
|
+
export const encrypt = (alg, key, cek) => {
|
|
51
52
|
const padding = resolvePadding(alg);
|
|
52
53
|
const oaepHash = resolveOaepHash(alg);
|
|
53
54
|
const keyObject = ensureKeyObject(key, alg, 'wrapKey', 'encrypt');
|
|
54
55
|
checkKey(keyObject, alg);
|
|
55
56
|
return publicEncrypt({ key: keyObject, oaepHash, padding }, cek);
|
|
56
57
|
};
|
|
57
|
-
export const decrypt =
|
|
58
|
+
export const decrypt = (alg, key, encryptedKey) => {
|
|
58
59
|
const padding = resolvePadding(alg);
|
|
59
60
|
const oaepHash = resolveOaepHash(alg);
|
|
60
61
|
const keyObject = ensureKeyObject(key, alg, 'unwrapKey', 'decrypt');
|
package/dist/types/index.d.ts
CHANGED
|
@@ -42,4 +42,4 @@ export type { GenerateKeyPairResult, GenerateKeyPairOptions } from './key/genera
|
|
|
42
42
|
export { generateSecret } from './key/generate_secret';
|
|
43
43
|
export type { GenerateSecretOptions } from './key/generate_secret';
|
|
44
44
|
export * as base64url from './util/base64url';
|
|
45
|
-
export type { KeyLike, JWK, FlattenedJWSInput, GeneralJWSInput, FlattenedJWS, GeneralJWS, JoseHeaderParameters, JWSHeaderParameters, JWEKeyManagementHeaderParameters, FlattenedJWE, GeneralJWE, JWEHeaderParameters, CritOption, DeflateOption, DecryptOptions, EncryptOptions, JWTClaimVerificationOptions, VerifyOptions, SignOptions, JWTPayload, DeflateFunction, InflateFunction, FlattenedDecryptResult, GeneralDecryptResult, CompactDecryptResult, FlattenedVerifyResult, GeneralVerifyResult, CompactVerifyResult, JWTVerifyResult, JWTDecryptResult, ResolvedKey, } from './types';
|
|
45
|
+
export type { KeyLike, JWK, FlattenedJWSInput, GeneralJWSInput, FlattenedJWS, GeneralJWS, JoseHeaderParameters, JWSHeaderParameters, JWEKeyManagementHeaderParameters, FlattenedJWE, GeneralJWE, JWEHeaderParameters, CritOption, DeflateOption, DecryptOptions, EncryptOptions, JWTClaimVerificationOptions, VerifyOptions, SignOptions, JWTPayload, DeflateFunction, InflateFunction, FlattenedDecryptResult, GeneralDecryptResult, CompactDecryptResult, FlattenedVerifyResult, GeneralVerifyResult, CompactVerifyResult, JWTVerifyResult, JWTDecryptResult, ResolvedKey, CompactJWEHeaderParameters, CompactJWSHeaderParameters, JWTHeaderParameters, } from './types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { KeyLike, DecryptOptions,
|
|
2
|
-
export interface CompactDecryptGetKey extends GetKeyFunction<
|
|
1
|
+
import type { KeyLike, DecryptOptions, CompactJWEHeaderParameters, GetKeyFunction, FlattenedJWE, CompactDecryptResult, ResolvedKey } from '../../types';
|
|
2
|
+
export interface CompactDecryptGetKey extends GetKeyFunction<CompactJWEHeaderParameters, FlattenedJWE> {
|
|
3
3
|
}
|
|
4
4
|
export declare function compactDecrypt(jwe: string | Uint8Array, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<CompactDecryptResult>;
|
|
5
5
|
export declare function compactDecrypt(jwe: string | Uint8Array, getKey: CompactDecryptGetKey, options?: DecryptOptions): Promise<CompactDecryptResult & ResolvedKey>;
|