jose 5.10.0 → 6.0.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 +15 -15
- package/dist/types/index.d.ts +48 -48
- package/dist/types/jwe/compact/decrypt.d.ts +4 -4
- package/dist/types/jwe/compact/encrypt.d.ts +4 -4
- package/dist/types/jwe/flattened/decrypt.d.ts +4 -4
- package/dist/types/jwe/flattened/encrypt.d.ts +6 -6
- package/dist/types/jwe/general/decrypt.d.ts +4 -4
- package/dist/types/jwe/general/encrypt.d.ts +7 -7
- package/dist/types/jwk/embedded.d.ts +2 -2
- package/dist/types/jwk/thumbprint.d.ts +5 -5
- package/dist/types/jwks/local.d.ts +2 -2
- package/dist/types/jwks/remote.d.ts +104 -25
- package/dist/types/jws/compact/sign.d.ts +4 -4
- package/dist/types/jws/compact/verify.d.ts +4 -4
- package/dist/types/jws/flattened/sign.d.ts +4 -4
- package/dist/types/jws/flattened/verify.d.ts +4 -4
- package/dist/types/jws/general/sign.d.ts +6 -6
- package/dist/types/jws/general/verify.d.ts +4 -4
- package/dist/types/jwt/decrypt.d.ts +5 -5
- package/dist/types/jwt/encrypt.d.ts +5 -5
- package/dist/types/jwt/produce.d.ts +3 -3
- package/dist/types/jwt/sign.d.ts +4 -4
- package/dist/types/jwt/unsecured.d.ts +6 -6
- package/dist/types/jwt/verify.d.ts +5 -5
- package/dist/types/key/export.d.ts +10 -12
- package/dist/types/key/generate_key_pair.d.ts +10 -11
- package/dist/types/key/generate_secret.d.ts +6 -9
- package/dist/types/key/import.d.ts +20 -27
- package/dist/types/types.d.ts +27 -29
- package/dist/types/util/decode_jwt.d.ts +2 -2
- package/dist/types/util/decode_protected_header.d.ts +2 -2
- package/dist/types/util/errors.d.ts +6 -6
- package/dist/{browser → webapi}/index.js +2 -2
- package/dist/{node/esm → webapi}/jwe/flattened/decrypt.js +8 -4
- package/dist/{node/esm → webapi}/jwe/flattened/encrypt.js +7 -3
- package/dist/{node/esm → webapi}/jwe/general/encrypt.js +8 -3
- package/dist/{node/esm → webapi}/jwk/thumbprint.js +18 -8
- package/dist/{node/esm → webapi}/jwks/local.js +1 -6
- package/dist/{node/esm → webapi}/jwks/remote.js +34 -6
- package/dist/{node/esm → webapi}/jws/flattened/sign.js +7 -5
- package/dist/{browser → webapi}/jws/flattened/verify.js +8 -14
- package/dist/{browser → webapi}/jwt/unsecured.js +1 -1
- package/dist/{node/esm → webapi}/key/export.js +2 -3
- package/dist/{browser/runtime/generate.js → webapi/key/generate_key_pair.js} +4 -57
- package/dist/webapi/key/generate_secret.js +40 -0
- package/dist/{browser → webapi}/key/import.js +8 -6
- package/dist/{node/esm → webapi}/lib/aesgcmkw.js +3 -3
- package/dist/{browser/runtime → webapi/lib}/aeskw.js +9 -16
- package/dist/{browser/runtime → webapi/lib}/asn1.js +24 -20
- package/dist/{browser/runtime → webapi/lib}/base64url.js +17 -9
- package/dist/{browser → webapi}/lib/buffer_utils.js +4 -19
- package/dist/{browser → webapi}/lib/cek.js +1 -2
- package/dist/{browser/runtime → webapi/lib}/check_cek_length.js +1 -2
- package/dist/{browser → webapi}/lib/check_iv_length.js +1 -2
- package/dist/webapi/lib/check_key_type.js +126 -0
- package/dist/{node/esm → webapi}/lib/crypto_key.js +9 -26
- package/dist/{browser/runtime → webapi/lib}/decrypt.js +26 -10
- package/dist/{node/esm → webapi}/lib/decrypt_key_management.js +22 -24
- package/dist/{browser/runtime → webapi/lib}/digest.js +1 -3
- package/dist/webapi/lib/ecdhes.js +46 -0
- package/dist/{browser/runtime → webapi/lib}/encrypt.js +8 -10
- package/dist/{node/esm → webapi}/lib/encrypt_key_management.js +26 -23
- package/dist/webapi/lib/get_sign_verify_key.js +12 -0
- package/dist/{node/esm → webapi}/lib/is_disjoint.js +1 -2
- package/dist/{browser → webapi}/lib/is_jwk.js +1 -1
- package/dist/webapi/lib/is_key_like.js +14 -0
- package/dist/{browser → webapi}/lib/is_object.js +2 -2
- package/dist/{node/esm → webapi}/lib/iv.js +1 -2
- package/dist/{browser/runtime → webapi/lib}/jwk_to_key.js +3 -13
- package/dist/webapi/lib/key_to_jwk.js +27 -0
- package/dist/webapi/lib/normalize_key.js +164 -0
- package/dist/webapi/lib/pbes2kw.js +37 -0
- package/dist/webapi/lib/rsaes.js +24 -0
- package/dist/{browser/runtime → webapi/lib}/sign.js +1 -3
- package/dist/{browser/runtime → webapi/lib}/subtle_dsa.js +4 -5
- package/dist/{browser → webapi}/lib/validate_algorithms.js +1 -2
- package/dist/{node/esm → webapi}/lib/validate_crit.js +3 -4
- package/dist/{browser/runtime → webapi/lib}/verify.js +1 -3
- package/dist/{node/esm → webapi}/util/base64url.js +1 -1
- package/package.json +36 -219
- package/dist/browser/jwe/compact/encrypt.js +0 -26
- package/dist/browser/jwe/flattened/decrypt.js +0 -161
- package/dist/browser/jwe/flattened/encrypt.js +0 -153
- package/dist/browser/jwe/general/encrypt.js +0 -174
- package/dist/browser/jwk/thumbprint.js +0 -53
- package/dist/browser/jwks/local.js +0 -124
- package/dist/browser/jwks/remote.js +0 -139
- package/dist/browser/jws/compact/sign.js +0 -17
- package/dist/browser/jws/flattened/sign.js +0 -81
- package/dist/browser/jws/general/sign.js +0 -67
- package/dist/browser/jwt/encrypt.js +0 -68
- package/dist/browser/jwt/produce.js +0 -75
- package/dist/browser/jwt/sign.js +0 -20
- package/dist/browser/key/export.js +0 -12
- package/dist/browser/key/generate_key_pair.js +0 -4
- package/dist/browser/key/generate_secret.js +0 -4
- package/dist/browser/lib/aesgcmkw.js +0 -16
- package/dist/browser/lib/check_key_type.js +0 -77
- package/dist/browser/lib/check_p2s.js +0 -6
- package/dist/browser/lib/crypto_key.js +0 -157
- package/dist/browser/lib/decrypt_key_management.js +0 -129
- package/dist/browser/lib/encrypt_key_management.js +0 -89
- package/dist/browser/lib/format_pem.js +0 -4
- package/dist/browser/lib/is_disjoint.js +0 -22
- package/dist/browser/lib/iv.js +0 -20
- package/dist/browser/lib/validate_crit.js +0 -34
- package/dist/browser/package.json +0 -1
- package/dist/browser/runtime/bogus.js +0 -6
- package/dist/browser/runtime/ecdhes.js +0 -47
- package/dist/browser/runtime/fetch_jwks.js +0 -34
- package/dist/browser/runtime/get_sign_verify_key.js +0 -24
- package/dist/browser/runtime/is_key_like.js +0 -8
- package/dist/browser/runtime/key_to_jwk.js +0 -21
- package/dist/browser/runtime/normalize_key.js +0 -68
- package/dist/browser/runtime/pbes2kw.js +0 -51
- package/dist/browser/runtime/random.js +0 -2
- package/dist/browser/runtime/rsaes.js +0 -37
- package/dist/browser/runtime/runtime.js +0 -1
- package/dist/browser/runtime/subtle_rsaes.js +0 -12
- package/dist/browser/runtime/timing_safe_equal.js +0 -19
- package/dist/browser/runtime/webcrypto.js +0 -2
- package/dist/browser/util/base64url.js +0 -3
- package/dist/browser/util/errors.js +0 -114
- package/dist/browser/util/runtime.js +0 -2
- package/dist/node/cjs/index.js +0 -69
- package/dist/node/cjs/jwe/compact/decrypt.js +0 -30
- package/dist/node/cjs/jwe/compact/encrypt.js +0 -31
- package/dist/node/cjs/jwe/flattened/decrypt.js +0 -164
- package/dist/node/cjs/jwe/flattened/encrypt.js +0 -165
- package/dist/node/cjs/jwe/general/decrypt.js +0 -34
- package/dist/node/cjs/jwe/general/encrypt.js +0 -186
- package/dist/node/cjs/jwk/embedded.js +0 -20
- package/dist/node/cjs/jwk/thumbprint.js +0 -57
- package/dist/node/cjs/jwks/local.js +0 -128
- package/dist/node/cjs/jwks/remote.js +0 -152
- package/dist/node/cjs/jws/compact/sign.js +0 -22
- package/dist/node/cjs/jws/compact/verify.js +0 -24
- package/dist/node/cjs/jws/flattened/sign.js +0 -88
- package/dist/node/cjs/jws/flattened/verify.js +0 -125
- package/dist/node/cjs/jws/general/sign.js +0 -77
- package/dist/node/cjs/jws/general/verify.js +0 -27
- package/dist/node/cjs/jwt/decrypt.js +0 -26
- package/dist/node/cjs/jwt/encrypt.js +0 -79
- package/dist/node/cjs/jwt/produce.js +0 -80
- package/dist/node/cjs/jwt/sign.js +0 -25
- package/dist/node/cjs/jwt/unsecured.js +0 -36
- package/dist/node/cjs/jwt/verify.js +0 -18
- package/dist/node/cjs/key/export.js +0 -17
- package/dist/node/cjs/key/generate_key_pair.js +0 -7
- package/dist/node/cjs/key/generate_secret.js +0 -7
- package/dist/node/cjs/key/import.js +0 -51
- package/dist/node/cjs/lib/aesgcmkw.js +0 -20
- package/dist/node/cjs/lib/buffer_utils.js +0 -60
- package/dist/node/cjs/lib/cek.js +0 -23
- package/dist/node/cjs/lib/check_iv_length.js +0 -10
- package/dist/node/cjs/lib/check_key_type.js +0 -80
- package/dist/node/cjs/lib/check_p2s.js +0 -9
- package/dist/node/cjs/lib/crypto_key.js +0 -161
- package/dist/node/cjs/lib/decrypt_key_management.js +0 -131
- package/dist/node/cjs/lib/encrypt_key_management.js +0 -91
- package/dist/node/cjs/lib/epoch.js +0 -3
- package/dist/node/cjs/lib/invalid_key_input.js +0 -34
- package/dist/node/cjs/lib/is_disjoint.js +0 -24
- package/dist/node/cjs/lib/is_jwk.js +0 -19
- package/dist/node/cjs/lib/is_object.js +0 -19
- package/dist/node/cjs/lib/iv.js +0 -23
- package/dist/node/cjs/lib/jwt_claims_set.js +0 -106
- package/dist/node/cjs/lib/private_symbols.js +0 -4
- package/dist/node/cjs/lib/secs.js +0 -57
- package/dist/node/cjs/lib/validate_algorithms.js +0 -13
- package/dist/node/cjs/lib/validate_crit.js +0 -36
- package/dist/node/cjs/runtime/aeskw.js +0 -55
- package/dist/node/cjs/runtime/asn1.js +0 -54
- package/dist/node/cjs/runtime/base64url.js +0 -20
- package/dist/node/cjs/runtime/cbc_tag.js +0 -11
- package/dist/node/cjs/runtime/check_cek_length.js +0 -37
- package/dist/node/cjs/runtime/check_key_length.js +0 -18
- package/dist/node/cjs/runtime/ciphers.js +0 -8
- package/dist/node/cjs/runtime/decrypt.js +0 -103
- package/dist/node/cjs/runtime/digest.js +0 -5
- package/dist/node/cjs/runtime/dsa_digest.js +0 -26
- package/dist/node/cjs/runtime/ecdhes.js +0 -70
- package/dist/node/cjs/runtime/encrypt.js +0 -80
- package/dist/node/cjs/runtime/fetch_jwks.js +0 -45
- package/dist/node/cjs/runtime/generate.js +0 -103
- package/dist/node/cjs/runtime/get_named_curve.js +0 -61
- package/dist/node/cjs/runtime/get_sign_verify_key.js +0 -31
- package/dist/node/cjs/runtime/hmac_digest.js +0 -16
- package/dist/node/cjs/runtime/is_key_like.js +0 -11
- package/dist/node/cjs/runtime/is_key_object.js +0 -4
- package/dist/node/cjs/runtime/jwk_to_key.js +0 -10
- package/dist/node/cjs/runtime/key_to_jwk.js +0 -36
- package/dist/node/cjs/runtime/node_key.js +0 -111
- package/dist/node/cjs/runtime/normalize_key.js +0 -3
- package/dist/node/cjs/runtime/pbes2kw.js +0 -48
- package/dist/node/cjs/runtime/random.js +0 -5
- package/dist/node/cjs/runtime/rsaes.js +0 -71
- package/dist/node/cjs/runtime/runtime.js +0 -3
- package/dist/node/cjs/runtime/sign.js +0 -19
- package/dist/node/cjs/runtime/timing_safe_equal.js +0 -5
- package/dist/node/cjs/runtime/verify.js +0 -31
- package/dist/node/cjs/runtime/webcrypto.js +0 -9
- package/dist/node/cjs/util/base64url.js +0 -6
- package/dist/node/cjs/util/decode_jwt.js +0 -35
- package/dist/node/cjs/util/decode_protected_header.js +0 -37
- package/dist/node/cjs/util/errors.js +0 -117
- package/dist/node/cjs/util/runtime.js +0 -4
- package/dist/node/esm/index.js +0 -30
- package/dist/node/esm/jwe/compact/decrypt.js +0 -27
- package/dist/node/esm/jwe/general/decrypt.js +0 -31
- package/dist/node/esm/jwk/embedded.js +0 -17
- package/dist/node/esm/jws/compact/verify.js +0 -21
- package/dist/node/esm/jws/flattened/verify.js +0 -122
- package/dist/node/esm/jws/general/verify.js +0 -24
- package/dist/node/esm/jwt/decrypt.js +0 -23
- package/dist/node/esm/jwt/unsecured.js +0 -32
- package/dist/node/esm/jwt/verify.js +0 -15
- package/dist/node/esm/key/generate_key_pair.js +0 -4
- package/dist/node/esm/key/generate_secret.js +0 -4
- package/dist/node/esm/key/import.js +0 -45
- package/dist/node/esm/lib/buffer_utils.js +0 -51
- package/dist/node/esm/lib/cek.js +0 -20
- package/dist/node/esm/lib/check_iv_length.js +0 -8
- package/dist/node/esm/lib/check_key_type.js +0 -77
- package/dist/node/esm/lib/check_p2s.js +0 -6
- package/dist/node/esm/lib/epoch.js +0 -1
- package/dist/node/esm/lib/invalid_key_input.js +0 -31
- package/dist/node/esm/lib/is_jwk.js +0 -13
- package/dist/node/esm/lib/is_object.js +0 -16
- package/dist/node/esm/lib/jwt_claims_set.js +0 -104
- package/dist/node/esm/lib/private_symbols.js +0 -1
- package/dist/node/esm/lib/secs.js +0 -55
- package/dist/node/esm/lib/validate_algorithms.js +0 -11
- package/dist/node/esm/package.json +0 -1
- package/dist/node/esm/runtime/aeskw.js +0 -50
- package/dist/node/esm/runtime/asn1.js +0 -46
- package/dist/node/esm/runtime/base64url.js +0 -14
- package/dist/node/esm/runtime/cbc_tag.js +0 -8
- package/dist/node/esm/runtime/check_cek_length.js +0 -35
- package/dist/node/esm/runtime/check_key_length.js +0 -16
- package/dist/node/esm/runtime/ciphers.js +0 -6
- package/dist/node/esm/runtime/decrypt.js +0 -101
- package/dist/node/esm/runtime/digest.js +0 -3
- package/dist/node/esm/runtime/dsa_digest.js +0 -23
- package/dist/node/esm/runtime/ecdhes.js +0 -64
- package/dist/node/esm/runtime/encrypt.js +0 -78
- package/dist/node/esm/runtime/fetch_jwks.js +0 -43
- package/dist/node/esm/runtime/generate.js +0 -99
- package/dist/node/esm/runtime/get_named_curve.js +0 -58
- package/dist/node/esm/runtime/get_sign_verify_key.js +0 -28
- package/dist/node/esm/runtime/hmac_digest.js +0 -13
- package/dist/node/esm/runtime/is_key_like.js +0 -8
- package/dist/node/esm/runtime/is_key_object.js +0 -2
- package/dist/node/esm/runtime/jwk_to_key.js +0 -8
- package/dist/node/esm/runtime/key_to_jwk.js +0 -34
- package/dist/node/esm/runtime/node_key.js +0 -108
- package/dist/node/esm/runtime/normalize_key.js +0 -1
- package/dist/node/esm/runtime/pbes2kw.js +0 -43
- package/dist/node/esm/runtime/random.js +0 -1
- package/dist/node/esm/runtime/rsaes.js +0 -66
- package/dist/node/esm/runtime/runtime.js +0 -1
- package/dist/node/esm/runtime/sign.js +0 -17
- package/dist/node/esm/runtime/timing_safe_equal.js +0 -3
- package/dist/node/esm/runtime/verify.js +0 -29
- package/dist/node/esm/runtime/webcrypto.js +0 -5
- package/dist/node/esm/util/decode_jwt.js +0 -32
- package/dist/node/esm/util/decode_protected_header.js +0 -34
- package/dist/node/esm/util/runtime.js +0 -2
- package/dist/types/util/runtime.d.ts +0 -3
- /package/dist/{browser → webapi}/jwe/compact/decrypt.js +0 -0
- /package/dist/{node/esm → webapi}/jwe/compact/encrypt.js +0 -0
- /package/dist/{browser → webapi}/jwe/general/decrypt.js +0 -0
- /package/dist/{browser → webapi}/jwk/embedded.js +0 -0
- /package/dist/{node/esm → webapi}/jws/compact/sign.js +0 -0
- /package/dist/{browser → webapi}/jws/compact/verify.js +0 -0
- /package/dist/{node/esm → webapi}/jws/general/sign.js +0 -0
- /package/dist/{browser → webapi}/jws/general/verify.js +0 -0
- /package/dist/{browser → webapi}/jwt/decrypt.js +0 -0
- /package/dist/{node/esm → webapi}/jwt/encrypt.js +0 -0
- /package/dist/{node/esm → webapi}/jwt/produce.js +0 -0
- /package/dist/{node/esm → webapi}/jwt/sign.js +0 -0
- /package/dist/{browser → webapi}/jwt/verify.js +0 -0
- /package/dist/{browser/runtime → webapi/lib}/check_key_length.js +0 -0
- /package/dist/{browser → webapi}/lib/epoch.js +0 -0
- /package/dist/{browser → webapi}/lib/invalid_key_input.js +0 -0
- /package/dist/{browser → webapi}/lib/jwt_claims_set.js +0 -0
- /package/dist/{browser → webapi}/lib/private_symbols.js +0 -0
- /package/dist/{browser → webapi}/lib/secs.js +0 -0
- /package/dist/{browser → webapi}/util/decode_jwt.js +0 -0
- /package/dist/{browser → webapi}/util/decode_protected_header.js +0 -0
- /package/dist/{node/esm → webapi}/util/errors.js +0 -0
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
1
|
+
import invalidKeyInput from './invalid_key_input.js';
|
|
3
2
|
import { encodeBase64, decodeBase64 } from './base64url.js';
|
|
4
|
-
import formatPEM from '../lib/format_pem.js';
|
|
5
3
|
import { JOSENotSupported } from '../util/errors.js';
|
|
6
|
-
import {
|
|
4
|
+
import { isCryptoKey, isKeyObject } from './is_key_like.js';
|
|
5
|
+
const formatPEM = (b64, descriptor) => {
|
|
6
|
+
const newlined = (b64.match(/.{1,64}/g) || []).join('\n');
|
|
7
|
+
return `-----BEGIN ${descriptor}-----\n${newlined}\n-----END ${descriptor}-----`;
|
|
8
|
+
};
|
|
7
9
|
const genericExport = async (keyType, keyFormat, key) => {
|
|
10
|
+
if (isKeyObject(key)) {
|
|
11
|
+
if (key.type !== keyType) {
|
|
12
|
+
throw new TypeError(`key is not a ${keyType} key`);
|
|
13
|
+
}
|
|
14
|
+
return key.export({ format: 'pem', type: keyFormat });
|
|
15
|
+
}
|
|
8
16
|
if (!isCryptoKey(key)) {
|
|
9
|
-
throw new TypeError(invalidKeyInput(key,
|
|
17
|
+
throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'KeyObject'));
|
|
10
18
|
}
|
|
11
19
|
if (!key.extractable) {
|
|
12
20
|
throw new TypeError('CryptoKey is not extractable');
|
|
@@ -43,16 +51,8 @@ const getNamedCurve = (keyData) => {
|
|
|
43
51
|
return 'P-384';
|
|
44
52
|
case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]):
|
|
45
53
|
return 'P-521';
|
|
46
|
-
case findOid(keyData, [0x2b, 0x65, 0x6e]):
|
|
47
|
-
return 'X25519';
|
|
48
|
-
case findOid(keyData, [0x2b, 0x65, 0x6f]):
|
|
49
|
-
return 'X448';
|
|
50
|
-
case findOid(keyData, [0x2b, 0x65, 0x70]):
|
|
51
|
-
return 'Ed25519';
|
|
52
|
-
case findOid(keyData, [0x2b, 0x65, 0x71]):
|
|
53
|
-
return 'Ed448';
|
|
54
54
|
default:
|
|
55
|
-
|
|
55
|
+
return undefined;
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
@@ -102,22 +102,19 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
|
102
102
|
case 'ECDH-ES+A192KW':
|
|
103
103
|
case 'ECDH-ES+A256KW': {
|
|
104
104
|
const namedCurve = getNamedCurve(keyData);
|
|
105
|
-
algorithm = namedCurve
|
|
105
|
+
algorithm = namedCurve?.startsWith('P-') ? { name: 'ECDH', namedCurve } : { name: 'X25519' };
|
|
106
106
|
keyUsages = isPublic ? [] : ['deriveBits'];
|
|
107
107
|
break;
|
|
108
108
|
}
|
|
109
109
|
case 'Ed25519':
|
|
110
|
-
algorithm = { name: 'Ed25519' };
|
|
111
|
-
keyUsages = isPublic ? ['verify'] : ['sign'];
|
|
112
|
-
break;
|
|
113
110
|
case 'EdDSA':
|
|
114
|
-
algorithm = { name:
|
|
111
|
+
algorithm = { name: 'Ed25519' };
|
|
115
112
|
keyUsages = isPublic ? ['verify'] : ['sign'];
|
|
116
113
|
break;
|
|
117
114
|
default:
|
|
118
115
|
throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value');
|
|
119
116
|
}
|
|
120
|
-
return crypto.subtle.importKey(keyFormat, keyData, algorithm, options?.extractable ?? false, keyUsages);
|
|
117
|
+
return crypto.subtle.importKey(keyFormat, keyData, algorithm, options?.extractable ?? (isPublic ? true : false), keyUsages);
|
|
121
118
|
};
|
|
122
119
|
export const fromPKCS8 = (pem, alg, options) => {
|
|
123
120
|
return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options);
|
|
@@ -188,7 +185,14 @@ function spkiFromX509(buf) {
|
|
|
188
185
|
const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents);
|
|
189
186
|
return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 0xa0 ? 6 : 5].raw);
|
|
190
187
|
}
|
|
188
|
+
let X509Certificate;
|
|
191
189
|
function getSPKI(x509) {
|
|
190
|
+
if ((X509Certificate ||= globalThis.process?.getBuiltinModule?.('node:crypto')?.X509Certificate)) {
|
|
191
|
+
try {
|
|
192
|
+
return new X509Certificate(x509).publicKey.export({ format: 'pem', type: 'spki' });
|
|
193
|
+
}
|
|
194
|
+
catch { }
|
|
195
|
+
}
|
|
192
196
|
const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '');
|
|
193
197
|
const raw = decodeBase64(pem);
|
|
194
198
|
return formatPEM(spkiFromX509(raw), 'PUBLIC KEY');
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { encoder, decoder } from '../lib/buffer_utils.js';
|
|
2
|
-
export
|
|
1
|
+
import { encoder, decoder, Buffer } from '../lib/buffer_utils.js';
|
|
2
|
+
export function encodeBase64(input) {
|
|
3
|
+
if (Buffer)
|
|
4
|
+
return Buffer.from(input).toString('base64');
|
|
3
5
|
let unencoded = input;
|
|
4
6
|
if (typeof unencoded === 'string') {
|
|
5
7
|
unencoded = encoder.encode(unencoded);
|
|
@@ -10,23 +12,29 @@ export const encodeBase64 = (input) => {
|
|
|
10
12
|
arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE)));
|
|
11
13
|
}
|
|
12
14
|
return btoa(arr.join(''));
|
|
13
|
-
}
|
|
14
|
-
export
|
|
15
|
+
}
|
|
16
|
+
export function encode(input) {
|
|
17
|
+
if (Buffer)
|
|
18
|
+
return Buffer.from(input).toString('base64url');
|
|
15
19
|
return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
16
|
-
}
|
|
17
|
-
export
|
|
20
|
+
}
|
|
21
|
+
export function decodeBase64(encoded) {
|
|
22
|
+
if (Buffer)
|
|
23
|
+
return Buffer.from(encoded, 'base64');
|
|
18
24
|
const binary = atob(encoded);
|
|
19
25
|
const bytes = new Uint8Array(binary.length);
|
|
20
26
|
for (let i = 0; i < binary.length; i++) {
|
|
21
27
|
bytes[i] = binary.charCodeAt(i);
|
|
22
28
|
}
|
|
23
29
|
return bytes;
|
|
24
|
-
}
|
|
25
|
-
export
|
|
30
|
+
}
|
|
31
|
+
export function decode(input) {
|
|
26
32
|
let encoded = input;
|
|
27
33
|
if (encoded instanceof Uint8Array) {
|
|
28
34
|
encoded = decoder.decode(encoded);
|
|
29
35
|
}
|
|
36
|
+
if (Buffer)
|
|
37
|
+
return Buffer.from(encoded, 'base64url');
|
|
30
38
|
encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '');
|
|
31
39
|
try {
|
|
32
40
|
return decodeBase64(encoded);
|
|
@@ -34,4 +42,4 @@ export const decode = (input) => {
|
|
|
34
42
|
catch {
|
|
35
43
|
throw new TypeError('The input to be decoded is not correctly encoded.');
|
|
36
44
|
}
|
|
37
|
-
}
|
|
45
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import digest from '../runtime/digest.js';
|
|
2
1
|
export const encoder = new TextEncoder();
|
|
3
2
|
export const decoder = new TextDecoder();
|
|
4
3
|
const MAX_INT32 = 2 ** 32;
|
|
4
|
+
const Buffer = globalThis.process?.getBuiltinModule?.('node:buffer')?.Buffer;
|
|
5
|
+
export { Buffer };
|
|
5
6
|
export function concat(...buffers) {
|
|
7
|
+
if (Buffer)
|
|
8
|
+
return Buffer.concat(buffers);
|
|
6
9
|
const size = buffers.reduce((acc, { length }) => acc + length, 0);
|
|
7
10
|
const buf = new Uint8Array(size);
|
|
8
11
|
let i = 0;
|
|
@@ -12,9 +15,6 @@ export function concat(...buffers) {
|
|
|
12
15
|
}
|
|
13
16
|
return buf;
|
|
14
17
|
}
|
|
15
|
-
export function p2s(alg, p2sInput) {
|
|
16
|
-
return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput);
|
|
17
|
-
}
|
|
18
18
|
function writeUInt32BE(buf, value, offset) {
|
|
19
19
|
if (value < 0 || value >= MAX_INT32) {
|
|
20
20
|
throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);
|
|
@@ -34,18 +34,3 @@ export function uint32be(value) {
|
|
|
34
34
|
writeUInt32BE(buf, value);
|
|
35
35
|
return buf;
|
|
36
36
|
}
|
|
37
|
-
export function lengthAndInput(input) {
|
|
38
|
-
return concat(uint32be(input.length), input);
|
|
39
|
-
}
|
|
40
|
-
export async function concatKdf(secret, bits, value) {
|
|
41
|
-
const iterations = Math.ceil((bits >> 3) / 32);
|
|
42
|
-
const res = new Uint8Array(iterations * 32);
|
|
43
|
-
for (let iter = 0; iter < iterations; iter++) {
|
|
44
|
-
const buf = new Uint8Array(4 + secret.length + value.length);
|
|
45
|
-
buf.set(uint32be(iter + 1));
|
|
46
|
-
buf.set(secret, 4);
|
|
47
|
-
buf.set(value, 4 + secret.length);
|
|
48
|
-
res.set(await digest('sha256', buf), iter * 32);
|
|
49
|
-
}
|
|
50
|
-
return res.slice(0, bits >> 3);
|
|
51
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { JOSENotSupported } from '../util/errors.js';
|
|
2
|
-
import random from '../runtime/random.js';
|
|
3
2
|
export function bitLength(alg) {
|
|
4
3
|
switch (alg) {
|
|
5
4
|
case 'A128GCM':
|
|
@@ -17,4 +16,4 @@ export function bitLength(alg) {
|
|
|
17
16
|
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
|
-
export default (alg) =>
|
|
19
|
+
export default (alg) => crypto.getRandomValues(new Uint8Array(bitLength(alg) >> 3));
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { JWEInvalid } from '../util/errors.js';
|
|
2
|
-
|
|
2
|
+
export default (cek, expected) => {
|
|
3
3
|
const actual = cek.byteLength << 3;
|
|
4
4
|
if (actual !== expected) {
|
|
5
5
|
throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`);
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
|
-
export default checkCekLength;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { JWEInvalid } from '../util/errors.js';
|
|
2
2
|
import { bitLength } from './iv.js';
|
|
3
|
-
|
|
3
|
+
export default (enc, iv) => {
|
|
4
4
|
if (iv.length << 3 !== bitLength(enc)) {
|
|
5
5
|
throw new JWEInvalid('Invalid Initialization Vector length');
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
|
-
export default checkIvLength;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { withAlg as invalidKeyInput } from './invalid_key_input.js';
|
|
2
|
+
import isKeyLike from './is_key_like.js';
|
|
3
|
+
import * as jwk from './is_jwk.js';
|
|
4
|
+
const tag = (key) => key?.[Symbol.toStringTag];
|
|
5
|
+
const jwkMatchesOp = (alg, key, usage) => {
|
|
6
|
+
if (key.use !== undefined) {
|
|
7
|
+
let expected;
|
|
8
|
+
switch (usage) {
|
|
9
|
+
case 'sign':
|
|
10
|
+
case 'verify':
|
|
11
|
+
expected = 'sig';
|
|
12
|
+
break;
|
|
13
|
+
case 'encrypt':
|
|
14
|
+
case 'decrypt':
|
|
15
|
+
expected = 'enc';
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
if (key.use !== expected) {
|
|
19
|
+
throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (key.alg !== undefined && key.alg !== alg) {
|
|
23
|
+
throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(key.key_ops)) {
|
|
26
|
+
let expectedKeyOp;
|
|
27
|
+
switch (true) {
|
|
28
|
+
case usage === 'sign' || usage === 'verify':
|
|
29
|
+
case alg === 'dir':
|
|
30
|
+
case alg.includes('CBC-HS'):
|
|
31
|
+
expectedKeyOp = usage;
|
|
32
|
+
break;
|
|
33
|
+
case alg.startsWith('PBES2'):
|
|
34
|
+
expectedKeyOp = 'deriveBits';
|
|
35
|
+
break;
|
|
36
|
+
case /^A\d{3}(?:GCM)?(?:KW)?$/.test(alg):
|
|
37
|
+
if (!alg.includes('GCM') && alg.endsWith('KW')) {
|
|
38
|
+
expectedKeyOp = usage === 'encrypt' ? 'wrapKey' : 'unwrapKey';
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
expectedKeyOp = usage;
|
|
42
|
+
}
|
|
43
|
+
break;
|
|
44
|
+
case usage === 'encrypt' && alg.startsWith('RSA'):
|
|
45
|
+
expectedKeyOp = 'wrapKey';
|
|
46
|
+
break;
|
|
47
|
+
case usage === 'decrypt':
|
|
48
|
+
expectedKeyOp = alg.startsWith('RSA') ? 'unwrapKey' : 'deriveBits';
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {
|
|
52
|
+
throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
};
|
|
57
|
+
const symmetricTypeCheck = (alg, key, usage) => {
|
|
58
|
+
if (key instanceof Uint8Array)
|
|
59
|
+
return;
|
|
60
|
+
if (jwk.isJWK(key)) {
|
|
61
|
+
if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
62
|
+
return;
|
|
63
|
+
throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
|
|
64
|
+
}
|
|
65
|
+
if (!isKeyLike(key)) {
|
|
66
|
+
throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key', 'Uint8Array'));
|
|
67
|
+
}
|
|
68
|
+
if (key.type !== 'secret') {
|
|
69
|
+
throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const asymmetricTypeCheck = (alg, key, usage) => {
|
|
73
|
+
if (jwk.isJWK(key)) {
|
|
74
|
+
switch (usage) {
|
|
75
|
+
case 'decrypt':
|
|
76
|
+
case 'sign':
|
|
77
|
+
if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
78
|
+
return;
|
|
79
|
+
throw new TypeError(`JSON Web Key for this operation be a private JWK`);
|
|
80
|
+
case 'encrypt':
|
|
81
|
+
case 'verify':
|
|
82
|
+
if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
83
|
+
return;
|
|
84
|
+
throw new TypeError(`JSON Web Key for this operation be a public JWK`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!isKeyLike(key)) {
|
|
88
|
+
throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));
|
|
89
|
+
}
|
|
90
|
+
if (key.type === 'secret') {
|
|
91
|
+
throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
|
|
92
|
+
}
|
|
93
|
+
if (key.type === 'public') {
|
|
94
|
+
switch (usage) {
|
|
95
|
+
case 'sign':
|
|
96
|
+
throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
|
|
97
|
+
case 'decrypt':
|
|
98
|
+
throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
|
|
99
|
+
default:
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (key.type === 'private') {
|
|
104
|
+
switch (usage) {
|
|
105
|
+
case 'verify':
|
|
106
|
+
throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`);
|
|
107
|
+
case 'encrypt':
|
|
108
|
+
throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
|
|
109
|
+
default:
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
export default (alg, key, usage) => {
|
|
115
|
+
const symmetric = alg.startsWith('HS') ||
|
|
116
|
+
alg === 'dir' ||
|
|
117
|
+
alg.startsWith('PBES2') ||
|
|
118
|
+
/^A(?:128|192|256)(?:GCM)?(?:KW)?$/.test(alg) ||
|
|
119
|
+
/^A(?:128|192|256)CBC-HS(?:256|384|512)$/.test(alg);
|
|
120
|
+
if (symmetric) {
|
|
121
|
+
symmetricTypeCheck(alg, key, usage);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
asymmetricTypeCheck(alg, key, usage);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
@@ -19,23 +19,12 @@ function getNamedCurve(alg) {
|
|
|
19
19
|
throw new Error('unreachable');
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
function checkUsage(key,
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
if (usages.length > 2) {
|
|
26
|
-
const last = usages.pop();
|
|
27
|
-
msg += `one of ${usages.join(', ')}, or ${last}.`;
|
|
28
|
-
}
|
|
29
|
-
else if (usages.length === 2) {
|
|
30
|
-
msg += `one of ${usages[0]} or ${usages[1]}.`;
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
msg += `${usages[0]}.`;
|
|
34
|
-
}
|
|
35
|
-
throw new TypeError(msg);
|
|
22
|
+
function checkUsage(key, usage) {
|
|
23
|
+
if (usage && !key.usages.includes(usage)) {
|
|
24
|
+
throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
|
|
36
25
|
}
|
|
37
26
|
}
|
|
38
|
-
export function checkSigCryptoKey(key, alg,
|
|
27
|
+
export function checkSigCryptoKey(key, alg, usage) {
|
|
39
28
|
switch (alg) {
|
|
40
29
|
case 'HS256':
|
|
41
30
|
case 'HS384':
|
|
@@ -70,13 +59,8 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
70
59
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
71
60
|
break;
|
|
72
61
|
}
|
|
62
|
+
case 'Ed25519':
|
|
73
63
|
case 'EdDSA': {
|
|
74
|
-
if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') {
|
|
75
|
-
throw unusable('Ed25519 or Ed448');
|
|
76
|
-
}
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
case 'Ed25519': {
|
|
80
64
|
if (!isAlgorithm(key.algorithm, 'Ed25519'))
|
|
81
65
|
throw unusable('Ed25519');
|
|
82
66
|
break;
|
|
@@ -95,9 +79,9 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
95
79
|
default:
|
|
96
80
|
throw new TypeError('CryptoKey does not support this operation');
|
|
97
81
|
}
|
|
98
|
-
checkUsage(key,
|
|
82
|
+
checkUsage(key, usage);
|
|
99
83
|
}
|
|
100
|
-
export function checkEncCryptoKey(key, alg,
|
|
84
|
+
export function checkEncCryptoKey(key, alg, usage) {
|
|
101
85
|
switch (alg) {
|
|
102
86
|
case 'A128GCM':
|
|
103
87
|
case 'A192GCM':
|
|
@@ -125,10 +109,9 @@ export function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
125
109
|
switch (key.algorithm.name) {
|
|
126
110
|
case 'ECDH':
|
|
127
111
|
case 'X25519':
|
|
128
|
-
case 'X448':
|
|
129
112
|
break;
|
|
130
113
|
default:
|
|
131
|
-
throw unusable('ECDH
|
|
114
|
+
throw unusable('ECDH or X25519');
|
|
132
115
|
}
|
|
133
116
|
break;
|
|
134
117
|
}
|
|
@@ -153,5 +136,5 @@ export function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
153
136
|
default:
|
|
154
137
|
throw new TypeError('CryptoKey does not support this operation');
|
|
155
138
|
}
|
|
156
|
-
checkUsage(key,
|
|
139
|
+
checkUsage(key, usage);
|
|
157
140
|
}
|
|
@@ -1,12 +1,29 @@
|
|
|
1
|
-
import { concat, uint64be } from '
|
|
2
|
-
import checkIvLength from '
|
|
1
|
+
import { concat, uint64be } from './buffer_utils.js';
|
|
2
|
+
import checkIvLength from './check_iv_length.js';
|
|
3
3
|
import checkCekLength from './check_cek_length.js';
|
|
4
|
-
import timingSafeEqual from './timing_safe_equal.js';
|
|
5
4
|
import { JOSENotSupported, JWEDecryptionFailed, JWEInvalid } from '../util/errors.js';
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
5
|
+
import { checkEncCryptoKey } from './crypto_key.js';
|
|
6
|
+
import invalidKeyInput from './invalid_key_input.js';
|
|
7
|
+
import { isCryptoKey } from './is_key_like.js';
|
|
8
|
+
let timingSafeEqual = globalThis.process?.getBuiltinModule?.('node:crypto')?.timingSafeEqual;
|
|
9
|
+
timingSafeEqual ||= (a, b) => {
|
|
10
|
+
if (!(a instanceof Uint8Array)) {
|
|
11
|
+
throw new TypeError('First argument must be a buffer');
|
|
12
|
+
}
|
|
13
|
+
if (!(b instanceof Uint8Array)) {
|
|
14
|
+
throw new TypeError('Second argument must be a buffer');
|
|
15
|
+
}
|
|
16
|
+
if (a.length !== b.length) {
|
|
17
|
+
throw new TypeError('Input buffers must have the same length');
|
|
18
|
+
}
|
|
19
|
+
const len = a.length;
|
|
20
|
+
let out = 0;
|
|
21
|
+
let i = -1;
|
|
22
|
+
while (++i < len) {
|
|
23
|
+
out |= a[i] ^ b[i];
|
|
24
|
+
}
|
|
25
|
+
return out === 0;
|
|
26
|
+
};
|
|
10
27
|
async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
11
28
|
if (!(cek instanceof Uint8Array)) {
|
|
12
29
|
throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
|
|
@@ -60,9 +77,9 @@ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
60
77
|
throw new JWEDecryptionFailed();
|
|
61
78
|
}
|
|
62
79
|
}
|
|
63
|
-
|
|
80
|
+
export default async (enc, cek, ciphertext, iv, tag, aad) => {
|
|
64
81
|
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
65
|
-
throw new TypeError(invalidKeyInput(cek,
|
|
82
|
+
throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'KeyObject', 'Uint8Array', 'JSON Web Key'));
|
|
66
83
|
}
|
|
67
84
|
if (!iv) {
|
|
68
85
|
throw new JWEInvalid('JWE Initialization Vector missing');
|
|
@@ -88,4 +105,3 @@ const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
|
|
|
88
105
|
throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
|
|
89
106
|
}
|
|
90
107
|
};
|
|
91
|
-
export default decrypt;
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import normalize from '../runtime/normalize_key.js';
|
|
1
|
+
import * as aeskw from './aeskw.js';
|
|
2
|
+
import * as ecdhes from './ecdhes.js';
|
|
3
|
+
import * as pbes2kw from './pbes2kw.js';
|
|
4
|
+
import * as rsaes from './rsaes.js';
|
|
5
|
+
import * as base64url from '../lib/base64url.js';
|
|
7
6
|
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
|
|
8
7
|
import { bitLength as cekLength } from '../lib/cek.js';
|
|
9
8
|
import { importJWK } from '../key/import.js';
|
|
10
|
-
import checkKeyType from './check_key_type.js';
|
|
11
9
|
import isObject from './is_object.js';
|
|
12
10
|
import { unwrap as aesGcmKw } from './aesgcmkw.js';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
key = (await normalize.normalizePrivateKey?.(key, alg)) || key;
|
|
11
|
+
import { assertCryptoKey } from './is_key_like.js';
|
|
12
|
+
export default async (alg, key, encryptedKey, joseHeader, options) => {
|
|
16
13
|
switch (alg) {
|
|
17
14
|
case 'dir': {
|
|
18
15
|
if (encryptedKey !== undefined)
|
|
@@ -27,16 +24,18 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options)
|
|
|
27
24
|
case 'ECDH-ES+A256KW': {
|
|
28
25
|
if (!isObject(joseHeader.epk))
|
|
29
26
|
throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
30
|
-
|
|
27
|
+
assertCryptoKey(key);
|
|
28
|
+
if (!ecdhes.allowed(key))
|
|
31
29
|
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
32
30
|
const epk = await importJWK(joseHeader.epk, alg);
|
|
31
|
+
assertCryptoKey(epk);
|
|
33
32
|
let partyUInfo;
|
|
34
33
|
let partyVInfo;
|
|
35
34
|
if (joseHeader.apu !== undefined) {
|
|
36
35
|
if (typeof joseHeader.apu !== 'string')
|
|
37
36
|
throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`);
|
|
38
37
|
try {
|
|
39
|
-
partyUInfo = base64url(joseHeader.apu);
|
|
38
|
+
partyUInfo = base64url.decode(joseHeader.apu);
|
|
40
39
|
}
|
|
41
40
|
catch {
|
|
42
41
|
throw new JWEInvalid('Failed to base64url decode the apu');
|
|
@@ -46,27 +45,27 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options)
|
|
|
46
45
|
if (typeof joseHeader.apv !== 'string')
|
|
47
46
|
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
48
47
|
try {
|
|
49
|
-
partyVInfo = base64url(joseHeader.apv);
|
|
48
|
+
partyVInfo = base64url.decode(joseHeader.apv);
|
|
50
49
|
}
|
|
51
50
|
catch {
|
|
52
51
|
throw new JWEInvalid('Failed to base64url decode the apv');
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
|
-
const sharedSecret = await
|
|
54
|
+
const sharedSecret = await ecdhes.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo);
|
|
56
55
|
if (alg === 'ECDH-ES')
|
|
57
56
|
return sharedSecret;
|
|
58
57
|
if (encryptedKey === undefined)
|
|
59
58
|
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
60
|
-
return
|
|
59
|
+
return aeskw.unwrap(alg.slice(-6), sharedSecret, encryptedKey);
|
|
61
60
|
}
|
|
62
|
-
case 'RSA1_5':
|
|
63
61
|
case 'RSA-OAEP':
|
|
64
62
|
case 'RSA-OAEP-256':
|
|
65
63
|
case 'RSA-OAEP-384':
|
|
66
64
|
case 'RSA-OAEP-512': {
|
|
67
65
|
if (encryptedKey === undefined)
|
|
68
66
|
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
69
|
-
|
|
67
|
+
assertCryptoKey(key);
|
|
68
|
+
return rsaes.decrypt(alg, key, encryptedKey);
|
|
70
69
|
}
|
|
71
70
|
case 'PBES2-HS256+A128KW':
|
|
72
71
|
case 'PBES2-HS384+A192KW':
|
|
@@ -82,19 +81,19 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options)
|
|
|
82
81
|
throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
|
|
83
82
|
let p2s;
|
|
84
83
|
try {
|
|
85
|
-
p2s = base64url(joseHeader.p2s);
|
|
84
|
+
p2s = base64url.decode(joseHeader.p2s);
|
|
86
85
|
}
|
|
87
86
|
catch {
|
|
88
87
|
throw new JWEInvalid('Failed to base64url decode the p2s');
|
|
89
88
|
}
|
|
90
|
-
return
|
|
89
|
+
return pbes2kw.unwrap(alg, key, encryptedKey, joseHeader.p2c, p2s);
|
|
91
90
|
}
|
|
92
91
|
case 'A128KW':
|
|
93
92
|
case 'A192KW':
|
|
94
93
|
case 'A256KW': {
|
|
95
94
|
if (encryptedKey === undefined)
|
|
96
95
|
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
97
|
-
return
|
|
96
|
+
return aeskw.unwrap(alg, key, encryptedKey);
|
|
98
97
|
}
|
|
99
98
|
case 'A128GCMKW':
|
|
100
99
|
case 'A192GCMKW':
|
|
@@ -107,14 +106,14 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options)
|
|
|
107
106
|
throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`);
|
|
108
107
|
let iv;
|
|
109
108
|
try {
|
|
110
|
-
iv = base64url(joseHeader.iv);
|
|
109
|
+
iv = base64url.decode(joseHeader.iv);
|
|
111
110
|
}
|
|
112
111
|
catch {
|
|
113
112
|
throw new JWEInvalid('Failed to base64url decode the iv');
|
|
114
113
|
}
|
|
115
114
|
let tag;
|
|
116
115
|
try {
|
|
117
|
-
tag = base64url(joseHeader.tag);
|
|
116
|
+
tag = base64url.decode(joseHeader.tag);
|
|
118
117
|
}
|
|
119
118
|
catch {
|
|
120
119
|
throw new JWEInvalid('Failed to base64url decode the tag');
|
|
@@ -125,5 +124,4 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options)
|
|
|
125
124
|
throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
|
|
126
125
|
}
|
|
127
126
|
}
|
|
128
|
-
}
|
|
129
|
-
export default decryptKeyManagement;
|
|
127
|
+
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const digest = async (algorithm, data) => {
|
|
1
|
+
export default async (algorithm, data) => {
|
|
3
2
|
const subtleDigest = `SHA-${algorithm.slice(-3)}`;
|
|
4
3
|
return new Uint8Array(await crypto.subtle.digest(subtleDigest, data));
|
|
5
4
|
};
|
|
6
|
-
export default digest;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { encoder, concat, uint32be } from './buffer_utils.js';
|
|
2
|
+
import { checkEncCryptoKey } from './crypto_key.js';
|
|
3
|
+
import digest from './digest.js';
|
|
4
|
+
function lengthAndInput(input) {
|
|
5
|
+
return concat(uint32be(input.length), input);
|
|
6
|
+
}
|
|
7
|
+
async function concatKdf(secret, bits, value) {
|
|
8
|
+
const iterations = Math.ceil((bits >> 3) / 32);
|
|
9
|
+
const res = new Uint8Array(iterations * 32);
|
|
10
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
11
|
+
const buf = new Uint8Array(4 + secret.length + value.length);
|
|
12
|
+
buf.set(uint32be(iter + 1));
|
|
13
|
+
buf.set(secret, 4);
|
|
14
|
+
buf.set(value, 4 + secret.length);
|
|
15
|
+
res.set(await digest('sha256', buf), iter * 32);
|
|
16
|
+
}
|
|
17
|
+
return res.slice(0, bits >> 3);
|
|
18
|
+
}
|
|
19
|
+
export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) {
|
|
20
|
+
checkEncCryptoKey(publicKey, 'ECDH');
|
|
21
|
+
checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits');
|
|
22
|
+
const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
|
|
23
|
+
let length;
|
|
24
|
+
if (publicKey.algorithm.name === 'X25519') {
|
|
25
|
+
length = 256;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
length =
|
|
29
|
+
Math.ceil(parseInt(publicKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3;
|
|
30
|
+
}
|
|
31
|
+
const sharedSecret = new Uint8Array(await crypto.subtle.deriveBits({
|
|
32
|
+
name: publicKey.algorithm.name,
|
|
33
|
+
public: publicKey,
|
|
34
|
+
}, privateKey, length));
|
|
35
|
+
return concatKdf(sharedSecret, keyLength, value);
|
|
36
|
+
}
|
|
37
|
+
export function allowed(key) {
|
|
38
|
+
switch (key.algorithm.namedCurve) {
|
|
39
|
+
case 'P-256':
|
|
40
|
+
case 'P-384':
|
|
41
|
+
case 'P-521':
|
|
42
|
+
return true;
|
|
43
|
+
default:
|
|
44
|
+
return key.algorithm.name === 'X25519';
|
|
45
|
+
}
|
|
46
|
+
}
|