jose 3.17.0 → 3.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -3
- package/dist/browser/jwe/compact/decrypt.js +5 -1
- package/dist/browser/jwe/flattened/decrypt.js +5 -0
- package/dist/browser/jwk/embedded.js +3 -3
- package/dist/browser/jwk/from_key_like.js +2 -2
- package/dist/browser/jwk/parse.js +2 -31
- package/dist/browser/jwks/remote.js +7 -10
- package/dist/browser/jws/compact/verify.js +5 -1
- package/dist/browser/jws/flattened/verify.js +5 -0
- package/dist/browser/jwt/decrypt.js +5 -1
- package/dist/browser/jwt/encrypt.js +1 -1
- package/dist/browser/{lib/jwt_producer.js → jwt/produce.js} +4 -4
- package/dist/browser/jwt/sign.js +1 -1
- package/dist/browser/jwt/unsecured.js +1 -1
- package/dist/browser/jwt/verify.js +5 -1
- package/dist/browser/key/export.js +12 -0
- package/dist/browser/key/import.js +119 -0
- package/dist/browser/lib/check_key_type.js +33 -16
- package/dist/browser/lib/decrypt_key_management.js +37 -37
- package/dist/browser/lib/encrypt_key_management.js +2 -2
- package/dist/browser/lib/format_pem.js +4 -0
- package/dist/browser/runtime/asn1.js +119 -0
- package/dist/browser/runtime/base64url.js +12 -7
- package/dist/browser/runtime/fetch_jwks.js +18 -5
- package/dist/browser/runtime/is_key_like.js +5 -0
- package/dist/browser/util/errors.js +10 -3
- package/dist/node/cjs/jwe/compact/decrypt.js +5 -1
- package/dist/node/cjs/jwe/flattened/decrypt.js +5 -0
- package/dist/node/cjs/jwk/embedded.js +3 -3
- package/dist/node/cjs/jwk/from_key_like.js +2 -2
- package/dist/node/cjs/jwk/parse.js +2 -31
- package/dist/node/cjs/jwks/remote.js +7 -10
- package/dist/node/cjs/jws/compact/verify.js +5 -1
- package/dist/node/cjs/jws/flattened/verify.js +5 -0
- package/dist/node/cjs/jwt/decrypt.js +5 -1
- package/dist/node/cjs/jwt/encrypt.js +2 -2
- package/dist/node/cjs/{lib/jwt_producer.js → jwt/produce.js} +5 -4
- package/dist/node/cjs/jwt/sign.js +2 -2
- package/dist/node/cjs/jwt/unsecured.js +2 -2
- package/dist/node/cjs/jwt/verify.js +5 -1
- package/dist/node/cjs/key/export.js +18 -0
- package/dist/node/cjs/key/import.js +126 -0
- package/dist/node/cjs/lib/check_key_type.js +33 -16
- package/dist/node/cjs/lib/decrypt_key_management.js +37 -37
- package/dist/node/cjs/lib/encrypt_key_management.js +2 -2
- package/dist/node/cjs/lib/format_pem.js +6 -0
- package/dist/node/cjs/runtime/asn1.js +46 -0
- package/dist/node/cjs/runtime/base64url.js +5 -1
- package/dist/node/cjs/runtime/fetch_jwks.js +5 -1
- package/dist/node/cjs/runtime/is_key_like.js +11 -0
- package/dist/node/cjs/util/errors.js +12 -4
- package/dist/node/esm/jwe/compact/decrypt.js +5 -1
- package/dist/node/esm/jwe/flattened/decrypt.js +5 -0
- package/dist/node/esm/jwk/embedded.js +3 -3
- package/dist/node/esm/jwk/from_key_like.js +2 -2
- package/dist/node/esm/jwk/parse.js +2 -31
- package/dist/node/esm/jwks/remote.js +7 -10
- package/dist/node/esm/jws/compact/verify.js +5 -1
- package/dist/node/esm/jws/flattened/verify.js +5 -0
- package/dist/node/esm/jwt/decrypt.js +5 -1
- package/dist/node/esm/jwt/encrypt.js +1 -1
- package/dist/node/esm/{lib/jwt_producer.js → jwt/produce.js} +4 -4
- package/dist/node/esm/jwt/sign.js +1 -1
- package/dist/node/esm/jwt/unsecured.js +1 -1
- package/dist/node/esm/jwt/verify.js +5 -1
- package/dist/node/esm/key/export.js +12 -0
- package/dist/node/esm/key/import.js +119 -0
- package/dist/node/esm/lib/check_key_type.js +33 -16
- package/dist/node/esm/lib/decrypt_key_management.js +37 -37
- package/dist/node/esm/lib/encrypt_key_management.js +2 -2
- package/dist/node/esm/lib/format_pem.js +4 -0
- package/dist/node/esm/runtime/asn1.js +39 -0
- package/dist/node/esm/runtime/base64url.js +2 -0
- package/dist/node/esm/runtime/fetch_jwks.js +6 -2
- package/dist/node/esm/runtime/is_key_like.js +8 -0
- package/dist/node/esm/util/errors.js +10 -3
- package/dist/types/jwe/compact/decrypt.d.ts +3 -2
- package/dist/types/jwe/compact/encrypt.d.ts +1 -1
- package/dist/types/jwe/flattened/decrypt.d.ts +3 -2
- package/dist/types/jwe/flattened/encrypt.d.ts +1 -1
- package/dist/types/jwe/general/decrypt.d.ts +3 -2
- package/dist/types/jwk/embedded.d.ts +2 -3
- package/dist/types/jwk/from_key_like.d.ts +1 -1
- package/dist/types/jwk/parse.d.ts +1 -1
- package/dist/types/jws/compact/sign.d.ts +1 -1
- package/dist/types/jws/compact/verify.d.ts +3 -2
- package/dist/types/jws/flattened/sign.d.ts +1 -1
- package/dist/types/jws/flattened/verify.d.ts +3 -2
- package/dist/types/jws/general/sign.d.ts +1 -1
- package/dist/types/jws/general/verify.d.ts +3 -2
- package/dist/types/jwt/decrypt.d.ts +3 -2
- package/dist/types/jwt/encrypt.d.ts +2 -2
- package/dist/types/{lib/jwt_producer.d.ts → jwt/produce.d.ts} +1 -1
- package/dist/types/jwt/sign.d.ts +2 -2
- package/dist/types/jwt/unsecured.d.ts +1 -1
- package/dist/types/jwt/verify.d.ts +3 -2
- package/dist/types/key/export.d.ts +5 -0
- package/dist/types/key/import.d.ts +9 -0
- package/dist/types/types.d.ts +101 -5
- package/dist/types/util/errors.d.ts +5 -0
- package/dist/types/util/generate_key_pair.d.ts +2 -2
- package/dist/types/util/generate_secret.d.ts +1 -1
- package/package.json +20 -8
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { decode as decodeBase64URL, encodeBase64, decodeBase64 } from '../runtime/base64url.js';
|
|
2
|
+
import { fromSPKI as importPublic } from '../runtime/asn1.js';
|
|
3
|
+
import { fromPKCS8 as importPrivate } from '../runtime/asn1.js';
|
|
4
|
+
import asKeyObject from '../runtime/jwk_to_key.js';
|
|
5
|
+
import { JOSENotSupported } from '../util/errors.js';
|
|
6
|
+
import formatPEM from '../lib/format_pem.js';
|
|
7
|
+
import isObject from '../lib/is_object.js';
|
|
8
|
+
function getElement(seq) {
|
|
9
|
+
let result = [];
|
|
10
|
+
let next = 0;
|
|
11
|
+
while (next < seq.length) {
|
|
12
|
+
let nextPart = parseElement(seq.subarray(next));
|
|
13
|
+
result.push(nextPart);
|
|
14
|
+
next += nextPart.byteLength;
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
function parseElement(bytes) {
|
|
19
|
+
let position = 0;
|
|
20
|
+
let tag = bytes[0] & 0x1f;
|
|
21
|
+
position++;
|
|
22
|
+
if (tag === 0x1f) {
|
|
23
|
+
tag = 0;
|
|
24
|
+
while (bytes[position] >= 0x80) {
|
|
25
|
+
tag = tag * 128 + bytes[position] - 0x80;
|
|
26
|
+
position++;
|
|
27
|
+
}
|
|
28
|
+
tag = tag * 128 + bytes[position] - 0x80;
|
|
29
|
+
position++;
|
|
30
|
+
}
|
|
31
|
+
let length = 0;
|
|
32
|
+
if (bytes[position] < 0x80) {
|
|
33
|
+
length = bytes[position];
|
|
34
|
+
position++;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
let numberOfDigits = bytes[position] & 0x7f;
|
|
38
|
+
position++;
|
|
39
|
+
length = 0;
|
|
40
|
+
for (let i = 0; i < numberOfDigits; i++) {
|
|
41
|
+
length = length * 256 + bytes[position];
|
|
42
|
+
position++;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (length === 0x80) {
|
|
46
|
+
length = 0;
|
|
47
|
+
while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) {
|
|
48
|
+
length++;
|
|
49
|
+
}
|
|
50
|
+
const byteLength = position + length + 2;
|
|
51
|
+
return {
|
|
52
|
+
byteLength,
|
|
53
|
+
contents: bytes.subarray(position, position + length),
|
|
54
|
+
raw: bytes.subarray(0, byteLength),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const byteLength = position + length;
|
|
58
|
+
return {
|
|
59
|
+
byteLength,
|
|
60
|
+
contents: bytes.subarray(position, byteLength),
|
|
61
|
+
raw: bytes.subarray(0, byteLength),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function spkiFromX509(buf) {
|
|
65
|
+
return encodeBase64(getElement(getElement(parseElement(buf).contents)[0].contents)[6].raw);
|
|
66
|
+
}
|
|
67
|
+
function getSPKI(x509) {
|
|
68
|
+
const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '');
|
|
69
|
+
const raw = decodeBase64(pem);
|
|
70
|
+
return formatPEM(spkiFromX509(raw), 'PUBLIC KEY');
|
|
71
|
+
}
|
|
72
|
+
export async function importSPKI(spki, alg, options) {
|
|
73
|
+
if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {
|
|
74
|
+
throw new TypeError('"spki" must be SPKI formatted string');
|
|
75
|
+
}
|
|
76
|
+
return importPublic(spki, alg, options);
|
|
77
|
+
}
|
|
78
|
+
export async function importX509(x509, alg, options) {
|
|
79
|
+
if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {
|
|
80
|
+
throw new TypeError('"x509" must be X.509 formatted string');
|
|
81
|
+
}
|
|
82
|
+
const spki = getSPKI(x509);
|
|
83
|
+
return importPublic(spki, alg, options);
|
|
84
|
+
}
|
|
85
|
+
export async function importPKCS8(pkcs8, alg, options) {
|
|
86
|
+
if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {
|
|
87
|
+
throw new TypeError('"pkcs8" must be PCKS8 formatted string');
|
|
88
|
+
}
|
|
89
|
+
return importPrivate(pkcs8, alg, options);
|
|
90
|
+
}
|
|
91
|
+
export async function importJWK(jwk, alg, octAsKeyObject) {
|
|
92
|
+
if (!isObject(jwk)) {
|
|
93
|
+
throw new TypeError('JWK must be an object');
|
|
94
|
+
}
|
|
95
|
+
alg || (alg = jwk.alg);
|
|
96
|
+
if (typeof alg !== 'string' || !alg) {
|
|
97
|
+
throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
|
|
98
|
+
}
|
|
99
|
+
switch (jwk.kty) {
|
|
100
|
+
case 'oct':
|
|
101
|
+
if (typeof jwk.k !== 'string' || !jwk.k) {
|
|
102
|
+
throw new TypeError('missing "k" (Key Value) Parameter value');
|
|
103
|
+
}
|
|
104
|
+
octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true);
|
|
105
|
+
if (octAsKeyObject) {
|
|
106
|
+
return asKeyObject({ ...jwk, alg, ext: false });
|
|
107
|
+
}
|
|
108
|
+
return decodeBase64URL(jwk.k);
|
|
109
|
+
case 'RSA':
|
|
110
|
+
if (jwk.oth !== undefined) {
|
|
111
|
+
throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
|
|
112
|
+
}
|
|
113
|
+
case 'EC':
|
|
114
|
+
case 'OKP':
|
|
115
|
+
return asKeyObject({ ...jwk, alg });
|
|
116
|
+
default:
|
|
117
|
+
throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -1,28 +1,45 @@
|
|
|
1
1
|
import invalidKeyInput from '../runtime/invalid_key_input.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import isKeyLike, { types } from '../runtime/is_key_like.js';
|
|
3
|
+
const symmetricTypeCheck = (key) => {
|
|
4
|
+
if (key instanceof Uint8Array)
|
|
5
|
+
return;
|
|
6
|
+
if (!isKeyLike(key)) {
|
|
7
|
+
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
5
8
|
}
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
alg.startsWith('PBES2') ||
|
|
9
|
-
alg.match(/^A\d{3}(?:GCM)?KW$/)) {
|
|
10
|
-
if (key instanceof Uint8Array || key.type === 'secret') {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
throw new TypeError('CryptoKey or KeyObject instances for symmetric algorithms must be of type "secret"');
|
|
9
|
+
if (key.type !== 'secret') {
|
|
10
|
+
throw new TypeError(`${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`);
|
|
14
11
|
}
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
};
|
|
13
|
+
const asymmetricTypeCheck = (key, usage) => {
|
|
14
|
+
if (!isKeyLike(key)) {
|
|
15
|
+
throw new TypeError(invalidKeyInput(key, ...types));
|
|
17
16
|
}
|
|
18
17
|
if (key.type === 'secret') {
|
|
19
|
-
throw new TypeError('
|
|
18
|
+
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`);
|
|
20
19
|
}
|
|
21
20
|
if (usage === 'sign' && key.type === 'public') {
|
|
22
|
-
throw new TypeError('
|
|
21
|
+
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`);
|
|
23
22
|
}
|
|
24
23
|
if (usage === 'decrypt' && key.type === 'public') {
|
|
25
|
-
throw new TypeError('
|
|
24
|
+
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`);
|
|
25
|
+
}
|
|
26
|
+
if (key.algorithm && usage === 'verify' && key.type === 'private') {
|
|
27
|
+
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`);
|
|
28
|
+
}
|
|
29
|
+
if (key.algorithm && usage === 'encrypt' && key.type === 'private') {
|
|
30
|
+
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const checkKeyType = (alg, key, usage) => {
|
|
34
|
+
const symmetric = alg.startsWith('HS') ||
|
|
35
|
+
alg === 'dir' ||
|
|
36
|
+
alg.startsWith('PBES2') ||
|
|
37
|
+
/^A\d{3}(?:GCM)?KW$/.test(alg);
|
|
38
|
+
if (symmetric) {
|
|
39
|
+
symmetricTypeCheck(key);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
asymmetricTypeCheck(key, usage);
|
|
26
43
|
}
|
|
27
44
|
};
|
|
28
45
|
export default checkKeyType;
|
|
@@ -6,83 +6,83 @@ import { unwrap as aesGcmKw } from '../runtime/aesgcmkw.js';
|
|
|
6
6
|
import { decode as base64url } from '../runtime/base64url.js';
|
|
7
7
|
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
|
|
8
8
|
import { bitLengths as cekLengths } from '../lib/cek.js';
|
|
9
|
-
import {
|
|
9
|
+
import { importJWK } from '../key/import.js';
|
|
10
10
|
import checkKeyType from './check_key_type.js';
|
|
11
|
-
|
|
12
|
-
if (!encryptedKey) {
|
|
13
|
-
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function assertHeaderParameter(joseHeader, parameter, name) {
|
|
17
|
-
if (joseHeader[parameter] === undefined) {
|
|
18
|
-
throw new JWEInvalid(`JOSE Header ${name} (${parameter}) missing`);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
11
|
+
import isObject from './is_object.js';
|
|
21
12
|
async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
22
13
|
checkKeyType(alg, key, 'decrypt');
|
|
23
14
|
switch (alg) {
|
|
24
15
|
case 'dir': {
|
|
25
|
-
if (encryptedKey !== undefined)
|
|
16
|
+
if (encryptedKey !== undefined)
|
|
26
17
|
throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
|
27
|
-
}
|
|
28
18
|
return key;
|
|
29
19
|
}
|
|
30
20
|
case 'ECDH-ES':
|
|
31
|
-
if (encryptedKey !== undefined)
|
|
21
|
+
if (encryptedKey !== undefined)
|
|
32
22
|
throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
|
33
|
-
}
|
|
34
23
|
case 'ECDH-ES+A128KW':
|
|
35
24
|
case 'ECDH-ES+A192KW':
|
|
36
25
|
case 'ECDH-ES+A256KW': {
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
if (!isObject(joseHeader.epk))
|
|
27
|
+
throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
28
|
+
if (!ECDH.ecdhAllowed(key))
|
|
39
29
|
throw new JOSENotSupported('ECDH-ES with the provided key is not allowed or not supported by your javascript runtime');
|
|
40
|
-
|
|
41
|
-
const epk = await parseJwk(joseHeader.epk, alg);
|
|
30
|
+
const epk = await importJWK(joseHeader.epk, alg);
|
|
42
31
|
let partyUInfo;
|
|
43
32
|
let partyVInfo;
|
|
44
|
-
if (joseHeader.apu !== undefined)
|
|
33
|
+
if (joseHeader.apu !== undefined) {
|
|
34
|
+
if (typeof joseHeader.apu !== 'string')
|
|
35
|
+
throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`);
|
|
45
36
|
partyUInfo = base64url(joseHeader.apu);
|
|
46
|
-
|
|
37
|
+
}
|
|
38
|
+
if (joseHeader.apv !== undefined) {
|
|
39
|
+
if (typeof joseHeader.apv !== 'string')
|
|
40
|
+
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
47
41
|
partyVInfo = base64url(joseHeader.apv);
|
|
42
|
+
}
|
|
48
43
|
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, parseInt(alg.substr(-5, 3), 10) || cekLengths.get(joseHeader.enc), partyUInfo, partyVInfo);
|
|
49
|
-
if (alg === 'ECDH-ES')
|
|
44
|
+
if (alg === 'ECDH-ES')
|
|
50
45
|
return sharedSecret;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return aesKw(kwAlg, sharedSecret, encryptedKey);
|
|
46
|
+
if (encryptedKey === undefined)
|
|
47
|
+
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
48
|
+
return aesKw(alg.substr(-6), sharedSecret, encryptedKey);
|
|
55
49
|
}
|
|
56
50
|
case 'RSA1_5':
|
|
57
51
|
case 'RSA-OAEP':
|
|
58
52
|
case 'RSA-OAEP-256':
|
|
59
53
|
case 'RSA-OAEP-384':
|
|
60
54
|
case 'RSA-OAEP-512': {
|
|
61
|
-
|
|
55
|
+
if (encryptedKey === undefined)
|
|
56
|
+
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
62
57
|
return rsaEs(alg, key, encryptedKey);
|
|
63
58
|
}
|
|
64
59
|
case 'PBES2-HS256+A128KW':
|
|
65
60
|
case 'PBES2-HS384+A192KW':
|
|
66
61
|
case 'PBES2-HS512+A256KW': {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
62
|
+
if (encryptedKey === undefined)
|
|
63
|
+
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
64
|
+
if (typeof joseHeader.p2c !== 'number')
|
|
65
|
+
throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
|
|
66
|
+
if (typeof joseHeader.p2s !== 'string')
|
|
67
|
+
throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
|
|
68
|
+
return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s));
|
|
73
69
|
}
|
|
74
70
|
case 'A128KW':
|
|
75
71
|
case 'A192KW':
|
|
76
72
|
case 'A256KW': {
|
|
77
|
-
|
|
73
|
+
if (encryptedKey === undefined)
|
|
74
|
+
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
78
75
|
return aesKw(alg, key, encryptedKey);
|
|
79
76
|
}
|
|
80
77
|
case 'A128GCMKW':
|
|
81
78
|
case 'A192GCMKW':
|
|
82
79
|
case 'A256GCMKW': {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
if (encryptedKey === undefined)
|
|
81
|
+
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
82
|
+
if (typeof joseHeader.iv !== 'string')
|
|
83
|
+
throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`);
|
|
84
|
+
if (typeof joseHeader.tag !== 'string')
|
|
85
|
+
throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`);
|
|
86
86
|
const iv = base64url(joseHeader.iv);
|
|
87
87
|
const tag = base64url(joseHeader.tag);
|
|
88
88
|
return aesGcmKw(alg, key, encryptedKey, iv, tag);
|
|
@@ -7,7 +7,7 @@ import { wrap as aesGcmKw } from '../runtime/aesgcmkw.js';
|
|
|
7
7
|
import { encode as base64url } from '../runtime/base64url.js';
|
|
8
8
|
import cekFactory, { bitLengths as cekLengths } from '../lib/cek.js';
|
|
9
9
|
import { JOSENotSupported } from '../util/errors.js';
|
|
10
|
-
import {
|
|
10
|
+
import { exportJWK } from '../key/export.js';
|
|
11
11
|
import checkKeyType from './check_key_type.js';
|
|
12
12
|
const generateCek = cekFactory(random);
|
|
13
13
|
async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
|
|
@@ -30,7 +30,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
30
30
|
const { apu, apv } = providedParameters;
|
|
31
31
|
let { epk: ephemeralKey } = providedParameters;
|
|
32
32
|
ephemeralKey || (ephemeralKey = await ECDH.generateEpk(key));
|
|
33
|
-
const { x, y, crv, kty } = await
|
|
33
|
+
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
|
|
34
34
|
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, parseInt(alg.substr(-5, 3), 10) || cekLengths.get(enc), apu, apv);
|
|
35
35
|
parameters = { epk: { x, y, crv, kty } };
|
|
36
36
|
if (apu)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createPrivateKey, createPublicKey } from 'crypto';
|
|
2
|
+
import { isCryptoKey, getKeyObject } from './webcrypto.js';
|
|
3
|
+
import isKeyObject from './is_key_object.js';
|
|
4
|
+
import invalidKeyInput from './invalid_key_input.js';
|
|
5
|
+
const genericExport = (keyType, keyFormat, key) => {
|
|
6
|
+
let keyObject;
|
|
7
|
+
if (isCryptoKey(key)) {
|
|
8
|
+
if (!key.extractable) {
|
|
9
|
+
throw new TypeError('CryptoKey is not extractable');
|
|
10
|
+
}
|
|
11
|
+
keyObject = getKeyObject(key);
|
|
12
|
+
}
|
|
13
|
+
else if (isKeyObject(key)) {
|
|
14
|
+
keyObject = key;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
throw new TypeError(invalidKeyInput(key, 'KeyObject', 'CryptoKey'));
|
|
18
|
+
}
|
|
19
|
+
if (keyObject.type !== keyType) {
|
|
20
|
+
throw new TypeError(`key is not a ${keyType} key`);
|
|
21
|
+
}
|
|
22
|
+
return keyObject.export({ format: 'pem', type: keyFormat });
|
|
23
|
+
};
|
|
24
|
+
export const toSPKI = (key) => {
|
|
25
|
+
return genericExport('public', 'spki', key);
|
|
26
|
+
};
|
|
27
|
+
export const toPKCS8 = (key) => {
|
|
28
|
+
return genericExport('private', 'pkcs8', key);
|
|
29
|
+
};
|
|
30
|
+
export const fromPKCS8 = (pem) => createPrivateKey({
|
|
31
|
+
key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, ''), 'base64'),
|
|
32
|
+
type: 'pkcs8',
|
|
33
|
+
format: 'der',
|
|
34
|
+
});
|
|
35
|
+
export const fromSPKI = (pem) => createPublicKey({
|
|
36
|
+
key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, ''), 'base64'),
|
|
37
|
+
type: 'spki',
|
|
38
|
+
format: 'der',
|
|
39
|
+
});
|
|
@@ -13,5 +13,7 @@ if (Buffer.isEncoding('base64url')) {
|
|
|
13
13
|
else {
|
|
14
14
|
encodeImpl = (input) => Buffer.from(input).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
15
15
|
}
|
|
16
|
+
export const decodeBase64 = (input) => Buffer.from(input, 'base64');
|
|
17
|
+
export const encodeBase64 = (input) => Buffer.from(input).toString('base64');
|
|
16
18
|
export const encode = encodeImpl;
|
|
17
19
|
export const decode = (input) => Buffer.from(normalize(input), 'base64');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { get as http } from 'http';
|
|
2
2
|
import { get as https } from 'https';
|
|
3
3
|
import { once } from 'events';
|
|
4
|
-
import { JOSEError } from '../util/errors.js';
|
|
4
|
+
import { JOSEError, JWKSTimeout } from '../util/errors.js';
|
|
5
5
|
import { concat, decoder } from '../lib/buffer_utils.js';
|
|
6
6
|
const protocols = {
|
|
7
7
|
'https:': https,
|
|
@@ -16,7 +16,11 @@ const fetchJwks = async (url, timeout, options) => {
|
|
|
16
16
|
agent,
|
|
17
17
|
timeout,
|
|
18
18
|
});
|
|
19
|
-
const [response] = await once(req, 'response');
|
|
19
|
+
const [response] = (await Promise.race([once(req, 'response'), once(req, 'timeout')]));
|
|
20
|
+
if (!response) {
|
|
21
|
+
req.destroy();
|
|
22
|
+
throw new JWKSTimeout();
|
|
23
|
+
}
|
|
20
24
|
if (response.statusCode !== 200) {
|
|
21
25
|
throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response');
|
|
22
26
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { isCryptoKey } from './webcrypto.js';
|
|
2
|
+
import isKeyObject from './is_key_object.js';
|
|
3
|
+
export default (key) => isKeyObject(key) || isCryptoKey(key);
|
|
4
|
+
const types = ['KeyObject'];
|
|
5
|
+
if (parseInt(process.versions.node) >= 16) {
|
|
6
|
+
types.push('CryptoKey');
|
|
7
|
+
}
|
|
8
|
+
export { types };
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export class JOSEError extends Error {
|
|
2
2
|
constructor(message) {
|
|
3
|
+
var _a;
|
|
3
4
|
super(message);
|
|
4
5
|
this.code = JOSEError.code;
|
|
5
6
|
this.name = this.constructor.name;
|
|
6
|
-
|
|
7
|
-
Error.captureStackTrace(this, this.constructor);
|
|
8
|
-
}
|
|
7
|
+
(_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor);
|
|
9
8
|
}
|
|
10
9
|
}
|
|
11
10
|
JOSEError.code = 'ERR_JOSE_GENERIC';
|
|
@@ -91,6 +90,14 @@ export class JWKSMultipleMatchingKeys extends JOSEError {
|
|
|
91
90
|
}
|
|
92
91
|
}
|
|
93
92
|
JWKSMultipleMatchingKeys.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';
|
|
93
|
+
export class JWKSTimeout extends JOSEError {
|
|
94
|
+
constructor() {
|
|
95
|
+
super(...arguments);
|
|
96
|
+
this.code = JWKSTimeout.code;
|
|
97
|
+
this.message = 'request timed out';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
JWKSTimeout.code = 'ERR_JWKS_TIMEOUT';
|
|
94
101
|
export class JWSSignatureVerificationFailed extends JOSEError {
|
|
95
102
|
constructor() {
|
|
96
103
|
super(...arguments);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { KeyLike, DecryptOptions, JWEHeaderParameters, GetKeyFunction, FlattenedJWE, CompactDecryptResult } from '../../types';
|
|
1
|
+
import type { KeyLike, DecryptOptions, JWEHeaderParameters, GetKeyFunction, FlattenedJWE, CompactDecryptResult, ResolvedKey } from '../../types';
|
|
2
2
|
export interface CompactDecryptGetKey extends GetKeyFunction<JWEHeaderParameters, FlattenedJWE> {
|
|
3
3
|
}
|
|
4
|
-
declare function compactDecrypt(jwe: string | Uint8Array, key: KeyLike |
|
|
4
|
+
declare function compactDecrypt(jwe: string | Uint8Array, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<CompactDecryptResult>;
|
|
5
|
+
declare function compactDecrypt(jwe: string | Uint8Array, getKey: CompactDecryptGetKey, options?: DecryptOptions): Promise<CompactDecryptResult & ResolvedKey>;
|
|
5
6
|
export { compactDecrypt };
|
|
6
7
|
export default compactDecrypt;
|
|
7
8
|
export type { KeyLike, DecryptOptions, CompactDecryptResult };
|
|
@@ -6,7 +6,7 @@ declare class CompactEncrypt {
|
|
|
6
6
|
setInitializationVector(iv: Uint8Array): this;
|
|
7
7
|
setProtectedHeader(protectedHeader: JWEHeaderParameters): this;
|
|
8
8
|
setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this;
|
|
9
|
-
encrypt(key: KeyLike, options?: EncryptOptions): Promise<string>;
|
|
9
|
+
encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise<string>;
|
|
10
10
|
}
|
|
11
11
|
export { CompactEncrypt };
|
|
12
12
|
export default CompactEncrypt;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { FlattenedDecryptResult, KeyLike, FlattenedJWE, JWEHeaderParameters, DecryptOptions, GetKeyFunction } from '../../types';
|
|
1
|
+
import type { FlattenedDecryptResult, KeyLike, FlattenedJWE, JWEHeaderParameters, DecryptOptions, GetKeyFunction, ResolvedKey } from '../../types';
|
|
2
2
|
export interface FlattenedDecryptGetKey extends GetKeyFunction<JWEHeaderParameters | undefined, FlattenedJWE> {
|
|
3
3
|
}
|
|
4
|
-
declare function flattenedDecrypt(jwe: FlattenedJWE, key: KeyLike |
|
|
4
|
+
declare function flattenedDecrypt(jwe: FlattenedJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<FlattenedDecryptResult>;
|
|
5
|
+
declare function flattenedDecrypt(jwe: FlattenedJWE, getKey: FlattenedDecryptGetKey, options?: DecryptOptions): Promise<FlattenedDecryptResult & ResolvedKey>;
|
|
5
6
|
export { flattenedDecrypt };
|
|
6
7
|
export default flattenedDecrypt;
|
|
7
8
|
export type { KeyLike, FlattenedJWE, JWEHeaderParameters, DecryptOptions, FlattenedDecryptResult };
|
|
@@ -16,7 +16,7 @@ declare class FlattenedEncrypt {
|
|
|
16
16
|
setAdditionalAuthenticatedData(aad: Uint8Array): this;
|
|
17
17
|
setContentEncryptionKey(cek: Uint8Array): this;
|
|
18
18
|
setInitializationVector(iv: Uint8Array): this;
|
|
19
|
-
encrypt(key: KeyLike, options?: EncryptOptions): Promise<FlattenedJWE>;
|
|
19
|
+
encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise<FlattenedJWE>;
|
|
20
20
|
}
|
|
21
21
|
export { FlattenedEncrypt };
|
|
22
22
|
export default FlattenedEncrypt;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { KeyLike, DecryptOptions, JWEHeaderParameters, GetKeyFunction, FlattenedJWE, GeneralJWE, GeneralDecryptResult } from '../../types';
|
|
1
|
+
import type { KeyLike, DecryptOptions, JWEHeaderParameters, GetKeyFunction, FlattenedJWE, GeneralJWE, GeneralDecryptResult, ResolvedKey } from '../../types';
|
|
2
2
|
export interface GeneralDecryptGetKey extends GetKeyFunction<JWEHeaderParameters, FlattenedJWE> {
|
|
3
3
|
}
|
|
4
|
-
declare function generalDecrypt(jwe: GeneralJWE, key: KeyLike |
|
|
4
|
+
declare function generalDecrypt(jwe: GeneralJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise<GeneralDecryptResult>;
|
|
5
|
+
declare function generalDecrypt(jwe: GeneralJWE, getKey: GeneralDecryptGetKey, options?: DecryptOptions): Promise<GeneralDecryptResult & ResolvedKey>;
|
|
5
6
|
export { generalDecrypt };
|
|
6
7
|
export default generalDecrypt;
|
|
7
8
|
export type { KeyLike, GeneralJWE, DecryptOptions, GeneralDecryptResult };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
declare function EmbeddedJWK(protectedHeader: JWSHeaderParameters, token: FlattenedJWSInput): Promise<CryptoKey | KeyObject>;
|
|
1
|
+
import type { FlattenedJWSInput, JWSHeaderParameters } from '../types';
|
|
2
|
+
declare function EmbeddedJWK(protectedHeader: JWSHeaderParameters, token: FlattenedJWSInput): Promise<import("../types.d").KeyLike>;
|
|
4
3
|
export { EmbeddedJWK };
|
|
5
4
|
export default EmbeddedJWK;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JWK, KeyLike } from '../types';
|
|
2
|
-
declare function parseJwk(jwk: JWK, alg?: string, octAsKeyObject?: boolean): Promise<KeyLike>;
|
|
2
|
+
declare function parseJwk(jwk: JWK, alg?: string, octAsKeyObject?: boolean): Promise<KeyLike | Uint8Array>;
|
|
3
3
|
export { parseJwk };
|
|
4
4
|
export default parseJwk;
|
|
5
5
|
export type { KeyLike, JWK };
|
|
@@ -3,7 +3,7 @@ declare class CompactSign {
|
|
|
3
3
|
private _flattened;
|
|
4
4
|
constructor(payload: Uint8Array);
|
|
5
5
|
setProtectedHeader(protectedHeader: JWSHeaderParameters): this;
|
|
6
|
-
sign(key: KeyLike, options?: SignOptions): Promise<string>;
|
|
6
|
+
sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise<string>;
|
|
7
7
|
}
|
|
8
8
|
export { CompactSign };
|
|
9
9
|
export default CompactSign;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { CompactVerifyResult, FlattenedJWSInput, GetKeyFunction, JWSHeaderParameters, KeyLike, VerifyOptions } from '../../types';
|
|
1
|
+
import type { CompactVerifyResult, FlattenedJWSInput, GetKeyFunction, JWSHeaderParameters, KeyLike, VerifyOptions, ResolvedKey } from '../../types';
|
|
2
2
|
export interface CompactVerifyGetKey extends GetKeyFunction<JWSHeaderParameters, FlattenedJWSInput> {
|
|
3
3
|
}
|
|
4
|
-
declare function compactVerify(jws: string | Uint8Array, key: KeyLike |
|
|
4
|
+
declare function compactVerify(jws: string | Uint8Array, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise<CompactVerifyResult>;
|
|
5
|
+
declare function compactVerify(jws: string | Uint8Array, getKey: CompactVerifyGetKey, options?: VerifyOptions): Promise<CompactVerifyResult & ResolvedKey>;
|
|
5
6
|
export { compactVerify };
|
|
6
7
|
export default compactVerify;
|
|
7
8
|
export type { KeyLike, VerifyOptions, CompactVerifyResult };
|
|
@@ -6,7 +6,7 @@ declare class FlattenedSign {
|
|
|
6
6
|
constructor(payload: Uint8Array);
|
|
7
7
|
setProtectedHeader(protectedHeader: JWSHeaderParameters): this;
|
|
8
8
|
setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters): this;
|
|
9
|
-
sign(key: KeyLike, options?: SignOptions): Promise<FlattenedJWS>;
|
|
9
|
+
sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise<FlattenedJWS>;
|
|
10
10
|
}
|
|
11
11
|
export { FlattenedSign };
|
|
12
12
|
export default FlattenedSign;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { FlattenedVerifyResult, KeyLike, FlattenedJWSInput, JWSHeaderParameters, VerifyOptions, GetKeyFunction } from '../../types';
|
|
1
|
+
import type { FlattenedVerifyResult, KeyLike, FlattenedJWSInput, JWSHeaderParameters, VerifyOptions, GetKeyFunction, ResolvedKey } from '../../types';
|
|
2
2
|
export interface FlattenedVerifyGetKey extends GetKeyFunction<JWSHeaderParameters | undefined, FlattenedJWSInput> {
|
|
3
3
|
}
|
|
4
|
-
declare function flattenedVerify(jws: FlattenedJWSInput, key: KeyLike |
|
|
4
|
+
declare function flattenedVerify(jws: FlattenedJWSInput, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise<FlattenedVerifyResult>;
|
|
5
|
+
declare function flattenedVerify(jws: FlattenedJWSInput, getKey: FlattenedVerifyGetKey, options?: VerifyOptions): Promise<FlattenedVerifyResult & ResolvedKey>;
|
|
5
6
|
export { flattenedVerify };
|
|
6
7
|
export default flattenedVerify;
|
|
7
8
|
export type { KeyLike, FlattenedJWSInput, GetKeyFunction, JWSHeaderParameters, VerifyOptions, FlattenedVerifyResult, };
|
|
@@ -7,7 +7,7 @@ declare class GeneralSign {
|
|
|
7
7
|
private _payload;
|
|
8
8
|
private _signatures;
|
|
9
9
|
constructor(payload: Uint8Array);
|
|
10
|
-
addSignature(key: KeyLike, options?: SignOptions): Signature;
|
|
10
|
+
addSignature(key: KeyLike | Uint8Array, options?: SignOptions): Signature;
|
|
11
11
|
sign(): Promise<GeneralJWS>;
|
|
12
12
|
}
|
|
13
13
|
export { GeneralSign };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { GeneralJWSInput, GeneralVerifyResult, FlattenedJWSInput, GetKeyFunction, JWSHeaderParameters, KeyLike, VerifyOptions } from '../../types';
|
|
1
|
+
import type { GeneralJWSInput, GeneralVerifyResult, FlattenedJWSInput, GetKeyFunction, JWSHeaderParameters, KeyLike, VerifyOptions, ResolvedKey } from '../../types';
|
|
2
2
|
export interface GeneralVerifyGetKey extends GetKeyFunction<JWSHeaderParameters, FlattenedJWSInput> {
|
|
3
3
|
}
|
|
4
|
-
declare function generalVerify(jws: GeneralJWSInput, key: KeyLike |
|
|
4
|
+
declare function generalVerify(jws: GeneralJWSInput, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise<GeneralVerifyResult>;
|
|
5
|
+
declare function generalVerify(jws: GeneralJWSInput, getKey: GeneralVerifyGetKey, options?: VerifyOptions): Promise<GeneralVerifyResult & ResolvedKey>;
|
|
5
6
|
export { generalVerify };
|
|
6
7
|
export default generalVerify;
|
|
7
8
|
export type { KeyLike, GeneralJWSInput, VerifyOptions, GeneralVerifyResult };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { KeyLike, DecryptOptions, JWTPayload, JWTClaimVerificationOptions, GetKeyFunction, JWEHeaderParameters, FlattenedJWE, JWTDecryptResult } from '../types';
|
|
1
|
+
import type { KeyLike, DecryptOptions, JWTPayload, JWTClaimVerificationOptions, GetKeyFunction, JWEHeaderParameters, FlattenedJWE, JWTDecryptResult, ResolvedKey } from '../types';
|
|
2
2
|
interface JWTDecryptOptions extends DecryptOptions, JWTClaimVerificationOptions {
|
|
3
3
|
}
|
|
4
4
|
export interface JWTDecryptGetKey extends GetKeyFunction<JWEHeaderParameters, FlattenedJWE> {
|
|
5
5
|
}
|
|
6
|
-
declare function jwtDecrypt(jwt: string | Uint8Array, key: KeyLike |
|
|
6
|
+
declare function jwtDecrypt(jwt: string | Uint8Array, key: KeyLike | Uint8Array, options?: JWTDecryptOptions): Promise<JWTDecryptResult>;
|
|
7
|
+
declare function jwtDecrypt(jwt: string | Uint8Array, getKey: JWTDecryptGetKey, options?: JWTDecryptOptions): Promise<JWTDecryptResult & ResolvedKey>;
|
|
7
8
|
export { jwtDecrypt };
|
|
8
9
|
export default jwtDecrypt;
|
|
9
10
|
export type { KeyLike, DecryptOptions, JWTPayload, JWTDecryptOptions, JWTDecryptResult };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EncryptOptions, JWEHeaderParameters, JWEKeyManagementHeaderParameters, JWTPayload, KeyLike } from '../types';
|
|
2
|
-
import ProduceJWT from '
|
|
2
|
+
import { ProduceJWT } from './produce';
|
|
3
3
|
declare class EncryptJWT extends ProduceJWT {
|
|
4
4
|
private _cek;
|
|
5
5
|
private _iv;
|
|
@@ -15,7 +15,7 @@ declare class EncryptJWT extends ProduceJWT {
|
|
|
15
15
|
replicateIssuerAsHeader(): this;
|
|
16
16
|
replicateSubjectAsHeader(): this;
|
|
17
17
|
replicateAudienceAsHeader(): this;
|
|
18
|
-
encrypt(key: KeyLike, options?: EncryptOptions): Promise<string>;
|
|
18
|
+
encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise<string>;
|
|
19
19
|
}
|
|
20
20
|
export { EncryptJWT };
|
|
21
21
|
export default EncryptJWT;
|