jose 5.10.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -15
- package/dist/types/index.d.ts +5 -5
- 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 +4 -4
- package/dist/types/jwt/produce.d.ts +3 -3
- package/dist/types/jwt/sign.d.ts +3 -3
- package/dist/types/jwt/unsecured.d.ts +5 -5
- 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,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
|
+
}
|
|
@@ -1,12 +1,11 @@
|
|
|
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
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import generateIv from '../lib/iv.js';
|
|
4
|
+
import { checkEncCryptoKey } from './crypto_key.js';
|
|
5
|
+
import invalidKeyInput from './invalid_key_input.js';
|
|
6
|
+
import generateIv from './iv.js';
|
|
8
7
|
import { JOSENotSupported } from '../util/errors.js';
|
|
9
|
-
import {
|
|
8
|
+
import { isCryptoKey } from './is_key_like.js';
|
|
10
9
|
async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
11
10
|
if (!(cek instanceof Uint8Array)) {
|
|
12
11
|
throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
|
|
@@ -44,9 +43,9 @@ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
44
43
|
const ciphertext = encrypted.slice(0, -16);
|
|
45
44
|
return { ciphertext, tag, iv };
|
|
46
45
|
}
|
|
47
|
-
|
|
46
|
+
export default async (enc, plaintext, cek, iv, aad) => {
|
|
48
47
|
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
49
|
-
throw new TypeError(invalidKeyInput(cek,
|
|
48
|
+
throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'KeyObject', 'Uint8Array', 'JSON Web Key'));
|
|
50
49
|
}
|
|
51
50
|
if (iv) {
|
|
52
51
|
checkIvLength(enc, iv);
|
|
@@ -73,4 +72,3 @@ const encrypt = async (enc, plaintext, cek, iv, aad) => {
|
|
|
73
72
|
throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
|
|
74
73
|
}
|
|
75
74
|
};
|
|
76
|
-
export default encrypt;
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
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';
|
|
6
|
+
import normalizeKey from './normalize_key.js';
|
|
7
7
|
import generateCek, { bitLength as cekLength } from '../lib/cek.js';
|
|
8
8
|
import { JOSENotSupported } from '../util/errors.js';
|
|
9
9
|
import { exportJWK } from '../key/export.js';
|
|
10
|
-
import checkKeyType from './check_key_type.js';
|
|
11
10
|
import { wrap as aesGcmKw } from './aesgcmkw.js';
|
|
12
|
-
|
|
11
|
+
import { assertCryptoKey } from './is_key_like.js';
|
|
12
|
+
export default async (alg, enc, key, providedCek, providedParameters = {}) => {
|
|
13
13
|
let encryptedKey;
|
|
14
14
|
let parameters;
|
|
15
15
|
let cek;
|
|
16
|
-
checkKeyType(alg, key, 'encrypt');
|
|
17
|
-
key = (await normalize.normalizePublicKey?.(key, alg)) || key;
|
|
18
16
|
switch (alg) {
|
|
19
17
|
case 'dir': {
|
|
20
18
|
cek = key;
|
|
@@ -24,37 +22,43 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
24
22
|
case 'ECDH-ES+A128KW':
|
|
25
23
|
case 'ECDH-ES+A192KW':
|
|
26
24
|
case 'ECDH-ES+A256KW': {
|
|
27
|
-
|
|
25
|
+
assertCryptoKey(key);
|
|
26
|
+
if (!ecdhes.allowed(key)) {
|
|
28
27
|
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
29
28
|
}
|
|
30
29
|
const { apu, apv } = providedParameters;
|
|
31
|
-
let
|
|
32
|
-
|
|
30
|
+
let ephemeralKey;
|
|
31
|
+
if (providedParameters.epk) {
|
|
32
|
+
ephemeralKey = (await normalizeKey(providedParameters.epk, alg));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
ephemeralKey = (await crypto.subtle.generateKey(key.algorithm, true, ['deriveBits'])).privateKey;
|
|
36
|
+
}
|
|
33
37
|
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
|
|
34
|
-
const sharedSecret = await
|
|
38
|
+
const sharedSecret = await ecdhes.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv);
|
|
35
39
|
parameters = { epk: { x, crv, kty } };
|
|
36
40
|
if (kty === 'EC')
|
|
37
41
|
parameters.epk.y = y;
|
|
38
42
|
if (apu)
|
|
39
|
-
parameters.apu = base64url(apu);
|
|
43
|
+
parameters.apu = base64url.encode(apu);
|
|
40
44
|
if (apv)
|
|
41
|
-
parameters.apv = base64url(apv);
|
|
45
|
+
parameters.apv = base64url.encode(apv);
|
|
42
46
|
if (alg === 'ECDH-ES') {
|
|
43
47
|
cek = sharedSecret;
|
|
44
48
|
break;
|
|
45
49
|
}
|
|
46
50
|
cek = providedCek || generateCek(enc);
|
|
47
51
|
const kwAlg = alg.slice(-6);
|
|
48
|
-
encryptedKey = await
|
|
52
|
+
encryptedKey = await aeskw.wrap(kwAlg, sharedSecret, cek);
|
|
49
53
|
break;
|
|
50
54
|
}
|
|
51
|
-
case 'RSA1_5':
|
|
52
55
|
case 'RSA-OAEP':
|
|
53
56
|
case 'RSA-OAEP-256':
|
|
54
57
|
case 'RSA-OAEP-384':
|
|
55
58
|
case 'RSA-OAEP-512': {
|
|
56
59
|
cek = providedCek || generateCek(enc);
|
|
57
|
-
|
|
60
|
+
assertCryptoKey(key);
|
|
61
|
+
encryptedKey = await rsaes.encrypt(alg, key, cek);
|
|
58
62
|
break;
|
|
59
63
|
}
|
|
60
64
|
case 'PBES2-HS256+A128KW':
|
|
@@ -62,14 +66,14 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
62
66
|
case 'PBES2-HS512+A256KW': {
|
|
63
67
|
cek = providedCek || generateCek(enc);
|
|
64
68
|
const { p2c, p2s } = providedParameters;
|
|
65
|
-
({ encryptedKey, ...parameters } = await
|
|
69
|
+
({ encryptedKey, ...parameters } = await pbes2kw.wrap(alg, key, cek, p2c, p2s));
|
|
66
70
|
break;
|
|
67
71
|
}
|
|
68
72
|
case 'A128KW':
|
|
69
73
|
case 'A192KW':
|
|
70
74
|
case 'A256KW': {
|
|
71
75
|
cek = providedCek || generateCek(enc);
|
|
72
|
-
encryptedKey = await
|
|
76
|
+
encryptedKey = await aeskw.wrap(alg, key, cek);
|
|
73
77
|
break;
|
|
74
78
|
}
|
|
75
79
|
case 'A128GCMKW':
|
|
@@ -85,5 +89,4 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
91
|
return { cek, encryptedKey, parameters };
|
|
88
|
-
}
|
|
89
|
-
export default encryptKeyManagement;
|
|
92
|
+
};
|