From 50b88b2ef6828115832e36c74e525b5eb93ce485 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 27 Feb 2023 12:49:23 +0000 Subject: [PATCH 1/3] chore: cleanup after publish --- dist/browser/index.bundle.js | 3368 ---------------- dist/browser/index.bundle.min.js | 4 - dist/browser/index.js | 31 - dist/browser/index.umd.js | 3373 ----------------- dist/browser/index.umd.min.js | 5 - dist/browser/jwe/compact/decrypt.js | 27 - dist/browser/jwe/compact/encrypt.js | 26 - dist/browser/jwe/flattened/decrypt.js | 137 - dist/browser/jwe/flattened/encrypt.js | 175 - dist/browser/jwe/general/decrypt.js | 31 - dist/browser/jwe/general/encrypt.js | 178 - dist/browser/jwk/embedded.js | 17 - dist/browser/jwk/thumbprint.js | 53 - dist/browser/jwks/local.js | 113 - dist/browser/jwks/remote.js | 81 - dist/browser/jws/compact/sign.js | 17 - dist/browser/jws/compact/verify.js | 21 - dist/browser/jws/flattened/sign.js | 81 - dist/browser/jws/flattened/verify.js | 104 - dist/browser/jws/general/sign.js | 67 - dist/browser/jws/general/verify.js | 24 - dist/browser/jwt/decrypt.js | 23 - dist/browser/jwt/encrypt.js | 68 - dist/browser/jwt/produce.js | 54 - dist/browser/jwt/sign.js | 21 - dist/browser/jwt/unsecured.js | 32 - dist/browser/jwt/verify.js | 16 - dist/browser/key/export.js | 12 - dist/browser/key/generate_key_pair.js | 4 - dist/browser/key/generate_secret.js | 4 - dist/browser/key/import.js | 50 - dist/browser/lib/aesgcmkw.js | 14 - dist/browser/lib/buffer_utils.js | 51 - dist/browser/lib/cek.js | 20 - dist/browser/lib/check_iv_length.js | 8 - dist/browser/lib/check_key_type.js | 45 - dist/browser/lib/check_p2s.js | 6 - dist/browser/lib/crypto_key.js | 158 - dist/browser/lib/decrypt_key_management.js | 98 - dist/browser/lib/encrypt_key_management.js | 87 - dist/browser/lib/epoch.js | 1 - dist/browser/lib/format_pem.js | 4 - dist/browser/lib/invalid_key_input.js | 30 - dist/browser/lib/is_disjoint.js | 22 - dist/browser/lib/is_object.js | 16 - dist/browser/lib/iv.js | 20 - dist/browser/lib/jwt_claims_set.js | 91 - dist/browser/lib/secs.js | 44 - dist/browser/lib/validate_algorithms.js | 11 - dist/browser/lib/validate_crit.js | 34 - dist/browser/package.json | 1 - dist/browser/runtime/aeskw.js | 32 - dist/browser/runtime/asn1.js | 214 -- dist/browser/runtime/base64url.js | 37 - dist/browser/runtime/bogus.js | 6 - dist/browser/runtime/check_cek_length.js | 8 - dist/browser/runtime/check_key_length.js | 8 - dist/browser/runtime/decrypt.js | 85 - dist/browser/runtime/digest.js | 6 - dist/browser/runtime/ecdhes.js | 46 - dist/browser/runtime/encrypt.js | 68 - dist/browser/runtime/env.js | 5 - dist/browser/runtime/fetch_jwks.js | 34 - dist/browser/runtime/generate.js | 153 - dist/browser/runtime/get_sign_verify_key.js | 17 - dist/browser/runtime/is_key_like.js | 5 - dist/browser/runtime/jwk_to_key.js | 155 - dist/browser/runtime/key_to_jwk.js | 21 - dist/browser/runtime/pbes2kw.js | 51 - dist/browser/runtime/random.js | 2 - dist/browser/runtime/rsaes.js | 37 - dist/browser/runtime/sign.js | 11 - dist/browser/runtime/subtle_dsa.js | 30 - dist/browser/runtime/subtle_rsaes.js | 12 - dist/browser/runtime/timing_safe_equal.js | 19 - dist/browser/runtime/verify.js | 16 - dist/browser/runtime/webcrypto.js | 2 - dist/browser/runtime/zlib.js | 7 - dist/browser/util/base64url.js | 3 - dist/browser/util/decode_jwt.js | 32 - dist/browser/util/decode_protected_header.js | 34 - dist/browser/util/errors.js | 148 - dist/deno/README.md | 51 - dist/deno/index.ts | 98 - dist/deno/jwe/compact/decrypt.ts | 99 - dist/deno/jwe/compact/encrypt.ts | 91 - dist/deno/jwe/flattened/decrypt.ts | 247 -- dist/deno/jwe/flattened/encrypt.ts | 309 -- dist/deno/jwe/general/decrypt.ts | 107 - dist/deno/jwe/general/encrypt.ts | 306 -- dist/deno/jwk/embedded.ts | 43 - dist/deno/jwk/thumbprint.ts | 114 - dist/deno/jwks/local.ts | 245 -- dist/deno/jwks/remote.ts | 204 - dist/deno/jws/compact/sign.ts | 52 - dist/deno/jws/compact/verify.ts | 90 - dist/deno/jws/flattened/sign.ts | 152 - dist/deno/jws/flattened/verify.ts | 203 - dist/deno/jws/general/sign.ts | 143 - dist/deno/jws/general/verify.ts | 98 - dist/deno/jwt/decrypt.ts | 108 - dist/deno/jwt/encrypt.ts | 162 - dist/deno/jwt/produce.ts | 104 - dist/deno/jwt/sign.ts | 134 - dist/deno/jwt/unsecured.ts | 78 - dist/deno/jwt/verify.ts | 147 - dist/deno/key/export.ts | 60 - dist/deno/key/generate_key_pair.ts | 57 - dist/deno/key/generate_secret.ts | 35 - dist/deno/key/import.ts | 193 - dist/deno/lib/aesgcmkw.ts | 30 - dist/deno/lib/buffer_utils.ts | 60 - dist/deno/lib/cek.ts | 21 - dist/deno/lib/check_iv_length.ts | 10 - dist/deno/lib/check_key_type.ts | 74 - dist/deno/lib/check_p2s.ts | 7 - dist/deno/lib/crypto_key.ts | 151 - dist/deno/lib/decrypt_key_management.ts | 141 - dist/deno/lib/encrypt_key_management.ts | 124 - dist/deno/lib/epoch.ts | 1 - dist/deno/lib/format_pem.ts | 4 - dist/deno/lib/invalid_key_input.ts | 30 - dist/deno/lib/is_disjoint.ts | 26 - dist/deno/lib/is_object.ts | 17 - dist/deno/lib/iv.ts | 21 - dist/deno/lib/jwt_claims_set.ts | 139 - dist/deno/lib/secs.ts | 51 - dist/deno/lib/validate_algorithms.ts | 16 - dist/deno/lib/validate_crit.ts | 56 - dist/deno/runtime/aeskw.ts | 56 - dist/deno/runtime/asn1.ts | 268 -- dist/deno/runtime/base64url.ts | 41 - dist/deno/runtime/bogus.ts | 7 - dist/deno/runtime/check_cek_length.ts | 12 - dist/deno/runtime/check_key_length.ts | 8 - dist/deno/runtime/decrypt.ts | 137 - dist/deno/runtime/digest.ts | 11 - dist/deno/runtime/ecdhes.ts | 72 - dist/deno/runtime/encrypt.ts | 122 - dist/deno/runtime/env.ts | 10 - dist/deno/runtime/fetch_jwks.ts | 43 - dist/deno/runtime/generate.ts | 169 - dist/deno/runtime/get_sign_verify_key.ts | 26 - dist/deno/runtime/interfaces.d.ts | 75 - dist/deno/runtime/is_key_like.ts | 8 - dist/deno/runtime/jwk_to_key.ts | 167 - dist/deno/runtime/key_to_jwk.ts | 25 - dist/deno/runtime/pbes2kw.ts | 78 - dist/deno/runtime/random.ts | 3 - dist/deno/runtime/rsaes.ts | 64 - dist/deno/runtime/sign.ts | 18 - dist/deno/runtime/subtle_dsa.ts | 35 - dist/deno/runtime/subtle_rsaes.ts | 15 - dist/deno/runtime/timing_safe_equal.ts | 23 - dist/deno/runtime/verify.ts | 18 - dist/deno/runtime/webcrypto.ts | 3 - dist/deno/runtime/zlib.ts | 13 - dist/deno/types.d.ts | 628 --- dist/deno/util/base64url.ts | 21 - dist/deno/util/decode_jwt.ts | 49 - dist/deno/util/decode_protected_header.ts | 48 - dist/deno/util/errors.ts | 185 - dist/node/cjs/index.js | 65 - dist/node/cjs/jwe/compact/decrypt.js | 31 - dist/node/cjs/jwe/compact/encrypt.js | 30 - dist/node/cjs/jwe/flattened/decrypt.js | 141 - dist/node/cjs/jwe/flattened/encrypt.js | 179 - dist/node/cjs/jwe/general/decrypt.js | 35 - dist/node/cjs/jwe/general/encrypt.js | 182 - dist/node/cjs/jwk/embedded.js | 21 - dist/node/cjs/jwk/thumbprint.js | 58 - dist/node/cjs/jwks/local.js | 119 - dist/node/cjs/jwks/remote.js | 85 - dist/node/cjs/jws/compact/sign.js | 21 - dist/node/cjs/jws/compact/verify.js | 25 - dist/node/cjs/jws/flattened/sign.js | 85 - dist/node/cjs/jws/flattened/verify.js | 108 - dist/node/cjs/jws/general/sign.js | 71 - dist/node/cjs/jws/general/verify.js | 28 - dist/node/cjs/jwt/decrypt.js | 27 - dist/node/cjs/jwt/encrypt.js | 72 - dist/node/cjs/jwt/produce.js | 58 - dist/node/cjs/jwt/sign.js | 25 - dist/node/cjs/jwt/unsecured.js | 36 - dist/node/cjs/jwt/verify.js | 20 - dist/node/cjs/key/export.js | 18 - dist/node/cjs/key/generate_key_pair.js | 8 - dist/node/cjs/key/generate_secret.js | 8 - dist/node/cjs/key/import.js | 57 - dist/node/cjs/lib/aesgcmkw.js | 19 - dist/node/cjs/lib/buffer_utils.js | 60 - dist/node/cjs/lib/cek.js | 24 - dist/node/cjs/lib/check_iv_length.js | 10 - dist/node/cjs/lib/check_key_type.js | 47 - dist/node/cjs/lib/check_p2s.js | 9 - dist/node/cjs/lib/crypto_key.js | 163 - dist/node/cjs/lib/decrypt_key_management.js | 100 - dist/node/cjs/lib/encrypt_key_management.js | 89 - dist/node/cjs/lib/epoch.js | 3 - dist/node/cjs/lib/invalid_key_input.js | 34 - dist/node/cjs/lib/is_disjoint.js | 24 - dist/node/cjs/lib/is_object.js | 19 - dist/node/cjs/lib/iv.js | 24 - dist/node/cjs/lib/jwt_claims_set.js | 93 - dist/node/cjs/lib/secs.js | 46 - dist/node/cjs/lib/validate_algorithms.js | 13 - dist/node/cjs/lib/validate_crit.js | 36 - dist/node/cjs/runtime/aeskw.js | 55 - dist/node/cjs/runtime/asn1.js | 54 - .../node/cjs/runtime/asn1_sequence_decoder.js | 47 - .../node/cjs/runtime/asn1_sequence_encoder.js | 91 - dist/node/cjs/runtime/base64url.js | 26 - dist/node/cjs/runtime/cbc_tag.js | 11 - dist/node/cjs/runtime/check_cek_length.js | 37 - dist/node/cjs/runtime/check_modulus_length.js | 52 - dist/node/cjs/runtime/ciphers.js | 8 - dist/node/cjs/runtime/decrypt.js | 97 - dist/node/cjs/runtime/digest.js | 5 - dist/node/cjs/runtime/dsa_digest.js | 25 - dist/node/cjs/runtime/ecdhes.js | 70 - dist/node/cjs/runtime/encrypt.js | 74 - dist/node/cjs/runtime/env.js | 7 - dist/node/cjs/runtime/fetch_jwks.js | 45 - dist/node/cjs/runtime/flags.js | 8 - dist/node/cjs/runtime/generate.js | 105 - dist/node/cjs/runtime/get_named_curve.js | 95 - dist/node/cjs/runtime/get_sign_verify_key.js | 24 - dist/node/cjs/runtime/hmac_digest.js | 16 - dist/node/cjs/runtime/is_key_like.js | 11 - dist/node/cjs/runtime/is_key_object.js | 7 - dist/node/cjs/runtime/jwk_to_key.js | 118 - dist/node/cjs/runtime/key_to_jwk.js | 160 - dist/node/cjs/runtime/node_key.js | 78 - dist/node/cjs/runtime/pbes2kw.js | 48 - dist/node/cjs/runtime/random.js | 5 - dist/node/cjs/runtime/rsaes.js | 69 - dist/node/cjs/runtime/sign.js | 25 - dist/node/cjs/runtime/timing_safe_equal.js | 5 - dist/node/cjs/runtime/verify.js | 38 - dist/node/cjs/runtime/webcrypto.js | 11 - dist/node/cjs/runtime/zlib.js | 11 - dist/node/cjs/util/base64url.js | 6 - dist/node/cjs/util/decode_jwt.js | 36 - dist/node/cjs/util/decode_protected_header.js | 38 - dist/node/cjs/util/errors.js | 166 - dist/node/esm/index.js | 29 - dist/node/esm/jwe/compact/decrypt.js | 27 - dist/node/esm/jwe/compact/encrypt.js | 26 - dist/node/esm/jwe/flattened/decrypt.js | 137 - dist/node/esm/jwe/flattened/encrypt.js | 175 - dist/node/esm/jwe/general/decrypt.js | 31 - dist/node/esm/jwe/general/encrypt.js | 178 - dist/node/esm/jwk/embedded.js | 17 - dist/node/esm/jwk/thumbprint.js | 53 - dist/node/esm/jwks/local.js | 113 - dist/node/esm/jwks/remote.js | 81 - dist/node/esm/jws/compact/sign.js | 17 - dist/node/esm/jws/compact/verify.js | 21 - dist/node/esm/jws/flattened/sign.js | 81 - dist/node/esm/jws/flattened/verify.js | 104 - dist/node/esm/jws/general/sign.js | 67 - dist/node/esm/jws/general/verify.js | 24 - dist/node/esm/jwt/decrypt.js | 23 - dist/node/esm/jwt/encrypt.js | 68 - dist/node/esm/jwt/produce.js | 54 - dist/node/esm/jwt/sign.js | 21 - dist/node/esm/jwt/unsecured.js | 32 - dist/node/esm/jwt/verify.js | 16 - dist/node/esm/key/export.js | 12 - dist/node/esm/key/generate_key_pair.js | 4 - dist/node/esm/key/generate_secret.js | 4 - dist/node/esm/key/import.js | 50 - dist/node/esm/lib/aesgcmkw.js | 14 - dist/node/esm/lib/buffer_utils.js | 51 - dist/node/esm/lib/cek.js | 20 - dist/node/esm/lib/check_iv_length.js | 8 - dist/node/esm/lib/check_key_type.js | 45 - dist/node/esm/lib/check_p2s.js | 6 - dist/node/esm/lib/crypto_key.js | 158 - dist/node/esm/lib/decrypt_key_management.js | 98 - dist/node/esm/lib/encrypt_key_management.js | 87 - dist/node/esm/lib/epoch.js | 1 - dist/node/esm/lib/invalid_key_input.js | 30 - dist/node/esm/lib/is_disjoint.js | 22 - dist/node/esm/lib/is_object.js | 16 - dist/node/esm/lib/iv.js | 20 - dist/node/esm/lib/jwt_claims_set.js | 91 - dist/node/esm/lib/secs.js | 44 - dist/node/esm/lib/validate_algorithms.js | 11 - dist/node/esm/lib/validate_crit.js | 34 - dist/node/esm/package.json | 1 - dist/node/esm/runtime/aeskw.js | 50 - dist/node/esm/runtime/asn1.js | 46 - .../node/esm/runtime/asn1_sequence_decoder.js | 44 - .../node/esm/runtime/asn1_sequence_encoder.js | 88 - dist/node/esm/runtime/base64url.js | 20 - dist/node/esm/runtime/cbc_tag.js | 8 - dist/node/esm/runtime/check_cek_length.js | 35 - dist/node/esm/runtime/check_modulus_length.js | 48 - dist/node/esm/runtime/ciphers.js | 6 - dist/node/esm/runtime/decrypt.js | 95 - dist/node/esm/runtime/digest.js | 3 - dist/node/esm/runtime/dsa_digest.js | 22 - dist/node/esm/runtime/ecdhes.js | 64 - dist/node/esm/runtime/encrypt.js | 72 - dist/node/esm/runtime/env.js | 3 - dist/node/esm/runtime/fetch_jwks.js | 43 - dist/node/esm/runtime/flags.js | 5 - dist/node/esm/runtime/generate.js | 100 - dist/node/esm/runtime/get_named_curve.js | 91 - dist/node/esm/runtime/get_sign_verify_key.js | 21 - dist/node/esm/runtime/hmac_digest.js | 13 - dist/node/esm/runtime/is_key_like.js | 8 - dist/node/esm/runtime/is_key_object.js | 5 - dist/node/esm/runtime/jwk_to_key.js | 116 - dist/node/esm/runtime/key_to_jwk.js | 158 - dist/node/esm/runtime/node_key.js | 75 - dist/node/esm/runtime/pbes2kw.js | 43 - dist/node/esm/runtime/random.js | 1 - dist/node/esm/runtime/rsaes.js | 64 - dist/node/esm/runtime/sign.js | 23 - dist/node/esm/runtime/timing_safe_equal.js | 3 - dist/node/esm/runtime/verify.js | 36 - dist/node/esm/runtime/webcrypto.js | 8 - dist/node/esm/runtime/zlib.js | 6 - dist/node/esm/util/base64url.js | 3 - dist/node/esm/util/decode_jwt.js | 32 - dist/node/esm/util/decode_protected_header.js | 34 - dist/node/esm/util/errors.js | 148 - dist/types/index.d.ts | 47 - dist/types/jwe/compact/decrypt.d.ts | 33 - dist/types/jwe/compact/encrypt.d.ts | 60 - dist/types/jwe/flattened/decrypt.d.ts | 43 - dist/types/jwe/flattened/encrypt.d.ts | 89 - dist/types/jwe/general/decrypt.d.ts | 47 - dist/types/jwe/general/encrypt.d.ts | 74 - dist/types/jwk/embedded.d.ts | 23 - dist/types/jwk/thumbprint.d.ts | 47 - dist/types/jwks/local.d.ts | 85 - dist/types/jwks/remote.d.ts | 92 - dist/types/jws/compact/sign.d.ts | 34 - dist/types/jws/compact/verify.d.ts | 37 - dist/types/jws/flattened/sign.d.ts | 42 - dist/types/jws/flattened/verify.d.ts | 42 - dist/types/jws/general/sign.d.ts | 54 - dist/types/jws/general/verify.d.ts | 45 - dist/types/jwt/decrypt.d.ts | 41 - dist/types/jwt/encrypt.d.ts | 85 - dist/types/jwt/produce.d.ts | 54 - dist/types/jwt/sign.d.ts | 113 - dist/types/jwt/unsecured.d.ts | 44 - dist/types/jwt/verify.d.ts | 108 - dist/types/key/export.d.ts | 47 - dist/types/key/generate_key_pair.d.ts | 44 - dist/types/key/generate_secret.d.ts | 26 - dist/types/key/import.d.ts | 119 - dist/types/types.d.ts | 628 --- dist/types/util/base64url.d.ts | 19 - dist/types/util/decode_jwt.d.ts | 17 - dist/types/util/decode_protected_header.d.ts | 15 - dist/types/util/errors.d.ts | 99 - 361 files changed, 27874 deletions(-) delete mode 100644 dist/browser/index.bundle.js delete mode 100644 dist/browser/index.bundle.min.js delete mode 100644 dist/browser/index.js delete mode 100644 dist/browser/index.umd.js delete mode 100644 dist/browser/index.umd.min.js delete mode 100644 dist/browser/jwe/compact/decrypt.js delete mode 100644 dist/browser/jwe/compact/encrypt.js delete mode 100644 dist/browser/jwe/flattened/decrypt.js delete mode 100644 dist/browser/jwe/flattened/encrypt.js delete mode 100644 dist/browser/jwe/general/decrypt.js delete mode 100644 dist/browser/jwe/general/encrypt.js delete mode 100644 dist/browser/jwk/embedded.js delete mode 100644 dist/browser/jwk/thumbprint.js delete mode 100644 dist/browser/jwks/local.js delete mode 100644 dist/browser/jwks/remote.js delete mode 100644 dist/browser/jws/compact/sign.js delete mode 100644 dist/browser/jws/compact/verify.js delete mode 100644 dist/browser/jws/flattened/sign.js delete mode 100644 dist/browser/jws/flattened/verify.js delete mode 100644 dist/browser/jws/general/sign.js delete mode 100644 dist/browser/jws/general/verify.js delete mode 100644 dist/browser/jwt/decrypt.js delete mode 100644 dist/browser/jwt/encrypt.js delete mode 100644 dist/browser/jwt/produce.js delete mode 100644 dist/browser/jwt/sign.js delete mode 100644 dist/browser/jwt/unsecured.js delete mode 100644 dist/browser/jwt/verify.js delete mode 100644 dist/browser/key/export.js delete mode 100644 dist/browser/key/generate_key_pair.js delete mode 100644 dist/browser/key/generate_secret.js delete mode 100644 dist/browser/key/import.js delete mode 100644 dist/browser/lib/aesgcmkw.js delete mode 100644 dist/browser/lib/buffer_utils.js delete mode 100644 dist/browser/lib/cek.js delete mode 100644 dist/browser/lib/check_iv_length.js delete mode 100644 dist/browser/lib/check_key_type.js delete mode 100644 dist/browser/lib/check_p2s.js delete mode 100644 dist/browser/lib/crypto_key.js delete mode 100644 dist/browser/lib/decrypt_key_management.js delete mode 100644 dist/browser/lib/encrypt_key_management.js delete mode 100644 dist/browser/lib/epoch.js delete mode 100644 dist/browser/lib/format_pem.js delete mode 100644 dist/browser/lib/invalid_key_input.js delete mode 100644 dist/browser/lib/is_disjoint.js delete mode 100644 dist/browser/lib/is_object.js delete mode 100644 dist/browser/lib/iv.js delete mode 100644 dist/browser/lib/jwt_claims_set.js delete mode 100644 dist/browser/lib/secs.js delete mode 100644 dist/browser/lib/validate_algorithms.js delete mode 100644 dist/browser/lib/validate_crit.js delete mode 100644 dist/browser/package.json delete mode 100644 dist/browser/runtime/aeskw.js delete mode 100644 dist/browser/runtime/asn1.js delete mode 100644 dist/browser/runtime/base64url.js delete mode 100644 dist/browser/runtime/bogus.js delete mode 100644 dist/browser/runtime/check_cek_length.js delete mode 100644 dist/browser/runtime/check_key_length.js delete mode 100644 dist/browser/runtime/decrypt.js delete mode 100644 dist/browser/runtime/digest.js delete mode 100644 dist/browser/runtime/ecdhes.js delete mode 100644 dist/browser/runtime/encrypt.js delete mode 100644 dist/browser/runtime/env.js delete mode 100644 dist/browser/runtime/fetch_jwks.js delete mode 100644 dist/browser/runtime/generate.js delete mode 100644 dist/browser/runtime/get_sign_verify_key.js delete mode 100644 dist/browser/runtime/is_key_like.js delete mode 100644 dist/browser/runtime/jwk_to_key.js delete mode 100644 dist/browser/runtime/key_to_jwk.js delete mode 100644 dist/browser/runtime/pbes2kw.js delete mode 100644 dist/browser/runtime/random.js delete mode 100644 dist/browser/runtime/rsaes.js delete mode 100644 dist/browser/runtime/sign.js delete mode 100644 dist/browser/runtime/subtle_dsa.js delete mode 100644 dist/browser/runtime/subtle_rsaes.js delete mode 100644 dist/browser/runtime/timing_safe_equal.js delete mode 100644 dist/browser/runtime/verify.js delete mode 100644 dist/browser/runtime/webcrypto.js delete mode 100644 dist/browser/runtime/zlib.js delete mode 100644 dist/browser/util/base64url.js delete mode 100644 dist/browser/util/decode_jwt.js delete mode 100644 dist/browser/util/decode_protected_header.js delete mode 100644 dist/browser/util/errors.js delete mode 100644 dist/deno/README.md delete mode 100644 dist/deno/index.ts delete mode 100644 dist/deno/jwe/compact/decrypt.ts delete mode 100644 dist/deno/jwe/compact/encrypt.ts delete mode 100644 dist/deno/jwe/flattened/decrypt.ts delete mode 100644 dist/deno/jwe/flattened/encrypt.ts delete mode 100644 dist/deno/jwe/general/decrypt.ts delete mode 100644 dist/deno/jwe/general/encrypt.ts delete mode 100644 dist/deno/jwk/embedded.ts delete mode 100644 dist/deno/jwk/thumbprint.ts delete mode 100644 dist/deno/jwks/local.ts delete mode 100644 dist/deno/jwks/remote.ts delete mode 100644 dist/deno/jws/compact/sign.ts delete mode 100644 dist/deno/jws/compact/verify.ts delete mode 100644 dist/deno/jws/flattened/sign.ts delete mode 100644 dist/deno/jws/flattened/verify.ts delete mode 100644 dist/deno/jws/general/sign.ts delete mode 100644 dist/deno/jws/general/verify.ts delete mode 100644 dist/deno/jwt/decrypt.ts delete mode 100644 dist/deno/jwt/encrypt.ts delete mode 100644 dist/deno/jwt/produce.ts delete mode 100644 dist/deno/jwt/sign.ts delete mode 100644 dist/deno/jwt/unsecured.ts delete mode 100644 dist/deno/jwt/verify.ts delete mode 100644 dist/deno/key/export.ts delete mode 100644 dist/deno/key/generate_key_pair.ts delete mode 100644 dist/deno/key/generate_secret.ts delete mode 100644 dist/deno/key/import.ts delete mode 100644 dist/deno/lib/aesgcmkw.ts delete mode 100644 dist/deno/lib/buffer_utils.ts delete mode 100644 dist/deno/lib/cek.ts delete mode 100644 dist/deno/lib/check_iv_length.ts delete mode 100644 dist/deno/lib/check_key_type.ts delete mode 100644 dist/deno/lib/check_p2s.ts delete mode 100644 dist/deno/lib/crypto_key.ts delete mode 100644 dist/deno/lib/decrypt_key_management.ts delete mode 100644 dist/deno/lib/encrypt_key_management.ts delete mode 100644 dist/deno/lib/epoch.ts delete mode 100644 dist/deno/lib/format_pem.ts delete mode 100644 dist/deno/lib/invalid_key_input.ts delete mode 100644 dist/deno/lib/is_disjoint.ts delete mode 100644 dist/deno/lib/is_object.ts delete mode 100644 dist/deno/lib/iv.ts delete mode 100644 dist/deno/lib/jwt_claims_set.ts delete mode 100644 dist/deno/lib/secs.ts delete mode 100644 dist/deno/lib/validate_algorithms.ts delete mode 100644 dist/deno/lib/validate_crit.ts delete mode 100644 dist/deno/runtime/aeskw.ts delete mode 100644 dist/deno/runtime/asn1.ts delete mode 100644 dist/deno/runtime/base64url.ts delete mode 100644 dist/deno/runtime/bogus.ts delete mode 100644 dist/deno/runtime/check_cek_length.ts delete mode 100644 dist/deno/runtime/check_key_length.ts delete mode 100644 dist/deno/runtime/decrypt.ts delete mode 100644 dist/deno/runtime/digest.ts delete mode 100644 dist/deno/runtime/ecdhes.ts delete mode 100644 dist/deno/runtime/encrypt.ts delete mode 100644 dist/deno/runtime/env.ts delete mode 100644 dist/deno/runtime/fetch_jwks.ts delete mode 100644 dist/deno/runtime/generate.ts delete mode 100644 dist/deno/runtime/get_sign_verify_key.ts delete mode 100644 dist/deno/runtime/interfaces.d.ts delete mode 100644 dist/deno/runtime/is_key_like.ts delete mode 100644 dist/deno/runtime/jwk_to_key.ts delete mode 100644 dist/deno/runtime/key_to_jwk.ts delete mode 100644 dist/deno/runtime/pbes2kw.ts delete mode 100644 dist/deno/runtime/random.ts delete mode 100644 dist/deno/runtime/rsaes.ts delete mode 100644 dist/deno/runtime/sign.ts delete mode 100644 dist/deno/runtime/subtle_dsa.ts delete mode 100644 dist/deno/runtime/subtle_rsaes.ts delete mode 100644 dist/deno/runtime/timing_safe_equal.ts delete mode 100644 dist/deno/runtime/verify.ts delete mode 100644 dist/deno/runtime/webcrypto.ts delete mode 100644 dist/deno/runtime/zlib.ts delete mode 100644 dist/deno/types.d.ts delete mode 100644 dist/deno/util/base64url.ts delete mode 100644 dist/deno/util/decode_jwt.ts delete mode 100644 dist/deno/util/decode_protected_header.ts delete mode 100644 dist/deno/util/errors.ts delete mode 100644 dist/node/cjs/index.js delete mode 100644 dist/node/cjs/jwe/compact/decrypt.js delete mode 100644 dist/node/cjs/jwe/compact/encrypt.js delete mode 100644 dist/node/cjs/jwe/flattened/decrypt.js delete mode 100644 dist/node/cjs/jwe/flattened/encrypt.js delete mode 100644 dist/node/cjs/jwe/general/decrypt.js delete mode 100644 dist/node/cjs/jwe/general/encrypt.js delete mode 100644 dist/node/cjs/jwk/embedded.js delete mode 100644 dist/node/cjs/jwk/thumbprint.js delete mode 100644 dist/node/cjs/jwks/local.js delete mode 100644 dist/node/cjs/jwks/remote.js delete mode 100644 dist/node/cjs/jws/compact/sign.js delete mode 100644 dist/node/cjs/jws/compact/verify.js delete mode 100644 dist/node/cjs/jws/flattened/sign.js delete mode 100644 dist/node/cjs/jws/flattened/verify.js delete mode 100644 dist/node/cjs/jws/general/sign.js delete mode 100644 dist/node/cjs/jws/general/verify.js delete mode 100644 dist/node/cjs/jwt/decrypt.js delete mode 100644 dist/node/cjs/jwt/encrypt.js delete mode 100644 dist/node/cjs/jwt/produce.js delete mode 100644 dist/node/cjs/jwt/sign.js delete mode 100644 dist/node/cjs/jwt/unsecured.js delete mode 100644 dist/node/cjs/jwt/verify.js delete mode 100644 dist/node/cjs/key/export.js delete mode 100644 dist/node/cjs/key/generate_key_pair.js delete mode 100644 dist/node/cjs/key/generate_secret.js delete mode 100644 dist/node/cjs/key/import.js delete mode 100644 dist/node/cjs/lib/aesgcmkw.js delete mode 100644 dist/node/cjs/lib/buffer_utils.js delete mode 100644 dist/node/cjs/lib/cek.js delete mode 100644 dist/node/cjs/lib/check_iv_length.js delete mode 100644 dist/node/cjs/lib/check_key_type.js delete mode 100644 dist/node/cjs/lib/check_p2s.js delete mode 100644 dist/node/cjs/lib/crypto_key.js delete mode 100644 dist/node/cjs/lib/decrypt_key_management.js delete mode 100644 dist/node/cjs/lib/encrypt_key_management.js delete mode 100644 dist/node/cjs/lib/epoch.js delete mode 100644 dist/node/cjs/lib/invalid_key_input.js delete mode 100644 dist/node/cjs/lib/is_disjoint.js delete mode 100644 dist/node/cjs/lib/is_object.js delete mode 100644 dist/node/cjs/lib/iv.js delete mode 100644 dist/node/cjs/lib/jwt_claims_set.js delete mode 100644 dist/node/cjs/lib/secs.js delete mode 100644 dist/node/cjs/lib/validate_algorithms.js delete mode 100644 dist/node/cjs/lib/validate_crit.js delete mode 100644 dist/node/cjs/runtime/aeskw.js delete mode 100644 dist/node/cjs/runtime/asn1.js delete mode 100644 dist/node/cjs/runtime/asn1_sequence_decoder.js delete mode 100644 dist/node/cjs/runtime/asn1_sequence_encoder.js delete mode 100644 dist/node/cjs/runtime/base64url.js delete mode 100644 dist/node/cjs/runtime/cbc_tag.js delete mode 100644 dist/node/cjs/runtime/check_cek_length.js delete mode 100644 dist/node/cjs/runtime/check_modulus_length.js delete mode 100644 dist/node/cjs/runtime/ciphers.js delete mode 100644 dist/node/cjs/runtime/decrypt.js delete mode 100644 dist/node/cjs/runtime/digest.js delete mode 100644 dist/node/cjs/runtime/dsa_digest.js delete mode 100644 dist/node/cjs/runtime/ecdhes.js delete mode 100644 dist/node/cjs/runtime/encrypt.js delete mode 100644 dist/node/cjs/runtime/env.js delete mode 100644 dist/node/cjs/runtime/fetch_jwks.js delete mode 100644 dist/node/cjs/runtime/flags.js delete mode 100644 dist/node/cjs/runtime/generate.js delete mode 100644 dist/node/cjs/runtime/get_named_curve.js delete mode 100644 dist/node/cjs/runtime/get_sign_verify_key.js delete mode 100644 dist/node/cjs/runtime/hmac_digest.js delete mode 100644 dist/node/cjs/runtime/is_key_like.js delete mode 100644 dist/node/cjs/runtime/is_key_object.js delete mode 100644 dist/node/cjs/runtime/jwk_to_key.js delete mode 100644 dist/node/cjs/runtime/key_to_jwk.js delete mode 100644 dist/node/cjs/runtime/node_key.js delete mode 100644 dist/node/cjs/runtime/pbes2kw.js delete mode 100644 dist/node/cjs/runtime/random.js delete mode 100644 dist/node/cjs/runtime/rsaes.js delete mode 100644 dist/node/cjs/runtime/sign.js delete mode 100644 dist/node/cjs/runtime/timing_safe_equal.js delete mode 100644 dist/node/cjs/runtime/verify.js delete mode 100644 dist/node/cjs/runtime/webcrypto.js delete mode 100644 dist/node/cjs/runtime/zlib.js delete mode 100644 dist/node/cjs/util/base64url.js delete mode 100644 dist/node/cjs/util/decode_jwt.js delete mode 100644 dist/node/cjs/util/decode_protected_header.js delete mode 100644 dist/node/cjs/util/errors.js delete mode 100644 dist/node/esm/index.js delete mode 100644 dist/node/esm/jwe/compact/decrypt.js delete mode 100644 dist/node/esm/jwe/compact/encrypt.js delete mode 100644 dist/node/esm/jwe/flattened/decrypt.js delete mode 100644 dist/node/esm/jwe/flattened/encrypt.js delete mode 100644 dist/node/esm/jwe/general/decrypt.js delete mode 100644 dist/node/esm/jwe/general/encrypt.js delete mode 100644 dist/node/esm/jwk/embedded.js delete mode 100644 dist/node/esm/jwk/thumbprint.js delete mode 100644 dist/node/esm/jwks/local.js delete mode 100644 dist/node/esm/jwks/remote.js delete mode 100644 dist/node/esm/jws/compact/sign.js delete mode 100644 dist/node/esm/jws/compact/verify.js delete mode 100644 dist/node/esm/jws/flattened/sign.js delete mode 100644 dist/node/esm/jws/flattened/verify.js delete mode 100644 dist/node/esm/jws/general/sign.js delete mode 100644 dist/node/esm/jws/general/verify.js delete mode 100644 dist/node/esm/jwt/decrypt.js delete mode 100644 dist/node/esm/jwt/encrypt.js delete mode 100644 dist/node/esm/jwt/produce.js delete mode 100644 dist/node/esm/jwt/sign.js delete mode 100644 dist/node/esm/jwt/unsecured.js delete mode 100644 dist/node/esm/jwt/verify.js delete mode 100644 dist/node/esm/key/export.js delete mode 100644 dist/node/esm/key/generate_key_pair.js delete mode 100644 dist/node/esm/key/generate_secret.js delete mode 100644 dist/node/esm/key/import.js delete mode 100644 dist/node/esm/lib/aesgcmkw.js delete mode 100644 dist/node/esm/lib/buffer_utils.js delete mode 100644 dist/node/esm/lib/cek.js delete mode 100644 dist/node/esm/lib/check_iv_length.js delete mode 100644 dist/node/esm/lib/check_key_type.js delete mode 100644 dist/node/esm/lib/check_p2s.js delete mode 100644 dist/node/esm/lib/crypto_key.js delete mode 100644 dist/node/esm/lib/decrypt_key_management.js delete mode 100644 dist/node/esm/lib/encrypt_key_management.js delete mode 100644 dist/node/esm/lib/epoch.js delete mode 100644 dist/node/esm/lib/invalid_key_input.js delete mode 100644 dist/node/esm/lib/is_disjoint.js delete mode 100644 dist/node/esm/lib/is_object.js delete mode 100644 dist/node/esm/lib/iv.js delete mode 100644 dist/node/esm/lib/jwt_claims_set.js delete mode 100644 dist/node/esm/lib/secs.js delete mode 100644 dist/node/esm/lib/validate_algorithms.js delete mode 100644 dist/node/esm/lib/validate_crit.js delete mode 100644 dist/node/esm/package.json delete mode 100644 dist/node/esm/runtime/aeskw.js delete mode 100644 dist/node/esm/runtime/asn1.js delete mode 100644 dist/node/esm/runtime/asn1_sequence_decoder.js delete mode 100644 dist/node/esm/runtime/asn1_sequence_encoder.js delete mode 100644 dist/node/esm/runtime/base64url.js delete mode 100644 dist/node/esm/runtime/cbc_tag.js delete mode 100644 dist/node/esm/runtime/check_cek_length.js delete mode 100644 dist/node/esm/runtime/check_modulus_length.js delete mode 100644 dist/node/esm/runtime/ciphers.js delete mode 100644 dist/node/esm/runtime/decrypt.js delete mode 100644 dist/node/esm/runtime/digest.js delete mode 100644 dist/node/esm/runtime/dsa_digest.js delete mode 100644 dist/node/esm/runtime/ecdhes.js delete mode 100644 dist/node/esm/runtime/encrypt.js delete mode 100644 dist/node/esm/runtime/env.js delete mode 100644 dist/node/esm/runtime/fetch_jwks.js delete mode 100644 dist/node/esm/runtime/flags.js delete mode 100644 dist/node/esm/runtime/generate.js delete mode 100644 dist/node/esm/runtime/get_named_curve.js delete mode 100644 dist/node/esm/runtime/get_sign_verify_key.js delete mode 100644 dist/node/esm/runtime/hmac_digest.js delete mode 100644 dist/node/esm/runtime/is_key_like.js delete mode 100644 dist/node/esm/runtime/is_key_object.js delete mode 100644 dist/node/esm/runtime/jwk_to_key.js delete mode 100644 dist/node/esm/runtime/key_to_jwk.js delete mode 100644 dist/node/esm/runtime/node_key.js delete mode 100644 dist/node/esm/runtime/pbes2kw.js delete mode 100644 dist/node/esm/runtime/random.js delete mode 100644 dist/node/esm/runtime/rsaes.js delete mode 100644 dist/node/esm/runtime/sign.js delete mode 100644 dist/node/esm/runtime/timing_safe_equal.js delete mode 100644 dist/node/esm/runtime/verify.js delete mode 100644 dist/node/esm/runtime/webcrypto.js delete mode 100644 dist/node/esm/runtime/zlib.js delete mode 100644 dist/node/esm/util/base64url.js delete mode 100644 dist/node/esm/util/decode_jwt.js delete mode 100644 dist/node/esm/util/decode_protected_header.js delete mode 100644 dist/node/esm/util/errors.js delete mode 100644 dist/types/index.d.ts delete mode 100644 dist/types/jwe/compact/decrypt.d.ts delete mode 100644 dist/types/jwe/compact/encrypt.d.ts delete mode 100644 dist/types/jwe/flattened/decrypt.d.ts delete mode 100644 dist/types/jwe/flattened/encrypt.d.ts delete mode 100644 dist/types/jwe/general/decrypt.d.ts delete mode 100644 dist/types/jwe/general/encrypt.d.ts delete mode 100644 dist/types/jwk/embedded.d.ts delete mode 100644 dist/types/jwk/thumbprint.d.ts delete mode 100644 dist/types/jwks/local.d.ts delete mode 100644 dist/types/jwks/remote.d.ts delete mode 100644 dist/types/jws/compact/sign.d.ts delete mode 100644 dist/types/jws/compact/verify.d.ts delete mode 100644 dist/types/jws/flattened/sign.d.ts delete mode 100644 dist/types/jws/flattened/verify.d.ts delete mode 100644 dist/types/jws/general/sign.d.ts delete mode 100644 dist/types/jws/general/verify.d.ts delete mode 100644 dist/types/jwt/decrypt.d.ts delete mode 100644 dist/types/jwt/encrypt.d.ts delete mode 100644 dist/types/jwt/produce.d.ts delete mode 100644 dist/types/jwt/sign.d.ts delete mode 100644 dist/types/jwt/unsecured.d.ts delete mode 100644 dist/types/jwt/verify.d.ts delete mode 100644 dist/types/key/export.d.ts delete mode 100644 dist/types/key/generate_key_pair.d.ts delete mode 100644 dist/types/key/generate_secret.d.ts delete mode 100644 dist/types/key/import.d.ts delete mode 100644 dist/types/types.d.ts delete mode 100644 dist/types/util/base64url.d.ts delete mode 100644 dist/types/util/decode_jwt.d.ts delete mode 100644 dist/types/util/decode_protected_header.d.ts delete mode 100644 dist/types/util/errors.d.ts diff --git a/dist/browser/index.bundle.js b/dist/browser/index.bundle.js deleted file mode 100644 index d083427e5b..0000000000 --- a/dist/browser/index.bundle.js +++ /dev/null @@ -1,3368 +0,0 @@ -var __defProp = Object.defineProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; - -// dist/browser/runtime/webcrypto.js -var webcrypto_default = crypto; -var isCryptoKey = (key) => key instanceof CryptoKey; - -// dist/browser/runtime/digest.js -var digest = async (algorithm, data) => { - const subtleDigest = `SHA-${algorithm.slice(-3)}`; - return new Uint8Array(await webcrypto_default.subtle.digest(subtleDigest, data)); -}; -var digest_default = digest; - -// dist/browser/lib/buffer_utils.js -var encoder = new TextEncoder(); -var decoder = new TextDecoder(); -var MAX_INT32 = 2 ** 32; -function concat(...buffers) { - const size = buffers.reduce((acc, { length }) => acc + length, 0); - const buf = new Uint8Array(size); - let i = 0; - buffers.forEach((buffer) => { - buf.set(buffer, i); - i += buffer.length; - }); - return buf; -} -function p2s(alg, p2sInput) { - return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); -} -function writeUInt32BE(buf, value, offset) { - if (value < 0 || value >= MAX_INT32) { - throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); - } - buf.set([value >>> 24, value >>> 16, value >>> 8, value & 255], offset); -} -function uint64be(value) { - const high = Math.floor(value / MAX_INT32); - const low = value % MAX_INT32; - const buf = new Uint8Array(8); - writeUInt32BE(buf, high, 0); - writeUInt32BE(buf, low, 4); - return buf; -} -function uint32be(value) { - const buf = new Uint8Array(4); - writeUInt32BE(buf, value); - return buf; -} -function lengthAndInput(input) { - return concat(uint32be(input.length), input); -} -async function concatKdf(secret, bits, value) { - const iterations = Math.ceil((bits >> 3) / 32); - const res = new Uint8Array(iterations * 32); - for (let iter = 0; iter < iterations; iter++) { - const buf = new Uint8Array(4 + secret.length + value.length); - buf.set(uint32be(iter + 1)); - buf.set(secret, 4); - buf.set(value, 4 + secret.length); - res.set(await digest_default("sha256", buf), iter * 32); - } - return res.slice(0, bits >> 3); -} - -// dist/browser/runtime/base64url.js -var encodeBase64 = (input) => { - let unencoded = input; - if (typeof unencoded === "string") { - unencoded = encoder.encode(unencoded); - } - const CHUNK_SIZE = 32768; - const arr = []; - for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { - arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))); - } - return btoa(arr.join("")); -}; -var encode = (input) => { - return encodeBase64(input).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); -}; -var decodeBase64 = (encoded) => { - const binary = atob(encoded); - const bytes = new Uint8Array(binary.length); - for (let i = 0; i < binary.length; i++) { - bytes[i] = binary.charCodeAt(i); - } - return bytes; -}; -var decode = (input) => { - let encoded = input; - if (encoded instanceof Uint8Array) { - encoded = decoder.decode(encoded); - } - encoded = encoded.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""); - try { - return decodeBase64(encoded); - } catch (_a) { - throw new TypeError("The input to be decoded is not correctly encoded."); - } -}; - -// dist/browser/util/errors.js -var errors_exports = {}; -__export(errors_exports, { - JOSEAlgNotAllowed: () => JOSEAlgNotAllowed, - JOSEError: () => JOSEError, - JOSENotSupported: () => JOSENotSupported, - JWEDecryptionFailed: () => JWEDecryptionFailed, - JWEInvalid: () => JWEInvalid, - JWKInvalid: () => JWKInvalid, - JWKSInvalid: () => JWKSInvalid, - JWKSMultipleMatchingKeys: () => JWKSMultipleMatchingKeys, - JWKSNoMatchingKey: () => JWKSNoMatchingKey, - JWKSTimeout: () => JWKSTimeout, - JWSInvalid: () => JWSInvalid, - JWSSignatureVerificationFailed: () => JWSSignatureVerificationFailed, - JWTClaimValidationFailed: () => JWTClaimValidationFailed, - JWTExpired: () => JWTExpired, - JWTInvalid: () => JWTInvalid -}); -var JOSEError = class extends Error { - static get code() { - return "ERR_JOSE_GENERIC"; - } - constructor(message2) { - var _a; - super(message2); - this.code = "ERR_JOSE_GENERIC"; - this.name = this.constructor.name; - (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); - } -}; -var JWTClaimValidationFailed = class extends JOSEError { - static get code() { - return "ERR_JWT_CLAIM_VALIDATION_FAILED"; - } - constructor(message2, claim = "unspecified", reason = "unspecified") { - super(message2); - this.code = "ERR_JWT_CLAIM_VALIDATION_FAILED"; - this.claim = claim; - this.reason = reason; - } -}; -var JWTExpired = class extends JOSEError { - static get code() { - return "ERR_JWT_EXPIRED"; - } - constructor(message2, claim = "unspecified", reason = "unspecified") { - super(message2); - this.code = "ERR_JWT_EXPIRED"; - this.claim = claim; - this.reason = reason; - } -}; -var JOSEAlgNotAllowed = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JOSE_ALG_NOT_ALLOWED"; - } - static get code() { - return "ERR_JOSE_ALG_NOT_ALLOWED"; - } -}; -var JOSENotSupported = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JOSE_NOT_SUPPORTED"; - } - static get code() { - return "ERR_JOSE_NOT_SUPPORTED"; - } -}; -var JWEDecryptionFailed = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWE_DECRYPTION_FAILED"; - this.message = "decryption operation failed"; - } - static get code() { - return "ERR_JWE_DECRYPTION_FAILED"; - } -}; -var JWEInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWE_INVALID"; - } - static get code() { - return "ERR_JWE_INVALID"; - } -}; -var JWSInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWS_INVALID"; - } - static get code() { - return "ERR_JWS_INVALID"; - } -}; -var JWTInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWT_INVALID"; - } - static get code() { - return "ERR_JWT_INVALID"; - } -}; -var JWKInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWK_INVALID"; - } - static get code() { - return "ERR_JWK_INVALID"; - } -}; -var JWKSInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_INVALID"; - } - static get code() { - return "ERR_JWKS_INVALID"; - } -}; -var JWKSNoMatchingKey = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_NO_MATCHING_KEY"; - this.message = "no applicable key found in the JSON Web Key Set"; - } - static get code() { - return "ERR_JWKS_NO_MATCHING_KEY"; - } -}; -var JWKSMultipleMatchingKeys = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; - this.message = "multiple matching keys found in the JSON Web Key Set"; - } - static get code() { - return "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; - } -}; -var JWKSTimeout = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_TIMEOUT"; - this.message = "request timed out"; - } - static get code() { - return "ERR_JWKS_TIMEOUT"; - } -}; -var JWSSignatureVerificationFailed = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; - this.message = "signature verification failed"; - } - static get code() { - return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; - } -}; - -// dist/browser/runtime/random.js -var random_default = webcrypto_default.getRandomValues.bind(webcrypto_default); - -// dist/browser/lib/iv.js -function bitLength(alg) { - switch (alg) { - case "A128GCM": - case "A128GCMKW": - case "A192GCM": - case "A192GCMKW": - case "A256GCM": - case "A256GCMKW": - return 96; - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - return 128; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -var iv_default = (alg) => random_default(new Uint8Array(bitLength(alg) >> 3)); - -// dist/browser/lib/check_iv_length.js -var checkIvLength = (enc, iv) => { - if (iv.length << 3 !== bitLength(enc)) { - throw new JWEInvalid("Invalid Initialization Vector length"); - } -}; -var check_iv_length_default = checkIvLength; - -// dist/browser/runtime/check_cek_length.js -var checkCekLength = (cek, expected) => { - const actual = cek.byteLength << 3; - if (actual !== expected) { - throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); - } -}; -var check_cek_length_default = checkCekLength; - -// dist/browser/runtime/timing_safe_equal.js -var timingSafeEqual = (a, b) => { - if (!(a instanceof Uint8Array)) { - throw new TypeError("First argument must be a buffer"); - } - if (!(b instanceof Uint8Array)) { - throw new TypeError("Second argument must be a buffer"); - } - if (a.length !== b.length) { - throw new TypeError("Input buffers must have the same length"); - } - const len = a.length; - let out = 0; - let i = -1; - while (++i < len) { - out |= a[i] ^ b[i]; - } - return out === 0; -}; -var timing_safe_equal_default = timingSafeEqual; - -// dist/browser/runtime/env.js -function isCloudflareWorkers() { - return typeof WebSocketPair !== "undefined" || typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime !== "undefined" && EdgeRuntime === "vercel"; -} - -// dist/browser/lib/crypto_key.js -function unusable(name, prop = "algorithm.name") { - return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); -} -function isAlgorithm(algorithm, name) { - return algorithm.name === name; -} -function getHashLength(hash) { - return parseInt(hash.name.slice(4), 10); -} -function getNamedCurve(alg) { - switch (alg) { - case "ES256": - return "P-256"; - case "ES384": - return "P-384"; - case "ES512": - return "P-521"; - default: - throw new Error("unreachable"); - } -} -function checkUsage(key, usages) { - if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { - let msg = "CryptoKey does not support this operation, its usages must include "; - if (usages.length > 2) { - const last = usages.pop(); - msg += `one of ${usages.join(", ")}, or ${last}.`; - } else if (usages.length === 2) { - msg += `one of ${usages[0]} or ${usages[1]}.`; - } else { - msg += `${usages[0]}.`; - } - throw new TypeError(msg); - } -} -function checkSigCryptoKey(key, alg, ...usages) { - switch (alg) { - case "HS256": - case "HS384": - case "HS512": { - if (!isAlgorithm(key.algorithm, "HMAC")) - throw unusable("HMAC"); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - case "RS256": - case "RS384": - case "RS512": { - if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5")) - throw unusable("RSASSA-PKCS1-v1_5"); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - case "PS256": - case "PS384": - case "PS512": { - if (!isAlgorithm(key.algorithm, "RSA-PSS")) - throw unusable("RSA-PSS"); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - case "EdDSA": { - if (key.algorithm.name !== "Ed25519" && key.algorithm.name !== "Ed448") { - if (isCloudflareWorkers()) { - if (isAlgorithm(key.algorithm, "NODE-ED25519")) - break; - throw unusable("Ed25519, Ed448, or NODE-ED25519"); - } - throw unusable("Ed25519 or Ed448"); - } - break; - } - case "ES256": - case "ES384": - case "ES512": { - if (!isAlgorithm(key.algorithm, "ECDSA")) - throw unusable("ECDSA"); - const expected = getNamedCurve(alg); - const actual = key.algorithm.namedCurve; - if (actual !== expected) - throw unusable(expected, "algorithm.namedCurve"); - break; - } - default: - throw new TypeError("CryptoKey does not support this operation"); - } - checkUsage(key, usages); -} -function checkEncCryptoKey(key, alg, ...usages) { - switch (alg) { - case "A128GCM": - case "A192GCM": - case "A256GCM": { - if (!isAlgorithm(key.algorithm, "AES-GCM")) - throw unusable("AES-GCM"); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, "algorithm.length"); - break; - } - case "A128KW": - case "A192KW": - case "A256KW": { - if (!isAlgorithm(key.algorithm, "AES-KW")) - throw unusable("AES-KW"); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, "algorithm.length"); - break; - } - case "ECDH": { - switch (key.algorithm.name) { - case "ECDH": - case "X25519": - case "X448": - break; - default: - throw unusable("ECDH, X25519, or X448"); - } - break; - } - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": - if (!isAlgorithm(key.algorithm, "PBKDF2")) - throw unusable("PBKDF2"); - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": { - if (!isAlgorithm(key.algorithm, "RSA-OAEP")) - throw unusable("RSA-OAEP"); - const expected = parseInt(alg.slice(9), 10) || 1; - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - default: - throw new TypeError("CryptoKey does not support this operation"); - } - checkUsage(key, usages); -} - -// dist/browser/lib/invalid_key_input.js -function message(msg, actual, ...types2) { - if (types2.length > 2) { - const last = types2.pop(); - msg += `one of type ${types2.join(", ")}, or ${last}.`; - } else if (types2.length === 2) { - msg += `one of type ${types2[0]} or ${types2[1]}.`; - } else { - msg += `of type ${types2[0]}.`; - } - if (actual == null) { - msg += ` Received ${actual}`; - } else if (typeof actual === "function" && actual.name) { - msg += ` Received function ${actual.name}`; - } else if (typeof actual === "object" && actual != null) { - if (actual.constructor && actual.constructor.name) { - msg += ` Received an instance of ${actual.constructor.name}`; - } - } - return msg; -} -var invalid_key_input_default = (actual, ...types2) => { - return message("Key must be ", actual, ...types2); -}; -function withAlg(alg, actual, ...types2) { - return message(`Key for the ${alg} algorithm must be `, actual, ...types2); -} - -// dist/browser/runtime/is_key_like.js -var is_key_like_default = (key) => { - return isCryptoKey(key); -}; -var types = ["CryptoKey"]; - -// dist/browser/runtime/decrypt.js -async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); - } - const keySize = parseInt(enc.slice(1, 4), 10); - const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["decrypt"]); - const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { - hash: `SHA-${keySize << 1}`, - name: "HMAC" - }, false, ["sign"]); - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); - const expectedTag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); - let macCheckPassed; - try { - macCheckPassed = timing_safe_equal_default(tag, expectedTag); - } catch (_a) { - } - if (!macCheckPassed) { - throw new JWEDecryptionFailed(); - } - let plaintext; - try { - plaintext = new Uint8Array(await webcrypto_default.subtle.decrypt({ iv, name: "AES-CBC" }, encKey, ciphertext)); - } catch (_b) { - } - if (!plaintext) { - throw new JWEDecryptionFailed(); - } - return plaintext; -} -async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { - let encKey; - if (cek instanceof Uint8Array) { - encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["decrypt"]); - } else { - checkEncCryptoKey(cek, enc, "decrypt"); - encKey = cek; - } - try { - return new Uint8Array(await webcrypto_default.subtle.decrypt({ - additionalData: aad, - iv, - name: "AES-GCM", - tagLength: 128 - }, encKey, concat(ciphertext, tag))); - } catch (_a) { - throw new JWEDecryptionFailed(); - } -} -var decrypt = async (enc, cek, ciphertext, iv, tag, aad) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); - } - check_iv_length_default(enc, iv); - switch (enc) { - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); - return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad); - case "A128GCM": - case "A192GCM": - case "A256GCM": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); - return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); - default: - throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); - } -}; -var decrypt_default = decrypt; - -// dist/browser/runtime/zlib.js -var inflate = async () => { - throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.'); -}; -var deflate = async () => { - throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.'); -}; - -// dist/browser/lib/is_disjoint.js -var isDisjoint = (...headers) => { - const sources = headers.filter(Boolean); - if (sources.length === 0 || sources.length === 1) { - return true; - } - let acc; - for (const header of sources) { - const parameters = Object.keys(header); - if (!acc || acc.size === 0) { - acc = new Set(parameters); - continue; - } - for (const parameter of parameters) { - if (acc.has(parameter)) { - return false; - } - acc.add(parameter); - } - } - return true; -}; -var is_disjoint_default = isDisjoint; - -// dist/browser/lib/is_object.js -function isObjectLike(value) { - return typeof value === "object" && value !== null; -} -function isObject(input) { - if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") { - return false; - } - if (Object.getPrototypeOf(input) === null) { - return true; - } - let proto = input; - while (Object.getPrototypeOf(proto) !== null) { - proto = Object.getPrototypeOf(proto); - } - return Object.getPrototypeOf(input) === proto; -} - -// dist/browser/runtime/bogus.js -var bogusWebCrypto = [ - { hash: "SHA-256", name: "HMAC" }, - true, - ["sign"] -]; -var bogus_default = bogusWebCrypto; - -// dist/browser/runtime/aeskw.js -function checkKeySize(key, alg) { - if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) { - throw new TypeError(`Invalid key size for alg: ${alg}`); - } -} -function getCryptoKey(key, alg, usage) { - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, usage); - return key; - } - if (key instanceof Uint8Array) { - return webcrypto_default.subtle.importKey("raw", key, "AES-KW", true, [usage]); - } - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); -} -var wrap = async (alg, key, cek) => { - const cryptoKey = await getCryptoKey(key, alg, "wrapKey"); - checkKeySize(cryptoKey, alg); - const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, cryptoKey, "AES-KW")); -}; -var unwrap = async (alg, key, encryptedKey) => { - const cryptoKey = await getCryptoKey(key, alg, "unwrapKey"); - checkKeySize(cryptoKey, alg); - const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, cryptoKey, "AES-KW", ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); -}; - -// dist/browser/runtime/ecdhes.js -async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { - if (!isCryptoKey(publicKey)) { - throw new TypeError(invalid_key_input_default(publicKey, ...types)); - } - checkEncCryptoKey(publicKey, "ECDH"); - if (!isCryptoKey(privateKey)) { - throw new TypeError(invalid_key_input_default(privateKey, ...types)); - } - checkEncCryptoKey(privateKey, "ECDH", "deriveBits"); - const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); - let length; - if (publicKey.algorithm.name === "X25519") { - length = 256; - } else if (publicKey.algorithm.name === "X448") { - length = 448; - } else { - length = Math.ceil(parseInt(publicKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3; - } - const sharedSecret = new Uint8Array(await webcrypto_default.subtle.deriveBits({ - name: publicKey.algorithm.name, - public: publicKey - }, privateKey, length)); - return concatKdf(sharedSecret, keyLength, value); -} -async function generateEpk(key) { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - return webcrypto_default.subtle.generateKey(key.algorithm, true, ["deriveBits"]); -} -function ecdhAllowed(key) { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - return ["P-256", "P-384", "P-521"].includes(key.algorithm.namedCurve) || key.algorithm.name === "X25519" || key.algorithm.name === "X448"; -} - -// dist/browser/lib/check_p2s.js -function checkP2s(p2s2) { - if (!(p2s2 instanceof Uint8Array) || p2s2.length < 8) { - throw new JWEInvalid("PBES2 Salt Input must be 8 or more octets"); - } -} - -// dist/browser/runtime/pbes2kw.js -function getCryptoKey2(key, alg) { - if (key instanceof Uint8Array) { - return webcrypto_default.subtle.importKey("raw", key, "PBKDF2", false, ["deriveBits"]); - } - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, "deriveBits", "deriveKey"); - return key; - } - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); -} -async function deriveKey2(p2s2, alg, p2c, key) { - checkP2s(p2s2); - const salt = p2s(alg, p2s2); - const keylen = parseInt(alg.slice(13, 16), 10); - const subtleAlg = { - hash: `SHA-${alg.slice(8, 11)}`, - iterations: p2c, - name: "PBKDF2", - salt - }; - const wrapAlg = { - length: keylen, - name: "AES-KW" - }; - const cryptoKey = await getCryptoKey2(key, alg); - if (cryptoKey.usages.includes("deriveBits")) { - return new Uint8Array(await webcrypto_default.subtle.deriveBits(subtleAlg, cryptoKey, keylen)); - } - if (cryptoKey.usages.includes("deriveKey")) { - return webcrypto_default.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ["wrapKey", "unwrapKey"]); - } - throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"'); -} -var encrypt = async (alg, key, cek, p2c = 2048, p2s2 = random_default(new Uint8Array(16))) => { - const derived = await deriveKey2(p2s2, alg, p2c, key); - const encryptedKey = await wrap(alg.slice(-6), derived, cek); - return { encryptedKey, p2c, p2s: encode(p2s2) }; -}; -var decrypt2 = async (alg, key, encryptedKey, p2c, p2s2) => { - const derived = await deriveKey2(p2s2, alg, p2c, key); - return unwrap(alg.slice(-6), derived, encryptedKey); -}; - -// dist/browser/runtime/subtle_rsaes.js -function subtleRsaEs(alg) { - switch (alg) { - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - return "RSA-OAEP"; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} - -// dist/browser/runtime/check_key_length.js -var check_key_length_default = (alg, key) => { - if (alg.startsWith("RS") || alg.startsWith("PS")) { - const { modulusLength } = key.algorithm; - if (typeof modulusLength !== "number" || modulusLength < 2048) { - throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); - } - } -}; - -// dist/browser/runtime/rsaes.js -var encrypt2 = async (alg, key, cek) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - checkEncCryptoKey(key, alg, "encrypt", "wrapKey"); - check_key_length_default(alg, key); - if (key.usages.includes("encrypt")) { - return new Uint8Array(await webcrypto_default.subtle.encrypt(subtleRsaEs(alg), key, cek)); - } - if (key.usages.includes("wrapKey")) { - const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, key, subtleRsaEs(alg))); - } - throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation'); -}; -var decrypt3 = async (alg, key, encryptedKey) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - checkEncCryptoKey(key, alg, "decrypt", "unwrapKey"); - check_key_length_default(alg, key); - if (key.usages.includes("decrypt")) { - return new Uint8Array(await webcrypto_default.subtle.decrypt(subtleRsaEs(alg), key, encryptedKey)); - } - if (key.usages.includes("unwrapKey")) { - const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, key, subtleRsaEs(alg), ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); - } - throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation'); -}; - -// dist/browser/lib/cek.js -function bitLength2(alg) { - switch (alg) { - case "A128GCM": - return 128; - case "A192GCM": - return 192; - case "A256GCM": - case "A128CBC-HS256": - return 256; - case "A192CBC-HS384": - return 384; - case "A256CBC-HS512": - return 512; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -var cek_default = (alg) => random_default(new Uint8Array(bitLength2(alg) >> 3)); - -// dist/browser/lib/format_pem.js -var format_pem_default = (b64, descriptor) => { - const newlined = (b64.match(/.{1,64}/g) || []).join("\n"); - return `-----BEGIN ${descriptor}----- -${newlined} ------END ${descriptor}-----`; -}; - -// dist/browser/runtime/asn1.js -var genericExport = async (keyType, keyFormat, key) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - if (!key.extractable) { - throw new TypeError("CryptoKey is not extractable"); - } - if (key.type !== keyType) { - throw new TypeError(`key is not a ${keyType} key`); - } - return format_pem_default(encodeBase64(new Uint8Array(await webcrypto_default.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`); -}; -var toSPKI = (key) => { - return genericExport("public", "spki", key); -}; -var toPKCS8 = (key) => { - return genericExport("private", "pkcs8", key); -}; -var findOid = (keyData, oid, from = 0) => { - if (from === 0) { - oid.unshift(oid.length); - oid.unshift(6); - } - let i = keyData.indexOf(oid[0], from); - if (i === -1) - return false; - const sub = keyData.subarray(i, i + oid.length); - if (sub.length !== oid.length) - return false; - return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1); -}; -var getNamedCurve2 = (keyData) => { - switch (true) { - case findOid(keyData, [42, 134, 72, 206, 61, 3, 1, 7]): - return "P-256"; - case findOid(keyData, [43, 129, 4, 0, 34]): - return "P-384"; - case findOid(keyData, [43, 129, 4, 0, 35]): - return "P-521"; - case findOid(keyData, [43, 101, 110]): - return "X25519"; - case findOid(keyData, [43, 101, 111]): - return "X448"; - case findOid(keyData, [43, 101, 112]): - return "Ed25519"; - case findOid(keyData, [43, 101, 113]): - return "Ed448"; - default: - throw new JOSENotSupported("Invalid or unsupported EC Key Curve or OKP Key Sub Type"); - } -}; -var genericImport = async (replace, keyFormat, pem, alg, options) => { - var _a, _b; - let algorithm; - let keyUsages; - const keyData = new Uint8Array(atob(pem.replace(replace, "")).split("").map((c) => c.charCodeAt(0))); - const isPublic = keyFormat === "spki"; - switch (alg) { - case "PS256": - case "PS384": - case "PS512": - algorithm = { name: "RSA-PSS", hash: `SHA-${alg.slice(-3)}` }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "RS256": - case "RS384": - case "RS512": - algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.slice(-3)}` }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - algorithm = { - name: "RSA-OAEP", - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}` - }; - keyUsages = isPublic ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"]; - break; - case "ES256": - algorithm = { name: "ECDSA", namedCurve: "P-256" }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "ES384": - algorithm = { name: "ECDSA", namedCurve: "P-384" }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "ES512": - algorithm = { name: "ECDSA", namedCurve: "P-521" }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - const namedCurve = getNamedCurve2(keyData); - algorithm = namedCurve.startsWith("P-") ? { name: "ECDH", namedCurve } : { name: namedCurve }; - keyUsages = isPublic ? [] : ["deriveBits"]; - break; - } - case "EdDSA": - algorithm = { name: getNamedCurve2(keyData) }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value'); - } - try { - return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); - } catch (err) { - if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { - algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages); - } - throw err; - } -}; -var fromPKCS8 = (pem, alg, options) => { - return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, "pkcs8", pem, alg, options); -}; -var fromSPKI = (pem, alg, options) => { - return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "spki", pem, alg, options); -}; -function getElement(seq) { - let result = []; - let next = 0; - while (next < seq.length) { - let nextPart = parseElement(seq.subarray(next)); - result.push(nextPart); - next += nextPart.byteLength; - } - return result; -} -function parseElement(bytes) { - let position = 0; - let tag = bytes[0] & 31; - position++; - if (tag === 31) { - tag = 0; - while (bytes[position] >= 128) { - tag = tag * 128 + bytes[position] - 128; - position++; - } - tag = tag * 128 + bytes[position] - 128; - position++; - } - let length = 0; - if (bytes[position] < 128) { - length = bytes[position]; - position++; - } else if (length === 128) { - length = 0; - while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { - if (length > bytes.byteLength) { - throw new TypeError("invalid indefinite form length"); - } - length++; - } - const byteLength2 = position + length + 2; - return { - byteLength: byteLength2, - contents: bytes.subarray(position, position + length), - raw: bytes.subarray(0, byteLength2) - }; - } else { - let numberOfDigits = bytes[position] & 127; - position++; - length = 0; - for (let i = 0; i < numberOfDigits; i++) { - length = length * 256 + bytes[position]; - position++; - } - } - const byteLength = position + length; - return { - byteLength, - contents: bytes.subarray(position, byteLength), - raw: bytes.subarray(0, byteLength) - }; -} -function spkiFromX509(buf) { - const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents); - return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 160 ? 6 : 5].raw); -} -function getSPKI(x509) { - const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ""); - const raw = decodeBase64(pem); - return format_pem_default(spkiFromX509(raw), "PUBLIC KEY"); -} -var fromX509 = (pem, alg, options) => { - let spki; - try { - spki = getSPKI(pem); - } catch (cause) { - throw new TypeError("failed to parse the X.509 certificate", { cause }); - } - return fromSPKI(spki, alg, options); -}; - -// dist/browser/runtime/jwk_to_key.js -function subtleMapping(jwk) { - let algorithm; - let keyUsages; - switch (jwk.kty) { - case "oct": { - switch (jwk.alg) { - case "HS256": - case "HS384": - case "HS512": - algorithm = { name: "HMAC", hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = ["sign", "verify"]; - break; - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`); - case "A128GCM": - case "A192GCM": - case "A256GCM": - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": - algorithm = { name: "AES-GCM" }; - keyUsages = ["encrypt", "decrypt"]; - break; - case "A128KW": - case "A192KW": - case "A256KW": - algorithm = { name: "AES-KW" }; - keyUsages = ["wrapKey", "unwrapKey"]; - break; - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": - algorithm = { name: "PBKDF2" }; - keyUsages = ["deriveBits"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case "RSA": { - switch (jwk.alg) { - case "PS256": - case "PS384": - case "PS512": - algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "RS256": - case "RS384": - case "RS512": - algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - algorithm = { - name: "RSA-OAEP", - hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}` - }; - keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case "EC": { - switch (jwk.alg) { - case "ES256": - algorithm = { name: "ECDSA", namedCurve: "P-256" }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ES384": - algorithm = { name: "ECDSA", namedCurve: "P-384" }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ES512": - algorithm = { name: "ECDSA", namedCurve: "P-521" }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": - algorithm = { name: "ECDH", namedCurve: jwk.crv }; - keyUsages = jwk.d ? ["deriveBits"] : []; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case "OKP": { - switch (jwk.alg) { - case "EdDSA": - algorithm = { name: jwk.crv }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": - algorithm = { name: jwk.crv }; - keyUsages = jwk.d ? ["deriveBits"] : []; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); - } - return { algorithm, keyUsages }; -} -var parse = async (jwk) => { - var _a, _b; - if (!jwk.alg) { - throw new TypeError('"alg" argument is required when "jwk.alg" is not present'); - } - const { algorithm, keyUsages } = subtleMapping(jwk); - const rest = [ - algorithm, - (_a = jwk.ext) !== null && _a !== void 0 ? _a : false, - (_b = jwk.key_ops) !== null && _b !== void 0 ? _b : keyUsages - ]; - if (algorithm.name === "PBKDF2") { - return webcrypto_default.subtle.importKey("raw", decode(jwk.k), ...rest); - } - const keyData = { ...jwk }; - delete keyData.alg; - delete keyData.use; - try { - return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); - } catch (err) { - if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { - rest[0] = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); - } - throw err; - } -}; -var jwk_to_key_default = parse; - -// dist/browser/key/import.js -async function importSPKI(spki, alg, options) { - if (typeof spki !== "string" || spki.indexOf("-----BEGIN PUBLIC KEY-----") !== 0) { - throw new TypeError('"spki" must be SPKI formatted string'); - } - return fromSPKI(spki, alg, options); -} -async function importX509(x509, alg, options) { - if (typeof x509 !== "string" || x509.indexOf("-----BEGIN CERTIFICATE-----") !== 0) { - throw new TypeError('"x509" must be X.509 formatted string'); - } - return fromX509(x509, alg, options); -} -async function importPKCS8(pkcs8, alg, options) { - if (typeof pkcs8 !== "string" || pkcs8.indexOf("-----BEGIN PRIVATE KEY-----") !== 0) { - throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); - } - return fromPKCS8(pkcs8, alg, options); -} -async function importJWK(jwk, alg, octAsKeyObject) { - var _a; - if (!isObject(jwk)) { - throw new TypeError("JWK must be an object"); - } - alg || (alg = jwk.alg); - switch (jwk.kty) { - case "oct": - if (typeof jwk.k !== "string" || !jwk.k) { - throw new TypeError('missing "k" (Key Value) Parameter value'); - } - octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : octAsKeyObject = jwk.ext !== true; - if (octAsKeyObject) { - return jwk_to_key_default({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); - } - return decode(jwk.k); - case "RSA": - if (jwk.oth !== void 0) { - throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); - } - case "EC": - case "OKP": - return jwk_to_key_default({ ...jwk, alg }); - default: - throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); - } -} - -// dist/browser/lib/check_key_type.js -var symmetricTypeCheck = (alg, key) => { - if (key instanceof Uint8Array) - return; - if (!is_key_like_default(key)) { - throw new TypeError(withAlg(alg, key, ...types, "Uint8Array")); - } - if (key.type !== "secret") { - throw new TypeError(`${types.join(" or ")} instances for symmetric algorithms must be of type "secret"`); - } -}; -var asymmetricTypeCheck = (alg, key, usage) => { - if (!is_key_like_default(key)) { - throw new TypeError(withAlg(alg, key, ...types)); - } - if (key.type === "secret") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`); - } - if (usage === "sign" && key.type === "public") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`); - } - if (usage === "decrypt" && key.type === "public") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`); - } - if (key.algorithm && usage === "verify" && key.type === "private") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`); - } - if (key.algorithm && usage === "encrypt" && key.type === "private") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`); - } -}; -var checkKeyType = (alg, key, usage) => { - const symmetric = alg.startsWith("HS") || alg === "dir" || alg.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(alg); - if (symmetric) { - symmetricTypeCheck(alg, key); - } else { - asymmetricTypeCheck(alg, key, usage); - } -}; -var check_key_type_default = checkKeyType; - -// dist/browser/runtime/encrypt.js -async function cbcEncrypt(enc, plaintext, cek, iv, aad) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); - } - const keySize = parseInt(enc.slice(1, 4), 10); - const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["encrypt"]); - const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { - hash: `SHA-${keySize << 1}`, - name: "HMAC" - }, false, ["sign"]); - const ciphertext = new Uint8Array(await webcrypto_default.subtle.encrypt({ - iv, - name: "AES-CBC" - }, encKey, plaintext)); - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); - const tag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); - return { ciphertext, tag }; -} -async function gcmEncrypt(enc, plaintext, cek, iv, aad) { - let encKey; - if (cek instanceof Uint8Array) { - encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["encrypt"]); - } else { - checkEncCryptoKey(cek, enc, "encrypt"); - encKey = cek; - } - const encrypted = new Uint8Array(await webcrypto_default.subtle.encrypt({ - additionalData: aad, - iv, - name: "AES-GCM", - tagLength: 128 - }, encKey, plaintext)); - const tag = encrypted.slice(-16); - const ciphertext = encrypted.slice(0, -16); - return { ciphertext, tag }; -} -var encrypt3 = async (enc, plaintext, cek, iv, aad) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); - } - check_iv_length_default(enc, iv); - switch (enc) { - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); - return cbcEncrypt(enc, plaintext, cek, iv, aad); - case "A128GCM": - case "A192GCM": - case "A256GCM": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); - return gcmEncrypt(enc, plaintext, cek, iv, aad); - default: - throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); - } -}; -var encrypt_default = encrypt3; - -// dist/browser/lib/aesgcmkw.js -async function wrap2(alg, key, cek, iv) { - const jweAlgorithm = alg.slice(0, 7); - iv || (iv = iv_default(jweAlgorithm)); - const { ciphertext: encryptedKey, tag } = await encrypt_default(jweAlgorithm, cek, key, iv, new Uint8Array(0)); - return { encryptedKey, iv: encode(iv), tag: encode(tag) }; -} -async function unwrap2(alg, key, encryptedKey, iv, tag) { - const jweAlgorithm = alg.slice(0, 7); - return decrypt_default(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); -} - -// dist/browser/lib/decrypt_key_management.js -async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { - check_key_type_default(alg, key, "decrypt"); - switch (alg) { - case "dir": { - if (encryptedKey !== void 0) - throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); - return key; - } - case "ECDH-ES": - if (encryptedKey !== void 0) - throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - if (!isObject(joseHeader.epk)) - throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); - if (!ecdhAllowed(key)) - throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); - const epk = await importJWK(joseHeader.epk, alg); - let partyUInfo; - let partyVInfo; - if (joseHeader.apu !== void 0) { - if (typeof joseHeader.apu !== "string") - throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); - partyUInfo = decode(joseHeader.apu); - } - if (joseHeader.apv !== void 0) { - if (typeof joseHeader.apv !== "string") - throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); - partyVInfo = decode(joseHeader.apv); - } - const sharedSecret = await deriveKey(epk, key, alg === "ECDH-ES" ? joseHeader.enc : alg, alg === "ECDH-ES" ? bitLength2(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); - if (alg === "ECDH-ES") - return sharedSecret; - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - return unwrap(alg.slice(-6), sharedSecret, encryptedKey); - } - case "RSA1_5": - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - return decrypt3(alg, key, encryptedKey); - } - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - if (typeof joseHeader.p2c !== "number") - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); - const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 1e4; - if (joseHeader.p2c > p2cLimit) - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); - if (typeof joseHeader.p2s !== "string") - throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); - return decrypt2(alg, key, encryptedKey, joseHeader.p2c, decode(joseHeader.p2s)); - } - case "A128KW": - case "A192KW": - case "A256KW": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - return unwrap(alg, key, encryptedKey); - } - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - if (typeof joseHeader.iv !== "string") - throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); - if (typeof joseHeader.tag !== "string") - throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); - const iv = decode(joseHeader.iv); - const tag = decode(joseHeader.tag); - return unwrap2(alg, key, encryptedKey, iv, tag); - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } -} -var decrypt_key_management_default = decryptKeyManagement; - -// dist/browser/lib/validate_crit.js -function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { - if (joseHeader.crit !== void 0 && protectedHeader.crit === void 0) { - throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); - } - if (!protectedHeader || protectedHeader.crit === void 0) { - return /* @__PURE__ */ new Set(); - } - if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) { - throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); - } - let recognized; - if (recognizedOption !== void 0) { - recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); - } else { - recognized = recognizedDefault; - } - for (const parameter of protectedHeader.crit) { - if (!recognized.has(parameter)) { - throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); - } - if (joseHeader[parameter] === void 0) { - throw new Err(`Extension Header Parameter "${parameter}" is missing`); - } else if (recognized.get(parameter) && protectedHeader[parameter] === void 0) { - throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); - } - } - return new Set(protectedHeader.crit); -} -var validate_crit_default = validateCrit; - -// dist/browser/lib/validate_algorithms.js -var validateAlgorithms = (option, algorithms) => { - if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) { - throw new TypeError(`"${option}" option must be an array of strings`); - } - if (!algorithms) { - return void 0; - } - return new Set(algorithms); -}; -var validate_algorithms_default = validateAlgorithms; - -// dist/browser/jwe/flattened/decrypt.js -async function flattenedDecrypt(jwe, key, options) { - var _a; - if (!isObject(jwe)) { - throw new JWEInvalid("Flattened JWE must be an object"); - } - if (jwe.protected === void 0 && jwe.header === void 0 && jwe.unprotected === void 0) { - throw new JWEInvalid("JOSE Header missing"); - } - if (typeof jwe.iv !== "string") { - throw new JWEInvalid("JWE Initialization Vector missing or incorrect type"); - } - if (typeof jwe.ciphertext !== "string") { - throw new JWEInvalid("JWE Ciphertext missing or incorrect type"); - } - if (typeof jwe.tag !== "string") { - throw new JWEInvalid("JWE Authentication Tag missing or incorrect type"); - } - if (jwe.protected !== void 0 && typeof jwe.protected !== "string") { - throw new JWEInvalid("JWE Protected Header incorrect type"); - } - if (jwe.encrypted_key !== void 0 && typeof jwe.encrypted_key !== "string") { - throw new JWEInvalid("JWE Encrypted Key incorrect type"); - } - if (jwe.aad !== void 0 && typeof jwe.aad !== "string") { - throw new JWEInvalid("JWE AAD incorrect type"); - } - if (jwe.header !== void 0 && !isObject(jwe.header)) { - throw new JWEInvalid("JWE Shared Unprotected Header incorrect type"); - } - if (jwe.unprotected !== void 0 && !isObject(jwe.unprotected)) { - throw new JWEInvalid("JWE Per-Recipient Unprotected Header incorrect type"); - } - let parsedProt; - if (jwe.protected) { - try { - const protectedHeader2 = decode(jwe.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader2)); - } catch (_b) { - throw new JWEInvalid("JWE Protected Header is invalid"); - } - } - if (!is_disjoint_default(parsedProt, jwe.header, jwe.unprotected)) { - throw new JWEInvalid("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint"); - } - const joseHeader = { - ...parsedProt, - ...jwe.header, - ...jwe.unprotected - }; - validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - if (joseHeader.zip !== void 0) { - if (!parsedProt || !parsedProt.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== "DEF") { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWEInvalid("missing JWE Algorithm (alg) in JWE Header"); - } - if (typeof enc !== "string" || !enc) { - throw new JWEInvalid("missing JWE Encryption Algorithm (enc) in JWE Header"); - } - const keyManagementAlgorithms = options && validate_algorithms_default("keyManagementAlgorithms", options.keyManagementAlgorithms); - const contentEncryptionAlgorithms = options && validate_algorithms_default("contentEncryptionAlgorithms", options.contentEncryptionAlgorithms); - if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { - throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); - } - let encryptedKey; - if (jwe.encrypted_key !== void 0) { - encryptedKey = decode(jwe.encrypted_key); - } - let resolvedKey = false; - if (typeof key === "function") { - key = await key(parsedProt, jwe); - resolvedKey = true; - } - let cek; - try { - cek = await decrypt_key_management_default(alg, key, encryptedKey, joseHeader, options); - } catch (err) { - if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { - throw err; - } - cek = cek_default(enc); - } - const iv = decode(jwe.iv); - const tag = decode(jwe.tag); - const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ""); - let additionalData; - if (jwe.aad !== void 0) { - additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(jwe.aad)); - } else { - additionalData = protectedHeader; - } - let plaintext = await decrypt_default(enc, cek, decode(jwe.ciphertext), iv, tag, additionalData); - if (joseHeader.zip === "DEF") { - plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); - } - const result = { plaintext }; - if (jwe.protected !== void 0) { - result.protectedHeader = parsedProt; - } - if (jwe.aad !== void 0) { - result.additionalAuthenticatedData = decode(jwe.aad); - } - if (jwe.unprotected !== void 0) { - result.sharedUnprotectedHeader = jwe.unprotected; - } - if (jwe.header !== void 0) { - result.unprotectedHeader = jwe.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} - -// dist/browser/jwe/compact/decrypt.js -async function compactDecrypt(jwe, key, options) { - if (jwe instanceof Uint8Array) { - jwe = decoder.decode(jwe); - } - if (typeof jwe !== "string") { - throw new JWEInvalid("Compact JWE must be a string or Uint8Array"); - } - const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length } = jwe.split("."); - if (length !== 5) { - throw new JWEInvalid("Invalid Compact JWE"); - } - const decrypted = await flattenedDecrypt({ - ciphertext, - iv: iv || void 0, - protected: protectedHeader || void 0, - tag: tag || void 0, - encrypted_key: encryptedKey || void 0 - }, key, options); - const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; - if (typeof key === "function") { - return { ...result, key: decrypted.key }; - } - return result; -} - -// dist/browser/jwe/general/decrypt.js -async function generalDecrypt(jwe, key, options) { - if (!isObject(jwe)) { - throw new JWEInvalid("General JWE must be an object"); - } - if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { - throw new JWEInvalid("JWE Recipients missing or incorrect type"); - } - if (!jwe.recipients.length) { - throw new JWEInvalid("JWE Recipients has no members"); - } - for (const recipient of jwe.recipients) { - try { - return await flattenedDecrypt({ - aad: jwe.aad, - ciphertext: jwe.ciphertext, - encrypted_key: recipient.encrypted_key, - header: recipient.header, - iv: jwe.iv, - protected: jwe.protected, - tag: jwe.tag, - unprotected: jwe.unprotected - }, key, options); - } catch (_a) { - } - } - throw new JWEDecryptionFailed(); -} - -// dist/browser/runtime/key_to_jwk.js -var keyToJWK = async (key) => { - if (key instanceof Uint8Array) { - return { - kty: "oct", - k: encode(key) - }; - } - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); - } - if (!key.extractable) { - throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK"); - } - const { ext, key_ops, alg, use, ...jwk } = await webcrypto_default.subtle.exportKey("jwk", key); - return jwk; -}; -var key_to_jwk_default = keyToJWK; - -// dist/browser/key/export.js -async function exportSPKI(key) { - return toSPKI(key); -} -async function exportPKCS8(key) { - return toPKCS8(key); -} -async function exportJWK(key) { - return key_to_jwk_default(key); -} - -// dist/browser/lib/encrypt_key_management.js -async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { - let encryptedKey; - let parameters; - let cek; - check_key_type_default(alg, key, "encrypt"); - switch (alg) { - case "dir": { - cek = key; - break; - } - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - if (!ecdhAllowed(key)) { - throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); - } - const { apu, apv } = providedParameters; - let { epk: ephemeralKey } = providedParameters; - ephemeralKey || (ephemeralKey = (await generateEpk(key)).privateKey); - const { x, y, crv, kty } = await exportJWK(ephemeralKey); - const sharedSecret = await deriveKey(key, ephemeralKey, alg === "ECDH-ES" ? enc : alg, alg === "ECDH-ES" ? bitLength2(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); - parameters = { epk: { x, crv, kty } }; - if (kty === "EC") - parameters.epk.y = y; - if (apu) - parameters.apu = encode(apu); - if (apv) - parameters.apv = encode(apv); - if (alg === "ECDH-ES") { - cek = sharedSecret; - break; - } - cek = providedCek || cek_default(enc); - const kwAlg = alg.slice(-6); - encryptedKey = await wrap(kwAlg, sharedSecret, cek); - break; - } - case "RSA1_5": - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": { - cek = providedCek || cek_default(enc); - encryptedKey = await encrypt2(alg, key, cek); - break; - } - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": { - cek = providedCek || cek_default(enc); - const { p2c, p2s: p2s2 } = providedParameters; - ({ encryptedKey, ...parameters } = await encrypt(alg, key, cek, p2c, p2s2)); - break; - } - case "A128KW": - case "A192KW": - case "A256KW": { - cek = providedCek || cek_default(enc); - encryptedKey = await wrap(alg, key, cek); - break; - } - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": { - cek = providedCek || cek_default(enc); - const { iv } = providedParameters; - ({ encryptedKey, ...parameters } = await wrap2(alg, key, cek, iv)); - break; - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } - return { cek, encryptedKey, parameters }; -} -var encrypt_key_management_default = encryptKeyManagement; - -// dist/browser/jwe/flattened/encrypt.js -var unprotected = Symbol(); -var FlattenedEncrypt = class { - constructor(plaintext) { - if (!(plaintext instanceof Uint8Array)) { - throw new TypeError("plaintext must be an instance of Uint8Array"); - } - this._plaintext = plaintext; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError("setKeyManagementParameters can only be called once"); - } - this._keyManagementParameters = parameters; - return this; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._sharedUnprotectedHeader) { - throw new TypeError("setSharedUnprotectedHeader can only be called once"); - } - this._sharedUnprotectedHeader = sharedUnprotectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError("setContentEncryptionKey can only be called once"); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError("setInitializationVector can only be called once"); - } - this._iv = iv; - return this; - } - async encrypt(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { - throw new JWEInvalid("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()"); - } - if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { - throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...this._sharedUnprotectedHeader - }; - validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== void 0) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== "DEF") { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (typeof enc !== "string" || !enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - let encryptedKey; - if (alg === "dir") { - if (this._cek) { - throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption"); - } - } else if (alg === "ECDH-ES") { - if (this._cek) { - throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement"); - } - } - let cek; - { - let parameters; - ({ cek, encryptedKey, parameters } = await encrypt_key_management_default(alg, enc, key, this._cek, this._keyManagementParameters)); - if (parameters) { - if (options && unprotected in options) { - if (!this._unprotectedHeader) { - this.setUnprotectedHeader(parameters); - } else { - this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; - } - } else { - if (!this._protectedHeader) { - this.setProtectedHeader(parameters); - } else { - this._protectedHeader = { ...this._protectedHeader, ...parameters }; - } - } - } - } - this._iv || (this._iv = iv_default(enc)); - let additionalData; - let protectedHeader; - let aadMember; - if (this._protectedHeader) { - protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); - } else { - protectedHeader = encoder.encode(""); - } - if (this._aad) { - aadMember = encode(this._aad); - additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(aadMember)); - } else { - additionalData = protectedHeader; - } - let ciphertext; - let tag; - if (joseHeader.zip === "DEF") { - const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); - ({ ciphertext, tag } = await encrypt_default(enc, deflated, cek, this._iv, additionalData)); - } else { - ; - ({ ciphertext, tag } = await encrypt_default(enc, this._plaintext, cek, this._iv, additionalData)); - } - const jwe = { - ciphertext: encode(ciphertext), - iv: encode(this._iv), - tag: encode(tag) - }; - if (encryptedKey) { - jwe.encrypted_key = encode(encryptedKey); - } - if (aadMember) { - jwe.aad = aadMember; - } - if (this._protectedHeader) { - jwe.protected = decoder.decode(protectedHeader); - } - if (this._sharedUnprotectedHeader) { - jwe.unprotected = this._sharedUnprotectedHeader; - } - if (this._unprotectedHeader) { - jwe.header = this._unprotectedHeader; - } - return jwe; - } -}; - -// dist/browser/jwe/general/encrypt.js -var IndividualRecipient = class { - constructor(enc, key, options) { - this.parent = enc; - this.key = key; - this.options = options; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addRecipient(...args) { - return this.parent.addRecipient(...args); - } - encrypt(...args) { - return this.parent.encrypt(...args); - } - done() { - return this.parent; - } -}; -var GeneralEncrypt = class { - constructor(plaintext) { - this._recipients = []; - this._plaintext = plaintext; - } - addRecipient(key, options) { - const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); - this._recipients.push(recipient); - return recipient; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError("setSharedUnprotectedHeader can only be called once"); - } - this._unprotectedHeader = sharedUnprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - async encrypt(options) { - var _a, _b, _c; - if (!this._recipients.length) { - throw new JWEInvalid("at least one recipient must be added"); - } - options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; - if (this._recipients.length === 1) { - const [recipient] = this._recipients; - const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).encrypt(recipient.key, { ...recipient.options, ...options }); - let jwe2 = { - ciphertext: flattened.ciphertext, - iv: flattened.iv, - recipients: [{}], - tag: flattened.tag - }; - if (flattened.aad) - jwe2.aad = flattened.aad; - if (flattened.protected) - jwe2.protected = flattened.protected; - if (flattened.unprotected) - jwe2.unprotected = flattened.unprotected; - if (flattened.encrypted_key) - jwe2.recipients[0].encrypted_key = flattened.encrypted_key; - if (flattened.header) - jwe2.recipients[0].header = flattened.header; - return jwe2; - } - let enc; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { - throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader - }; - const { alg } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (alg === "dir" || alg === "ECDH-ES") { - throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); - } - if (typeof joseHeader.enc !== "string" || !joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - if (!enc) { - enc = joseHeader.enc; - } else if (enc !== joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); - } - validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), recipient.options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== void 0) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - } - } - const cek = cek_default(enc); - let jwe = { - ciphertext: "", - iv: "", - recipients: [], - tag: "" - }; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - const target = {}; - jwe.recipients.push(target); - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader - }; - const p2c = joseHeader.alg.startsWith("PBES2") ? 2048 + i : void 0; - if (i === 0) { - const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setContentEncryptionKey(cek).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).setKeyManagementParameters({ p2c }).encrypt(recipient.key, { - ...recipient.options, - ...options, - [unprotected]: true - }); - jwe.ciphertext = flattened.ciphertext; - jwe.iv = flattened.iv; - jwe.tag = flattened.tag; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - target.encrypted_key = flattened.encrypted_key; - if (flattened.header) - target.header = flattened.header; - continue; - } - const { encryptedKey, parameters } = await encrypt_key_management_default(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); - target.encrypted_key = encode(encryptedKey); - if (recipient.unprotectedHeader || parameters) - target.header = { ...recipient.unprotectedHeader, ...parameters }; - } - return jwe; - } -}; - -// dist/browser/runtime/subtle_dsa.js -function subtleDsa(alg, algorithm) { - const hash = `SHA-${alg.slice(-3)}`; - switch (alg) { - case "HS256": - case "HS384": - case "HS512": - return { hash, name: "HMAC" }; - case "PS256": - case "PS384": - case "PS512": - return { hash, name: "RSA-PSS", saltLength: alg.slice(-3) >> 3 }; - case "RS256": - case "RS384": - case "RS512": - return { hash, name: "RSASSA-PKCS1-v1_5" }; - case "ES256": - case "ES384": - case "ES512": - return { hash, name: "ECDSA", namedCurve: algorithm.namedCurve }; - case "EdDSA": - if (isCloudflareWorkers() && algorithm.name === "NODE-ED25519") { - return { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - } - return { name: algorithm.name }; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} - -// dist/browser/runtime/get_sign_verify_key.js -function getCryptoKey3(alg, key, usage) { - if (isCryptoKey(key)) { - checkSigCryptoKey(key, alg, usage); - return key; - } - if (key instanceof Uint8Array) { - if (!alg.startsWith("HS")) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - return webcrypto_default.subtle.importKey("raw", key, { hash: `SHA-${alg.slice(-3)}`, name: "HMAC" }, false, [usage]); - } - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); -} - -// dist/browser/runtime/verify.js -var verify = async (alg, key, signature, data) => { - const cryptoKey = await getCryptoKey3(alg, key, "verify"); - check_key_length_default(alg, cryptoKey); - const algorithm = subtleDsa(alg, cryptoKey.algorithm); - try { - return await webcrypto_default.subtle.verify(algorithm, cryptoKey, signature, data); - } catch (_a) { - return false; - } -}; -var verify_default = verify; - -// dist/browser/jws/flattened/verify.js -async function flattenedVerify(jws, key, options) { - var _a; - if (!isObject(jws)) { - throw new JWSInvalid("Flattened JWS must be an object"); - } - if (jws.protected === void 0 && jws.header === void 0) { - throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); - } - if (jws.protected !== void 0 && typeof jws.protected !== "string") { - throw new JWSInvalid("JWS Protected Header incorrect type"); - } - if (jws.payload === void 0) { - throw new JWSInvalid("JWS Payload missing"); - } - if (typeof jws.signature !== "string") { - throw new JWSInvalid("JWS Signature missing or incorrect type"); - } - if (jws.header !== void 0 && !isObject(jws.header)) { - throw new JWSInvalid("JWS Unprotected Header incorrect type"); - } - let parsedProt = {}; - if (jws.protected) { - try { - const protectedHeader = decode(jws.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader)); - } catch (_b) { - throw new JWSInvalid("JWS Protected Header is invalid"); - } - } - if (!is_disjoint_default(parsedProt, jws.header)) { - throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); - } - const joseHeader = { - ...parsedProt, - ...jws.header - }; - const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - let b64 = true; - if (extensions.has("b64")) { - b64 = parsedProt.b64; - if (typeof b64 !== "boolean") { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - const algorithms = options && validate_algorithms_default("algorithms", options.algorithms); - if (algorithms && !algorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (b64) { - if (typeof jws.payload !== "string") { - throw new JWSInvalid("JWS Payload must be a string"); - } - } else if (typeof jws.payload !== "string" && !(jws.payload instanceof Uint8Array)) { - throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance"); - } - let resolvedKey = false; - if (typeof key === "function") { - key = await key(parsedProt, jws); - resolvedKey = true; - } - check_key_type_default(alg, key, "verify"); - const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ""), encoder.encode("."), typeof jws.payload === "string" ? encoder.encode(jws.payload) : jws.payload); - const signature = decode(jws.signature); - const verified = await verify_default(alg, key, signature, data); - if (!verified) { - throw new JWSSignatureVerificationFailed(); - } - let payload; - if (b64) { - payload = decode(jws.payload); - } else if (typeof jws.payload === "string") { - payload = encoder.encode(jws.payload); - } else { - payload = jws.payload; - } - const result = { payload }; - if (jws.protected !== void 0) { - result.protectedHeader = parsedProt; - } - if (jws.header !== void 0) { - result.unprotectedHeader = jws.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} - -// dist/browser/jws/compact/verify.js -async function compactVerify(jws, key, options) { - if (jws instanceof Uint8Array) { - jws = decoder.decode(jws); - } - if (typeof jws !== "string") { - throw new JWSInvalid("Compact JWS must be a string or Uint8Array"); - } - const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split("."); - if (length !== 3) { - throw new JWSInvalid("Invalid Compact JWS"); - } - const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); - const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; - if (typeof key === "function") { - return { ...result, key: verified.key }; - } - return result; -} - -// dist/browser/jws/general/verify.js -async function generalVerify(jws, key, options) { - if (!isObject(jws)) { - throw new JWSInvalid("General JWS must be an object"); - } - if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { - throw new JWSInvalid("JWS Signatures missing or incorrect type"); - } - for (const signature of jws.signatures) { - try { - return await flattenedVerify({ - header: signature.header, - payload: jws.payload, - protected: signature.protected, - signature: signature.signature - }, key, options); - } catch (_a) { - } - } - throw new JWSSignatureVerificationFailed(); -} - -// dist/browser/lib/epoch.js -var epoch_default = (date) => Math.floor(date.getTime() / 1e3); - -// dist/browser/lib/secs.js -var minute = 60; -var hour = minute * 60; -var day = hour * 24; -var week = day * 7; -var year = day * 365.25; -var REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; -var secs_default = (str) => { - const matched = REGEX.exec(str); - if (!matched) { - throw new TypeError("Invalid time period format"); - } - const value = parseFloat(matched[1]); - const unit = matched[2].toLowerCase(); - switch (unit) { - case "sec": - case "secs": - case "second": - case "seconds": - case "s": - return Math.round(value); - case "minute": - case "minutes": - case "min": - case "mins": - case "m": - return Math.round(value * minute); - case "hour": - case "hours": - case "hr": - case "hrs": - case "h": - return Math.round(value * hour); - case "day": - case "days": - case "d": - return Math.round(value * day); - case "week": - case "weeks": - case "w": - return Math.round(value * week); - default: - return Math.round(value * year); - } -}; - -// dist/browser/lib/jwt_claims_set.js -var normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ""); -var checkAudiencePresence = (audPayload, audOption) => { - if (typeof audPayload === "string") { - return audOption.includes(audPayload); - } - if (Array.isArray(audPayload)) { - return audOption.some(Set.prototype.has.bind(new Set(audPayload))); - } - return false; -}; -var jwt_claims_set_default = (protectedHeader, encodedPayload, options = {}) => { - const { typ } = options; - if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { - throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', "typ", "check_failed"); - } - let payload; - try { - payload = JSON.parse(decoder.decode(encodedPayload)); - } catch (_a) { - } - if (!isObject(payload)) { - throw new JWTInvalid("JWT Claims Set must be a top-level JSON object"); - } - const { issuer } = options; - if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { - throw new JWTClaimValidationFailed('unexpected "iss" claim value', "iss", "check_failed"); - } - const { subject } = options; - if (subject && payload.sub !== subject) { - throw new JWTClaimValidationFailed('unexpected "sub" claim value', "sub", "check_failed"); - } - const { audience } = options; - if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) { - throw new JWTClaimValidationFailed('unexpected "aud" claim value', "aud", "check_failed"); - } - let tolerance; - switch (typeof options.clockTolerance) { - case "string": - tolerance = secs_default(options.clockTolerance); - break; - case "number": - tolerance = options.clockTolerance; - break; - case "undefined": - tolerance = 0; - break; - default: - throw new TypeError("Invalid clockTolerance option type"); - } - const { currentDate } = options; - const now = epoch_default(currentDate || /* @__PURE__ */ new Date()); - if ((payload.iat !== void 0 || options.maxTokenAge) && typeof payload.iat !== "number") { - throw new JWTClaimValidationFailed('"iat" claim must be a number', "iat", "invalid"); - } - if (payload.nbf !== void 0) { - if (typeof payload.nbf !== "number") { - throw new JWTClaimValidationFailed('"nbf" claim must be a number', "nbf", "invalid"); - } - if (payload.nbf > now + tolerance) { - throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', "nbf", "check_failed"); - } - } - if (payload.exp !== void 0) { - if (typeof payload.exp !== "number") { - throw new JWTClaimValidationFailed('"exp" claim must be a number', "exp", "invalid"); - } - if (payload.exp <= now - tolerance) { - throw new JWTExpired('"exp" claim timestamp check failed', "exp", "check_failed"); - } - } - if (options.maxTokenAge) { - const age = now - payload.iat; - const max = typeof options.maxTokenAge === "number" ? options.maxTokenAge : secs_default(options.maxTokenAge); - if (age - tolerance > max) { - throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', "iat", "check_failed"); - } - if (age < 0 - tolerance) { - throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', "iat", "check_failed"); - } - } - return payload; -}; - -// dist/browser/jwt/verify.js -async function jwtVerify(jwt, key, options) { - var _a; - const verified = await compactVerify(jwt, key, options); - if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes("b64")) && verified.protectedHeader.b64 === false) { - throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); - } - const payload = jwt_claims_set_default(verified.protectedHeader, verified.payload, options); - const result = { payload, protectedHeader: verified.protectedHeader }; - if (typeof key === "function") { - return { ...result, key: verified.key }; - } - return result; -} - -// dist/browser/jwt/decrypt.js -async function jwtDecrypt(jwt, key, options) { - const decrypted = await compactDecrypt(jwt, key, options); - const payload = jwt_claims_set_default(decrypted.protectedHeader, decrypted.plaintext, options); - const { protectedHeader } = decrypted; - if (protectedHeader.iss !== void 0 && protectedHeader.iss !== payload.iss) { - throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', "iss", "mismatch"); - } - if (protectedHeader.sub !== void 0 && protectedHeader.sub !== payload.sub) { - throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', "sub", "mismatch"); - } - if (protectedHeader.aud !== void 0 && JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { - throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', "aud", "mismatch"); - } - const result = { payload, protectedHeader }; - if (typeof key === "function") { - return { ...result, key: decrypted.key }; - } - return result; -} - -// dist/browser/jwe/compact/encrypt.js -var CompactEncrypt = class { - constructor(plaintext) { - this._flattened = new FlattenedEncrypt(plaintext); - } - setContentEncryptionKey(cek) { - this._flattened.setContentEncryptionKey(cek); - return this; - } - setInitializationVector(iv) { - this._flattened.setInitializationVector(iv); - return this; - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - setKeyManagementParameters(parameters) { - this._flattened.setKeyManagementParameters(parameters); - return this; - } - async encrypt(key, options) { - const jwe = await this._flattened.encrypt(key, options); - return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join("."); - } -}; - -// dist/browser/runtime/sign.js -var sign = async (alg, key, data) => { - const cryptoKey = await getCryptoKey3(alg, key, "sign"); - check_key_length_default(alg, cryptoKey); - const signature = await webcrypto_default.subtle.sign(subtleDsa(alg, cryptoKey.algorithm), cryptoKey, data); - return new Uint8Array(signature); -}; -var sign_default = sign; - -// dist/browser/jws/flattened/sign.js -var FlattenedSign = class { - constructor(payload) { - if (!(payload instanceof Uint8Array)) { - throw new TypeError("payload must be an instance of Uint8Array"); - } - this._payload = payload; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - async sign(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader) { - throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()"); - } - if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader)) { - throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader - }; - const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - let b64 = true; - if (extensions.has("b64")) { - b64 = this._protectedHeader.b64; - if (typeof b64 !== "boolean") { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - check_key_type_default(alg, key, "sign"); - let payload = this._payload; - if (b64) { - payload = encoder.encode(encode(payload)); - } - let protectedHeader; - if (this._protectedHeader) { - protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); - } else { - protectedHeader = encoder.encode(""); - } - const data = concat(protectedHeader, encoder.encode("."), payload); - const signature = await sign_default(alg, key, data); - const jws = { - signature: encode(signature), - payload: "" - }; - if (b64) { - jws.payload = decoder.decode(payload); - } - if (this._unprotectedHeader) { - jws.header = this._unprotectedHeader; - } - if (this._protectedHeader) { - jws.protected = decoder.decode(protectedHeader); - } - return jws; - } -}; - -// dist/browser/jws/compact/sign.js -var CompactSign = class { - constructor(payload) { - this._flattened = new FlattenedSign(payload); - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - async sign(key, options) { - const jws = await this._flattened.sign(key, options); - if (jws.payload === void 0) { - throw new TypeError("use the flattened module for creating JWS with b64: false"); - } - return `${jws.protected}.${jws.payload}.${jws.signature}`; - } -}; - -// dist/browser/jws/general/sign.js -var IndividualSignature = class { - constructor(sig, key, options) { - this.parent = sig; - this.key = key; - this.options = options; - } - setProtectedHeader(protectedHeader) { - if (this.protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this.protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addSignature(...args) { - return this.parent.addSignature(...args); - } - sign(...args) { - return this.parent.sign(...args); - } - done() { - return this.parent; - } -}; -var GeneralSign = class { - constructor(payload) { - this._signatures = []; - this._payload = payload; - } - addSignature(key, options) { - const signature = new IndividualSignature(this, key, options); - this._signatures.push(signature); - return signature; - } - async sign() { - if (!this._signatures.length) { - throw new JWSInvalid("at least one signature must be added"); - } - const jws = { - signatures: [], - payload: "" - }; - for (let i = 0; i < this._signatures.length; i++) { - const signature = this._signatures[i]; - const flattened = new FlattenedSign(this._payload); - flattened.setProtectedHeader(signature.protectedHeader); - flattened.setUnprotectedHeader(signature.unprotectedHeader); - const { payload, ...rest } = await flattened.sign(signature.key, signature.options); - if (i === 0) { - jws.payload = payload; - } else if (jws.payload !== payload) { - throw new JWSInvalid("inconsistent use of JWS Unencoded Payload Option (RFC7797)"); - } - jws.signatures.push(rest); - } - return jws; - } -}; - -// dist/browser/jwt/produce.js -var ProduceJWT = class { - constructor(payload) { - if (!isObject(payload)) { - throw new TypeError("JWT Claims Set MUST be an object"); - } - this._payload = payload; - } - setIssuer(issuer) { - this._payload = { ...this._payload, iss: issuer }; - return this; - } - setSubject(subject) { - this._payload = { ...this._payload, sub: subject }; - return this; - } - setAudience(audience) { - this._payload = { ...this._payload, aud: audience }; - return this; - } - setJti(jwtId) { - this._payload = { ...this._payload, jti: jwtId }; - return this; - } - setNotBefore(input) { - if (typeof input === "number") { - this._payload = { ...this._payload, nbf: input }; - } else { - this._payload = { ...this._payload, nbf: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; - } - return this; - } - setExpirationTime(input) { - if (typeof input === "number") { - this._payload = { ...this._payload, exp: input }; - } else { - this._payload = { ...this._payload, exp: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; - } - return this; - } - setIssuedAt(input) { - if (typeof input === "undefined") { - this._payload = { ...this._payload, iat: epoch_default(/* @__PURE__ */ new Date()) }; - } else { - this._payload = { ...this._payload, iat: input }; - } - return this; - } -}; - -// dist/browser/jwt/sign.js -var SignJWT = class extends ProduceJWT { - setProtectedHeader(protectedHeader) { - this._protectedHeader = protectedHeader; - return this; - } - async sign(key, options) { - var _a; - const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); - sig.setProtectedHeader(this._protectedHeader); - if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && this._protectedHeader.crit.includes("b64") && this._protectedHeader.b64 === false) { - throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); - } - return sig.sign(key, options); - } -}; - -// dist/browser/jwt/encrypt.js -var EncryptJWT = class extends ProduceJWT { - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError("setKeyManagementParameters can only be called once"); - } - this._keyManagementParameters = parameters; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError("setContentEncryptionKey can only be called once"); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError("setInitializationVector can only be called once"); - } - this._iv = iv; - return this; - } - replicateIssuerAsHeader() { - this._replicateIssuerAsHeader = true; - return this; - } - replicateSubjectAsHeader() { - this._replicateSubjectAsHeader = true; - return this; - } - replicateAudienceAsHeader() { - this._replicateAudienceAsHeader = true; - return this; - } - async encrypt(key, options) { - const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); - if (this._replicateIssuerAsHeader) { - this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; - } - if (this._replicateSubjectAsHeader) { - this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; - } - if (this._replicateAudienceAsHeader) { - this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; - } - enc.setProtectedHeader(this._protectedHeader); - if (this._iv) { - enc.setInitializationVector(this._iv); - } - if (this._cek) { - enc.setContentEncryptionKey(this._cek); - } - if (this._keyManagementParameters) { - enc.setKeyManagementParameters(this._keyManagementParameters); - } - return enc.encrypt(key, options); - } -}; - -// dist/browser/jwk/thumbprint.js -var check = (value, description) => { - if (typeof value !== "string" || !value) { - throw new JWKInvalid(`${description} missing or invalid`); - } -}; -async function calculateJwkThumbprint(jwk, digestAlgorithm) { - if (!isObject(jwk)) { - throw new TypeError("JWK must be an object"); - } - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; - if (digestAlgorithm !== "sha256" && digestAlgorithm !== "sha384" && digestAlgorithm !== "sha512") { - throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); - } - let components; - switch (jwk.kty) { - case "EC": - check(jwk.crv, '"crv" (Curve) Parameter'); - check(jwk.x, '"x" (X Coordinate) Parameter'); - check(jwk.y, '"y" (Y Coordinate) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; - break; - case "OKP": - check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); - check(jwk.x, '"x" (Public Key) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; - break; - case "RSA": - check(jwk.e, '"e" (Exponent) Parameter'); - check(jwk.n, '"n" (Modulus) Parameter'); - components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; - break; - case "oct": - check(jwk.k, '"k" (Key Value) Parameter'); - components = { k: jwk.k, kty: jwk.kty }; - break; - default: - throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); - } - const data = encoder.encode(JSON.stringify(components)); - return encode(await digest_default(digestAlgorithm, data)); -} -async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; - const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); - return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; -} - -// dist/browser/jwk/embedded.js -async function EmbeddedJWK(protectedHeader, token) { - const joseHeader = { - ...protectedHeader, - ...token.header - }; - if (!isObject(joseHeader.jwk)) { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); - } - const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); - if (key instanceof Uint8Array || key.type !== "public") { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); - } - return key; -} - -// dist/browser/jwks/local.js -function getKtyFromAlg(alg) { - switch (typeof alg === "string" && alg.slice(0, 2)) { - case "RS": - case "PS": - return "RSA"; - case "ES": - return "EC"; - case "Ed": - return "OKP"; - default: - throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); - } -} -function isJWKSLike(jwks) { - return jwks && typeof jwks === "object" && Array.isArray(jwks.keys) && jwks.keys.every(isJWKLike); -} -function isJWKLike(key) { - return isObject(key); -} -function clone(obj) { - if (typeof structuredClone === "function") { - return structuredClone(obj); - } - return JSON.parse(JSON.stringify(obj)); -} -var LocalJWKSet = class { - constructor(jwks) { - this._cached = /* @__PURE__ */ new WeakMap(); - if (!isJWKSLike(jwks)) { - throw new JWKSInvalid("JSON Web Key Set malformed"); - } - this._jwks = clone(jwks); - } - async getKey(protectedHeader, token) { - const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; - const kty = getKtyFromAlg(alg); - const candidates = this._jwks.keys.filter((jwk2) => { - let candidate = kty === jwk2.kty; - if (candidate && typeof kid === "string") { - candidate = kid === jwk2.kid; - } - if (candidate && typeof jwk2.alg === "string") { - candidate = alg === jwk2.alg; - } - if (candidate && typeof jwk2.use === "string") { - candidate = jwk2.use === "sig"; - } - if (candidate && Array.isArray(jwk2.key_ops)) { - candidate = jwk2.key_ops.includes("verify"); - } - if (candidate && alg === "EdDSA") { - candidate = jwk2.crv === "Ed25519" || jwk2.crv === "Ed448"; - } - if (candidate) { - switch (alg) { - case "ES256": - candidate = jwk2.crv === "P-256"; - break; - case "ES256K": - candidate = jwk2.crv === "secp256k1"; - break; - case "ES384": - candidate = jwk2.crv === "P-384"; - break; - case "ES512": - candidate = jwk2.crv === "P-521"; - break; - } - } - return candidate; - }); - const { 0: jwk, length } = candidates; - if (length === 0) { - throw new JWKSNoMatchingKey(); - } else if (length !== 1) { - const error = new JWKSMultipleMatchingKeys(); - const { _cached } = this; - error[Symbol.asyncIterator] = async function* () { - for (const jwk2 of candidates) { - try { - yield await importWithAlgCache(_cached, jwk2, alg); - } catch (_a) { - continue; - } - } - }; - throw error; - } - return importWithAlgCache(this._cached, jwk, alg); - } -}; -async function importWithAlgCache(cache, jwk, alg) { - const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); - if (cached[alg] === void 0) { - const keyObject = await importJWK({ ...jwk, ext: true }, alg); - if (keyObject.type !== "public") { - throw new JWKSInvalid("JSON Web Key Set members must be public keys"); - } - cached[alg] = keyObject; - } - return cached[alg]; -} -function createLocalJWKSet(jwks) { - return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); -} - -// dist/browser/runtime/fetch_jwks.js -var fetchJwks = async (url, timeout, options) => { - let controller; - let id; - let timedOut = false; - if (typeof AbortController === "function") { - controller = new AbortController(); - id = setTimeout(() => { - timedOut = true; - controller.abort(); - }, timeout); - } - const response = await fetch(url.href, { - signal: controller ? controller.signal : void 0, - redirect: "manual", - headers: options.headers - }).catch((err) => { - if (timedOut) - throw new JWKSTimeout(); - throw err; - }); - if (id !== void 0) - clearTimeout(id); - if (response.status !== 200) { - throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response"); - } - try { - return await response.json(); - } catch (_a) { - throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON"); - } -}; -var fetch_jwks_default = fetchJwks; - -// dist/browser/jwks/remote.js -var RemoteJWKSet = class extends LocalJWKSet { - constructor(url, options) { - super({ keys: [] }); - this._jwks = void 0; - if (!(url instanceof URL)) { - throw new TypeError("url must be an instance of URL"); - } - this._url = new URL(url.href); - this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; - this._timeoutDuration = typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === "number" ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5e3; - this._cooldownDuration = typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === "number" ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 3e4; - this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === "number" ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 6e5; - } - coolingDown() { - return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cooldownDuration : false; - } - fresh() { - return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cacheMaxAge : false; - } - async getKey(protectedHeader, token) { - if (!this._jwks || !this.fresh()) { - await this.reload(); - } - try { - return await super.getKey(protectedHeader, token); - } catch (err) { - if (err instanceof JWKSNoMatchingKey) { - if (this.coolingDown() === false) { - await this.reload(); - return super.getKey(protectedHeader, token); - } - } - throw err; - } - } - async reload() { - if (this._pendingFetch && isCloudflareWorkers()) { - return new Promise((resolve) => { - const isDone = () => { - if (this._pendingFetch === void 0) { - resolve(); - } else { - setTimeout(isDone, 5); - } - }; - isDone(); - }); - } - if (!this._pendingFetch) { - this._pendingFetch = fetch_jwks_default(this._url, this._timeoutDuration, this._options).then((json) => { - if (!isJWKSLike(json)) { - throw new JWKSInvalid("JSON Web Key Set malformed"); - } - this._jwks = { keys: json.keys }; - this._jwksTimestamp = Date.now(); - this._pendingFetch = void 0; - }).catch((err) => { - this._pendingFetch = void 0; - throw err; - }); - } - await this._pendingFetch; - } -}; -function createRemoteJWKSet(url, options) { - return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); -} - -// dist/browser/jwt/unsecured.js -var UnsecuredJWT = class extends ProduceJWT { - encode() { - const header = encode(JSON.stringify({ alg: "none" })); - const payload = encode(JSON.stringify(this._payload)); - return `${header}.${payload}.`; - } - static decode(jwt, options) { - if (typeof jwt !== "string") { - throw new JWTInvalid("Unsecured JWT must be a string"); - } - const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split("."); - if (length !== 3 || signature !== "") { - throw new JWTInvalid("Invalid Unsecured JWT"); - } - let header; - try { - header = JSON.parse(decoder.decode(decode(encodedHeader))); - if (header.alg !== "none") - throw new Error(); - } catch (_a) { - throw new JWTInvalid("Invalid Unsecured JWT"); - } - const payload = jwt_claims_set_default(header, decode(encodedPayload), options); - return { payload, header }; - } -}; - -// dist/browser/util/base64url.js -var base64url_exports2 = {}; -__export(base64url_exports2, { - decode: () => decode2, - encode: () => encode2 -}); -var encode2 = encode; -var decode2 = decode; - -// dist/browser/util/decode_protected_header.js -function decodeProtectedHeader(token) { - let protectedB64u; - if (typeof token === "string") { - const parts = token.split("."); - if (parts.length === 3 || parts.length === 5) { - ; - [protectedB64u] = parts; - } - } else if (typeof token === "object" && token) { - if ("protected" in token) { - protectedB64u = token.protected; - } else { - throw new TypeError("Token does not contain a Protected Header"); - } - } - try { - if (typeof protectedB64u !== "string" || !protectedB64u) { - throw new Error(); - } - const result = JSON.parse(decoder.decode(decode2(protectedB64u))); - if (!isObject(result)) { - throw new Error(); - } - return result; - } catch (_a) { - throw new TypeError("Invalid Token or Protected Header formatting"); - } -} - -// dist/browser/util/decode_jwt.js -function decodeJwt(jwt) { - if (typeof jwt !== "string") - throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string"); - const { 1: payload, length } = jwt.split("."); - if (length === 5) - throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded"); - if (length !== 3) - throw new JWTInvalid("Invalid JWT"); - if (!payload) - throw new JWTInvalid("JWTs must contain a payload"); - let decoded; - try { - decoded = decode2(payload); - } catch (_a) { - throw new JWTInvalid("Failed to parse the base64url encoded payload"); - } - let result; - try { - result = JSON.parse(decoder.decode(decoded)); - } catch (_b) { - throw new JWTInvalid("Failed to parse the decoded payload as JSON"); - } - if (!isObject(result)) - throw new JWTInvalid("Invalid JWT Claims Set"); - return result; -} - -// dist/browser/runtime/generate.js -async function generateSecret(alg, options) { - var _a; - let length; - let algorithm; - let keyUsages; - switch (alg) { - case "HS256": - case "HS384": - case "HS512": - length = parseInt(alg.slice(-3), 10); - algorithm = { name: "HMAC", hash: `SHA-${length}`, length }; - keyUsages = ["sign", "verify"]; - break; - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - length = parseInt(alg.slice(-3), 10); - return random_default(new Uint8Array(length >> 3)); - case "A128KW": - case "A192KW": - case "A256KW": - length = parseInt(alg.slice(1, 4), 10); - algorithm = { name: "AES-KW", length }; - keyUsages = ["wrapKey", "unwrapKey"]; - break; - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": - case "A128GCM": - case "A192GCM": - case "A256GCM": - length = parseInt(alg.slice(1, 4), 10); - algorithm = { name: "AES-GCM", length }; - keyUsages = ["encrypt", "decrypt"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - return webcrypto_default.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); -} -function getModulusLengthOption(options) { - var _a; - const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; - if (typeof modulusLength !== "number" || modulusLength < 2048) { - throw new JOSENotSupported("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used"); - } - return modulusLength; -} -async function generateKeyPair(alg, options) { - var _a, _b, _c, _d; - let algorithm; - let keyUsages; - switch (alg) { - case "PS256": - case "PS384": - case "PS512": - algorithm = { - name: "RSA-PSS", - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: getModulusLengthOption(options) - }; - keyUsages = ["sign", "verify"]; - break; - case "RS256": - case "RS384": - case "RS512": - algorithm = { - name: "RSASSA-PKCS1-v1_5", - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: getModulusLengthOption(options) - }; - keyUsages = ["sign", "verify"]; - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - algorithm = { - name: "RSA-OAEP", - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: getModulusLengthOption(options) - }; - keyUsages = ["decrypt", "unwrapKey", "encrypt", "wrapKey"]; - break; - case "ES256": - algorithm = { name: "ECDSA", namedCurve: "P-256" }; - keyUsages = ["sign", "verify"]; - break; - case "ES384": - algorithm = { name: "ECDSA", namedCurve: "P-384" }; - keyUsages = ["sign", "verify"]; - break; - case "ES512": - algorithm = { name: "ECDSA", namedCurve: "P-521" }; - keyUsages = ["sign", "verify"]; - break; - case "EdDSA": - keyUsages = ["sign", "verify"]; - const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : "Ed25519"; - switch (crv) { - case "Ed25519": - case "Ed448": - algorithm = { name: crv }; - break; - default: - throw new JOSENotSupported("Invalid or unsupported crv option provided"); - } - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - keyUsages = ["deriveKey", "deriveBits"]; - const crv2 = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : "P-256"; - switch (crv2) { - case "P-256": - case "P-384": - case "P-521": { - algorithm = { name: "ECDH", namedCurve: crv2 }; - break; - } - case "X25519": - case "X448": - algorithm = { name: crv2 }; - break; - default: - throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448"); - } - break; - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - try { - return await webcrypto_default.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages); - } catch (err) { - if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { - algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - return await webcrypto_default.subtle.generateKey(algorithm, (_d = options === null || options === void 0 ? void 0 : options.extractable) !== null && _d !== void 0 ? _d : false, keyUsages); - } - throw err; - } -} - -// dist/browser/key/generate_key_pair.js -async function generateKeyPair2(alg, options) { - return generateKeyPair(alg, options); -} - -// dist/browser/key/generate_secret.js -async function generateSecret2(alg, options) { - return generateSecret(alg, options); -} -export { - CompactEncrypt, - CompactSign, - EmbeddedJWK, - EncryptJWT, - FlattenedEncrypt, - FlattenedSign, - GeneralEncrypt, - GeneralSign, - SignJWT, - UnsecuredJWT, - base64url_exports2 as base64url, - calculateJwkThumbprint, - calculateJwkThumbprintUri, - compactDecrypt, - compactVerify, - createLocalJWKSet, - createRemoteJWKSet, - decodeJwt, - decodeProtectedHeader, - errors_exports as errors, - exportJWK, - exportPKCS8, - exportSPKI, - flattenedDecrypt, - flattenedVerify, - generalDecrypt, - generalVerify, - generateKeyPair2 as generateKeyPair, - generateSecret2 as generateSecret, - importJWK, - importPKCS8, - importSPKI, - importX509, - jwtDecrypt, - jwtVerify -}; diff --git a/dist/browser/index.bundle.min.js b/dist/browser/index.bundle.min.js deleted file mode 100644 index c0fdbc9842..0000000000 --- a/dist/browser/index.bundle.min.js +++ /dev/null @@ -1,4 +0,0 @@ -var qt=Object.defineProperty;var ct=(e,t)=>{for(var r in t)qt(e,r,{get:t[r],enumerable:!0})};var f=crypto,b=e=>e instanceof CryptoKey;var Zt=async(e,t)=>{let r=`SHA-${e.slice(-3)}`;return new Uint8Array(await f.subtle.digest(r,t))},Ke=Zt;var E=new TextEncoder,v=new TextDecoder,xe=2**32;function W(...e){let t=e.reduce((o,{length:a})=>o+a,0),r=new Uint8Array(t),n=0;return e.forEach(o=>{r.set(o,n),n+=o.length}),r}function dt(e,t){return W(E.encode(e),new Uint8Array([0]),t)}function ke(e,t,r){if(t<0||t>=xe)throw new RangeError(`value must be >= 0 and <= ${xe-1}. Received ${t}`);e.set([t>>>24,t>>>16,t>>>8,t&255],r)}function He(e){let t=Math.floor(e/xe),r=e%xe,n=new Uint8Array(8);return ke(n,t,0),ke(n,r,4),n}function Ce(e){let t=new Uint8Array(4);return ke(t,e),t}function Pe(e){return W(Ce(e.length),e)}async function pt(e,t,r){let n=Math.ceil((t>>3)/32),o=new Uint8Array(n*32);for(let a=0;a>3)}var We=e=>{let t=e;typeof t=="string"&&(t=E.encode(t));let r=32768,n=[];for(let o=0;oWe(e).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_"),Be=e=>{let t=atob(e),r=new Uint8Array(t.length);for(let n=0;n{let t=e;t instanceof Uint8Array&&(t=v.decode(t)),t=t.replace(/-/g,"+").replace(/_/g,"/").replace(/\s/g,"");try{return Be(t)}catch(r){throw new TypeError("The input to be decoded is not correctly encoded.")}};var ft={};ct(ft,{JOSEAlgNotAllowed:()=>B,JOSEError:()=>C,JOSENotSupported:()=>l,JWEDecryptionFailed:()=>M,JWEInvalid:()=>u,JWKInvalid:()=>pe,JWKSInvalid:()=>L,JWKSMultipleMatchingKeys:()=>ue,JWKSNoMatchingKey:()=>q,JWKSTimeout:()=>fe,JWSInvalid:()=>h,JWSSignatureVerificationFailed:()=>Z,JWTClaimValidationFailed:()=>J,JWTExpired:()=>re,JWTInvalid:()=>H});var C=class extends Error{static get code(){return"ERR_JOSE_GENERIC"}constructor(t){var r;super(t),this.code="ERR_JOSE_GENERIC",this.name=this.constructor.name,(r=Error.captureStackTrace)===null||r===void 0||r.call(Error,this,this.constructor)}},J=class extends C{static get code(){return"ERR_JWT_CLAIM_VALIDATION_FAILED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_CLAIM_VALIDATION_FAILED",this.claim=r,this.reason=n}},re=class extends C{static get code(){return"ERR_JWT_EXPIRED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_EXPIRED",this.claim=r,this.reason=n}},B=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_ALG_NOT_ALLOWED"}static get code(){return"ERR_JOSE_ALG_NOT_ALLOWED"}},l=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_NOT_SUPPORTED"}static get code(){return"ERR_JOSE_NOT_SUPPORTED"}},M=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_DECRYPTION_FAILED",this.message="decryption operation failed"}static get code(){return"ERR_JWE_DECRYPTION_FAILED"}},u=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_INVALID"}static get code(){return"ERR_JWE_INVALID"}},h=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_INVALID"}static get code(){return"ERR_JWS_INVALID"}},H=class extends C{constructor(){super(...arguments),this.code="ERR_JWT_INVALID"}static get code(){return"ERR_JWT_INVALID"}},pe=class extends C{constructor(){super(...arguments),this.code="ERR_JWK_INVALID"}static get code(){return"ERR_JWK_INVALID"}},L=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_INVALID"}static get code(){return"ERR_JWKS_INVALID"}},q=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_NO_MATCHING_KEY",this.message="no applicable key found in the JSON Web Key Set"}static get code(){return"ERR_JWKS_NO_MATCHING_KEY"}},ue=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_MULTIPLE_MATCHING_KEYS",this.message="multiple matching keys found in the JSON Web Key Set"}static get code(){return"ERR_JWKS_MULTIPLE_MATCHING_KEYS"}},fe=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_TIMEOUT",this.message="request timed out"}static get code(){return"ERR_JWKS_TIMEOUT"}},Z=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED",this.message="signature verification failed"}static get code(){return"ERR_JWS_SIGNATURE_VERIFICATION_FAILED"}};var $=f.getRandomValues.bind(f);function Le(e){switch(e){case"A128GCM":case"A128GCMKW":case"A192GCM":case"A192GCMKW":case"A256GCM":case"A256GCMKW":return 96;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return 128;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var Je=e=>$(new Uint8Array(Le(e)>>3));var Qt=(e,t)=>{if(t.length<<3!==Le(e))throw new u("Invalid Initialization Vector length")},Te=Qt;var jt=(e,t)=>{let r=e.byteLength<<3;if(r!==t)throw new u(`Invalid Content Encryption Key length. Expected ${t} bits, got ${r} bits`)},ne=jt;var er=(e,t)=>{if(!(e instanceof Uint8Array))throw new TypeError("First argument must be a buffer");if(!(t instanceof Uint8Array))throw new TypeError("Second argument must be a buffer");if(e.length!==t.length)throw new TypeError("Input buffers must have the same length");let r=e.length,n=0,o=-1;for(;++oe.usages.includes(r))){let r="CryptoKey does not support this operation, its usages must include ";if(t.length>2){let n=t.pop();r+=`one of ${t.join(", ")}, or ${n}.`}else t.length===2?r+=`one of ${t[0]} or ${t[1]}.`:r+=`${t[0]}.`;throw new TypeError(r)}}function ht(e,t,...r){switch(t){case"HS256":case"HS384":case"HS512":{if(!N(e.algorithm,"HMAC"))throw P("HMAC");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"RS256":case"RS384":case"RS512":{if(!N(e.algorithm,"RSASSA-PKCS1-v1_5"))throw P("RSASSA-PKCS1-v1_5");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"PS256":case"PS384":case"PS512":{if(!N(e.algorithm,"RSA-PSS"))throw P("RSA-PSS");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"EdDSA":{if(e.algorithm.name!=="Ed25519"&&e.algorithm.name!=="Ed448"){if(D()){if(N(e.algorithm,"NODE-ED25519"))break;throw P("Ed25519, Ed448, or NODE-ED25519")}throw P("Ed25519 or Ed448")}break}case"ES256":case"ES384":case"ES512":{if(!N(e.algorithm,"ECDSA"))throw P("ECDSA");let n=tr(t);if(e.algorithm.namedCurve!==n)throw P(n,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r)}function I(e,t,...r){switch(t){case"A128GCM":case"A192GCM":case"A256GCM":{if(!N(e.algorithm,"AES-GCM"))throw P("AES-GCM");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"A128KW":case"A192KW":case"A256KW":{if(!N(e.algorithm,"AES-KW"))throw P("AES-KW");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"ECDH":{switch(e.algorithm.name){case"ECDH":case"X25519":case"X448":break;default:throw P("ECDH, X25519, or X448")}break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":if(!N(e.algorithm,"PBKDF2"))throw P("PBKDF2");break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(!N(e.algorithm,"RSA-OAEP"))throw P("RSA-OAEP");let n=parseInt(t.slice(9),10)||1;if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r)}function yt(e,t,...r){if(r.length>2){let n=r.pop();e+=`one of type ${r.join(", ")}, or ${n}.`}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t=="function"&&t.name?e+=` Received function ${t.name}`:typeof t=="object"&&t!=null&&t.constructor&&t.constructor.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var A=(e,...t)=>yt("Key must be ",e,...t);function $e(e,t,...r){return yt(`Key for the ${e} algorithm must be `,t,...r)}var Ge=e=>b(e),y=["CryptoKey"];async function rr(e,t,r,n,o,a){if(!(t instanceof Uint8Array))throw new TypeError(A(t,"Uint8Array"));let i=parseInt(e.slice(1,4),10),s=await f.subtle.importKey("raw",t.subarray(i>>3),"AES-CBC",!1,["decrypt"]),c=await f.subtle.importKey("raw",t.subarray(0,i>>3),{hash:`SHA-${i<<1}`,name:"HMAC"},!1,["sign"]),d=W(a,n,r,He(a.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",c,d)).slice(0,i>>3)),m;try{m=lt(o,p)}catch(T){}if(!m)throw new M;let K;try{K=new Uint8Array(await f.subtle.decrypt({iv:n,name:"AES-CBC"},s,r))}catch(T){}if(!K)throw new M;return K}async function nr(e,t,r,n,o,a){let i;t instanceof Uint8Array?i=await f.subtle.importKey("raw",t,"AES-GCM",!1,["decrypt"]):(I(t,e,"decrypt"),i=t);try{return new Uint8Array(await f.subtle.decrypt({additionalData:a,iv:n,name:"AES-GCM",tagLength:128},i,W(r,o)))}catch(s){throw new M}}var or=async(e,t,r,n,o,a)=>{if(!b(t)&&!(t instanceof Uint8Array))throw new TypeError(A(t,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(-3),10)),rr(e,t,r,n,o,a);case"A128GCM":case"A192GCM":case"A256GCM":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(1,4),10)),nr(e,t,r,n,o,a);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},De=or;var wt=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.')},Et=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.')};var ar=(...e)=>{let t=e.filter(Boolean);if(t.length===0||t.length===1)return!0;let r;for(let n of t){let o=Object.keys(n);if(!r||r.size===0){r=new Set(o);continue}for(let a of o){if(r.has(a))return!1;r.add(a)}}return!0},R=ar;function ir(e){return typeof e=="object"&&e!==null}function w(e){if(!ir(e)||Object.prototype.toString.call(e)!=="[object Object]")return!1;if(Object.getPrototypeOf(e)===null)return!0;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}var sr=[{hash:"SHA-256",name:"HMAC"},!0,["sign"]],oe=sr;function gt(e,t){if(e.algorithm.length!==parseInt(t.slice(1,4),10))throw new TypeError(`Invalid key size for alg: ${t}`)}function St(e,t,r){if(b(e))return I(e,t,r),e;if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"AES-KW",!0,[r]);throw new TypeError(A(e,...y,"Uint8Array"))}var le=async(e,t,r)=>{let n=await St(t,e,"wrapKey");gt(n,e);let o=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",o,n,"AES-KW"))},me=async(e,t,r)=>{let n=await St(t,e,"unwrapKey");gt(n,e);let o=await f.subtle.unwrapKey("raw",r,n,"AES-KW",...oe);return new Uint8Array(await f.subtle.exportKey("raw",o))};async function Re(e,t,r,n,o=new Uint8Array(0),a=new Uint8Array(0)){if(!b(e))throw new TypeError(A(e,...y));if(I(e,"ECDH"),!b(t))throw new TypeError(A(t,...y));I(t,"ECDH","deriveBits");let i=W(Pe(E.encode(r)),Pe(o),Pe(a),Ce(n)),s;e.algorithm.name==="X25519"?s=256:e.algorithm.name==="X448"?s=448:s=Math.ceil(parseInt(e.algorithm.namedCurve.substr(-3),10)/8)<<3;let c=new Uint8Array(await f.subtle.deriveBits({name:e.algorithm.name,public:e},t,s));return pt(c,n,i)}async function At(e){if(!b(e))throw new TypeError(A(e,...y));return f.subtle.generateKey(e.algorithm,!0,["deriveBits"])}function Oe(e){if(!b(e))throw new TypeError(A(e,...y));return["P-256","P-384","P-521"].includes(e.algorithm.namedCurve)||e.algorithm.name==="X25519"||e.algorithm.name==="X448"}function Ve(e){if(!(e instanceof Uint8Array)||e.length<8)throw new u("PBES2 Salt Input must be 8 or more octets")}function cr(e,t){if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"PBKDF2",!1,["deriveBits"]);if(b(e))return I(e,t,"deriveBits","deriveKey"),e;throw new TypeError(A(e,...y,"Uint8Array"))}async function _t(e,t,r,n){Ve(e);let o=dt(t,e),a=parseInt(t.slice(13,16),10),i={hash:`SHA-${t.slice(8,11)}`,iterations:r,name:"PBKDF2",salt:o},s={length:a,name:"AES-KW"},c=await cr(n,t);if(c.usages.includes("deriveBits"))return new Uint8Array(await f.subtle.deriveBits(i,c,a));if(c.usages.includes("deriveKey"))return f.subtle.deriveKey(i,c,s,!1,["wrapKey","unwrapKey"]);throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"')}var vt=async(e,t,r,n=2048,o=$(new Uint8Array(16)))=>{let a=await _t(o,e,n,t);return{encryptedKey:await le(e.slice(-6),a,r),p2c:n,p2s:g(o)}},Kt=async(e,t,r,n,o)=>{let a=await _t(o,e,n,t);return me(e.slice(-6),a,r)};function ae(e){switch(e){case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":return"RSA-OAEP";default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}var Q=(e,t)=>{if(e.startsWith("RS")||e.startsWith("PS")){let{modulusLength:r}=t.algorithm;if(typeof r!="number"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}};var xt=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"encrypt","wrapKey"),Q(e,t),t.usages.includes("encrypt"))return new Uint8Array(await f.subtle.encrypt(ae(e),t,r));if(t.usages.includes("wrapKey")){let n=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",n,t,ae(e)))}throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation')},Ht=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"decrypt","unwrapKey"),Q(e,t),t.usages.includes("decrypt"))return new Uint8Array(await f.subtle.decrypt(ae(e),t,r));if(t.usages.includes("unwrapKey")){let n=await f.subtle.unwrapKey("raw",r,t,ae(e),...oe);return new Uint8Array(await f.subtle.exportKey("raw",n))}throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation')};function he(e){switch(e){case"A128GCM":return 128;case"A192GCM":return 192;case"A256GCM":case"A128CBC-HS256":return 256;case"A192CBC-HS384":return 384;case"A256CBC-HS512":return 512;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var O=e=>$(new Uint8Array(he(e)>>3));var Fe=(e,t)=>{let r=(e.match(/.{1,64}/g)||[]).join(` -`);return`-----BEGIN ${t}----- -${r} ------END ${t}-----`};var Wt=async(e,t,r)=>{if(!b(r))throw new TypeError(A(r,...y));if(!r.extractable)throw new TypeError("CryptoKey is not extractable");if(r.type!==e)throw new TypeError(`key is not a ${e} key`);return Fe(We(new Uint8Array(await f.subtle.exportKey(t,r))),`${e.toUpperCase()} KEY`)},Jt=e=>Wt("public","spki",e),Tt=e=>Wt("private","pkcs8",e),G=(e,t,r=0)=>{r===0&&(t.unshift(t.length),t.unshift(6));let n=e.indexOf(t[0],r);if(n===-1)return!1;let o=e.subarray(n,n+t.length);return o.length!==t.length?!1:o.every((a,i)=>a===t[i])||G(e,t,n+1)},Ct=e=>{switch(!0){case G(e,[42,134,72,206,61,3,1,7]):return"P-256";case G(e,[43,129,4,0,34]):return"P-384";case G(e,[43,129,4,0,35]):return"P-521";case G(e,[43,101,110]):return"X25519";case G(e,[43,101,111]):return"X448";case G(e,[43,101,112]):return"Ed25519";case G(e,[43,101,113]):return"Ed448";default:throw new l("Invalid or unsupported EC Key Curve or OKP Key Sub Type")}},It=async(e,t,r,n,o)=>{var a,i;let s,c,d=new Uint8Array(atob(r.replace(e,"")).split("").map(m=>m.charCodeAt(0))),p=t==="spki";switch(n){case"PS256":case"PS384":case"PS512":s={name:"RSA-PSS",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RS256":case"RS384":case"RS512":s={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":s={name:"RSA-OAEP",hash:`SHA-${parseInt(n.slice(-3),10)||1}`},c=p?["encrypt","wrapKey"]:["decrypt","unwrapKey"];break;case"ES256":s={name:"ECDSA",namedCurve:"P-256"},c=p?["verify"]:["sign"];break;case"ES384":s={name:"ECDSA",namedCurve:"P-384"},c=p?["verify"]:["sign"];break;case"ES512":s={name:"ECDSA",namedCurve:"P-521"},c=p?["verify"]:["sign"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{let m=Ct(d);s=m.startsWith("P-")?{name:"ECDH",namedCurve:m}:{name:m},c=p?[]:["deriveBits"];break}case"EdDSA":s={name:Ct(d)},c=p?["verify"]:["sign"];break;default:throw new l('Invalid or unsupported "alg" (Algorithm) value')}try{return await f.subtle.importKey(t,d,s,(a=o==null?void 0:o.extractable)!==null&&a!==void 0?a:!1,c)}catch(m){if(s.name==="Ed25519"&&(m==null?void 0:m.name)==="NotSupportedError"&&D())return s={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey(t,d,s,(i=o==null?void 0:o.extractable)!==null&&i!==void 0?i:!1,c);throw m}},Dt=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g,"pkcs8",e,t,r),ze=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g,"spki",e,t,r);function Pt(e){let t=[],r=0;for(;r=128;)r=r*128+e[t]-128,t++;r=r*128+e[t]-128,t++}let n=0;if(e[t]<128)n=e[t],t++;else if(n===128){for(n=0;e[t+n]!==0||e[t+n+1]!==0;){if(n>e.byteLength)throw new TypeError("invalid indefinite form length");n++}let a=t+n+2;return{byteLength:a,contents:e.subarray(t,t+n),raw:e.subarray(0,a)}}else{let a=e[t]&127;t++,n=0;for(let i=0;i{let n;try{n=pr(e)}catch(o){throw new TypeError("failed to parse the X.509 certificate",{cause:o})}return ze(n,t,r)};function ur(e){let t,r;switch(e.kty){case"oct":{switch(e.alg){case"HS256":case"HS384":case"HS512":t={name:"HMAC",hash:`SHA-${e.alg.slice(-3)}`},r=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":throw new l(`${e.alg} keys cannot be imported as CryptoKey instances`);case"A128GCM":case"A192GCM":case"A256GCM":case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":t={name:"AES-GCM"},r=["encrypt","decrypt"];break;case"A128KW":case"A192KW":case"A256KW":t={name:"AES-KW"},r=["wrapKey","unwrapKey"];break;case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":t={name:"PBKDF2"},r=["deriveBits"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"RSA":{switch(e.alg){case"PS256":case"PS384":case"PS512":t={name:"RSA-PSS",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":t={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":t={name:"RSA-OAEP",hash:`SHA-${parseInt(e.alg.slice(-3),10)||1}`},r=e.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"EC":{switch(e.alg){case"ES256":t={name:"ECDSA",namedCurve:"P-256"},r=e.d?["sign"]:["verify"];break;case"ES384":t={name:"ECDSA",namedCurve:"P-384"},r=e.d?["sign"]:["verify"];break;case"ES512":t={name:"ECDSA",namedCurve:"P-521"},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:"ECDH",namedCurve:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"OKP":{switch(e.alg){case"EdDSA":t={name:e.crv},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}default:throw new l('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return{algorithm:t,keyUsages:r}}var fr=async e=>{var t,r;if(!e.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');let{algorithm:n,keyUsages:o}=ur(e),a=[n,(t=e.ext)!==null&&t!==void 0?t:!1,(r=e.key_ops)!==null&&r!==void 0?r:o];if(n.name==="PBKDF2")return f.subtle.importKey("raw",S(e.k),...a);let i={...e};delete i.alg,delete i.use;try{return await f.subtle.importKey("jwk",i,...a)}catch(s){if(n.name==="Ed25519"&&(s==null?void 0:s.name)==="NotSupportedError"&&D())return a[0]={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey("jwk",i,...a);throw s}},Xe=fr;async function lr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PUBLIC KEY-----")!==0)throw new TypeError('"spki" must be SPKI formatted string');return ze(e,t,r)}async function mr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN CERTIFICATE-----")!==0)throw new TypeError('"x509" must be X.509 formatted string');return Ot(e,t,r)}async function hr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PRIVATE KEY-----")!==0)throw new TypeError('"pkcs8" must be PKCS#8 formatted string');return Dt(e,t,r)}async function j(e,t,r){var n;if(!w(e))throw new TypeError("JWK must be an object");switch(t||(t=e.alg),e.kty){case"oct":if(typeof e.k!="string"||!e.k)throw new TypeError('missing "k" (Key Value) Parameter value');return r!=null||(r=e.ext!==!0),r?Xe({...e,alg:t,ext:(n=e.ext)!==null&&n!==void 0?n:!1}):S(e.k);case"RSA":if(e.oth!==void 0)throw new l('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');case"EC":case"OKP":return Xe({...e,alg:t});default:throw new l('Unsupported "kty" (Key Type) Parameter value')}}var yr=(e,t)=>{if(!(t instanceof Uint8Array)){if(!Ge(t))throw new TypeError($e(e,t,...y,"Uint8Array"));if(t.type!=="secret")throw new TypeError(`${y.join(" or ")} instances for symmetric algorithms must be of type "secret"`)}},wr=(e,t,r)=>{if(!Ge(t))throw new TypeError($e(e,t,...y));if(t.type==="secret")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`);if(r==="sign"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`);if(r==="decrypt"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`);if(t.algorithm&&r==="verify"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`);if(t.algorithm&&r==="encrypt"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`)},Er=(e,t,r)=>{e.startsWith("HS")||e==="dir"||e.startsWith("PBES2")||/^A\d{3}(?:GCM)?KW$/.test(e)?yr(e,t):wr(e,t,r)},V=Er;async function gr(e,t,r,n,o){if(!(r instanceof Uint8Array))throw new TypeError(A(r,"Uint8Array"));let a=parseInt(e.slice(1,4),10),i=await f.subtle.importKey("raw",r.subarray(a>>3),"AES-CBC",!1,["encrypt"]),s=await f.subtle.importKey("raw",r.subarray(0,a>>3),{hash:`SHA-${a<<1}`,name:"HMAC"},!1,["sign"]),c=new Uint8Array(await f.subtle.encrypt({iv:n,name:"AES-CBC"},i,t)),d=W(o,n,c,He(o.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",s,d)).slice(0,a>>3));return{ciphertext:c,tag:p}}async function Sr(e,t,r,n,o){let a;r instanceof Uint8Array?a=await f.subtle.importKey("raw",r,"AES-GCM",!1,["encrypt"]):(I(r,e,"encrypt"),a=r);let i=new Uint8Array(await f.subtle.encrypt({additionalData:o,iv:n,name:"AES-GCM",tagLength:128},a,t)),s=i.slice(-16);return{ciphertext:i.slice(0,-16),tag:s}}var Ar=async(e,t,r,n,o)=>{if(!b(r)&&!(r instanceof Uint8Array))throw new TypeError(A(r,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(-3),10)),gr(e,t,r,n,o);case"A128GCM":case"A192GCM":case"A256GCM":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(1,4),10)),Sr(e,t,r,n,o);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},ye=Ar;async function Ut(e,t,r,n){let o=e.slice(0,7);n||(n=Je(o));let{ciphertext:a,tag:i}=await ye(o,r,t,n,new Uint8Array(0));return{encryptedKey:a,iv:g(n),tag:g(i)}}async function Mt(e,t,r,n,o){let a=e.slice(0,7);return De(a,t,r,n,o,new Uint8Array(0))}async function br(e,t,r,n,o){switch(V(e,t,"decrypt"),e){case"dir":{if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");return t}case"ECDH-ES":if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!w(n.epk))throw new u('JOSE Header "epk" (Ephemeral Public Key) missing or invalid');if(!Oe(t))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let a=await j(n.epk,e),i,s;if(n.apu!==void 0){if(typeof n.apu!="string")throw new u('JOSE Header "apu" (Agreement PartyUInfo) invalid');i=S(n.apu)}if(n.apv!==void 0){if(typeof n.apv!="string")throw new u('JOSE Header "apv" (Agreement PartyVInfo) invalid');s=S(n.apv)}let c=await Re(a,t,e==="ECDH-ES"?n.enc:e,e==="ECDH-ES"?he(n.enc):parseInt(e.slice(-5,-2),10),i,s);if(e==="ECDH-ES")return c;if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e.slice(-6),c,r)}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(r===void 0)throw new u("JWE Encrypted Key missing");return Ht(e,t,r)}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.p2c!="number")throw new u('JOSE Header "p2c" (PBES2 Count) missing or invalid');let a=(o==null?void 0:o.maxPBES2Count)||1e4;if(n.p2c>a)throw new u('JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds');if(typeof n.p2s!="string")throw new u('JOSE Header "p2s" (PBES2 Salt) missing or invalid');return Kt(e,t,r,n.p2c,S(n.p2s))}case"A128KW":case"A192KW":case"A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e,t,r)}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.iv!="string")throw new u('JOSE Header "iv" (Initialization Vector) missing or invalid');if(typeof n.tag!="string")throw new u('JOSE Header "tag" (Authentication Tag) missing or invalid');let a=S(n.iv),i=S(n.tag);return Mt(e,t,r,a,i)}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}}var Nt=br;function _r(e,t,r,n,o){if(o.crit!==void 0&&n.crit===void 0)throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');if(!n||n.crit===void 0)return new Set;if(!Array.isArray(n.crit)||n.crit.length===0||n.crit.some(i=>typeof i!="string"||i.length===0))throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let a;r!==void 0?a=new Map([...Object.entries(r),...t.entries()]):a=t;for(let i of n.crit){if(!a.has(i))throw new l(`Extension Header Parameter "${i}" is not recognized`);if(o[i]===void 0)throw new e(`Extension Header Parameter "${i}" is missing`);if(a.get(i)&&n[i]===void 0)throw new e(`Extension Header Parameter "${i}" MUST be integrity protected`)}return new Set(n.crit)}var U=_r;var vr=(e,t)=>{if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!="string")))throw new TypeError(`"${e}" option must be an array of strings`);if(t)return new Set(t)},we=vr;async function Ee(e,t,r){var n;if(!w(e))throw new u("Flattened JWE must be an object");if(e.protected===void 0&&e.header===void 0&&e.unprotected===void 0)throw new u("JOSE Header missing");if(typeof e.iv!="string")throw new u("JWE Initialization Vector missing or incorrect type");if(typeof e.ciphertext!="string")throw new u("JWE Ciphertext missing or incorrect type");if(typeof e.tag!="string")throw new u("JWE Authentication Tag missing or incorrect type");if(e.protected!==void 0&&typeof e.protected!="string")throw new u("JWE Protected Header incorrect type");if(e.encrypted_key!==void 0&&typeof e.encrypted_key!="string")throw new u("JWE Encrypted Key incorrect type");if(e.aad!==void 0&&typeof e.aad!="string")throw new u("JWE AAD incorrect type");if(e.header!==void 0&&!w(e.header))throw new u("JWE Shared Unprotected Header incorrect type");if(e.unprotected!==void 0&&!w(e.unprotected))throw new u("JWE Per-Recipient Unprotected Header incorrect type");let o;if(e.protected)try{let Y=S(e.protected);o=JSON.parse(v.decode(Y))}catch(Y){throw new u("JWE Protected Header is invalid")}if(!R(o,e.header,e.unprotected))throw new u("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint");let a={...o,...e.header,...e.unprotected};if(U(u,new Map,r==null?void 0:r.crit,o,a),a.zip!==void 0){if(!o||!o.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(a.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:i,enc:s}=a;if(typeof i!="string"||!i)throw new u("missing JWE Algorithm (alg) in JWE Header");if(typeof s!="string"||!s)throw new u("missing JWE Encryption Algorithm (enc) in JWE Header");let c=r&&we("keyManagementAlgorithms",r.keyManagementAlgorithms),d=r&&we("contentEncryptionAlgorithms",r.contentEncryptionAlgorithms);if(c&&!c.has(i))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(d&&!d.has(s))throw new B('"enc" (Encryption Algorithm) Header Parameter not allowed');let p;e.encrypted_key!==void 0&&(p=S(e.encrypted_key));let m=!1;typeof t=="function"&&(t=await t(o,e),m=!0);let K;try{K=await Nt(i,t,p,a,r)}catch(Y){if(Y instanceof TypeError||Y instanceof u||Y instanceof l)throw Y;K=O(s)}let T=S(e.iv),x=S(e.tag),_=E.encode((n=e.protected)!==null&&n!==void 0?n:""),k;e.aad!==void 0?k=W(_,E.encode("."),E.encode(e.aad)):k=_;let Ne=await De(s,K,S(e.ciphertext),T,x,k);a.zip==="DEF"&&(Ne=await((r==null?void 0:r.inflateRaw)||wt)(Ne));let te={plaintext:Ne};return e.protected!==void 0&&(te.protectedHeader=o),e.aad!==void 0&&(te.additionalAuthenticatedData=S(e.aad)),e.unprotected!==void 0&&(te.sharedUnprotectedHeader=e.unprotected),e.header!==void 0&&(te.unprotectedHeader=e.header),m?{...te,key:t}:te}async function Ye(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new u("Compact JWE must be a string or Uint8Array");let{0:n,1:o,2:a,3:i,4:s,length:c}=e.split(".");if(c!==5)throw new u("Invalid Compact JWE");let d=await Ee({ciphertext:i,iv:a||void 0,protected:n||void 0,tag:s||void 0,encrypted_key:o||void 0},t,r),p={plaintext:d.plaintext,protectedHeader:d.protectedHeader};return typeof t=="function"?{...p,key:d.key}:p}async function Kr(e,t,r){if(!w(e))throw new u("General JWE must be an object");if(!Array.isArray(e.recipients)||!e.recipients.every(w))throw new u("JWE Recipients missing or incorrect type");if(!e.recipients.length)throw new u("JWE Recipients has no members");for(let n of e.recipients)try{return await Ee({aad:e.aad,ciphertext:e.ciphertext,encrypted_key:n.encrypted_key,header:n.header,iv:e.iv,protected:e.protected,tag:e.tag,unprotected:e.unprotected},t,r)}catch(o){}throw new M}var xr=async e=>{if(e instanceof Uint8Array)return{kty:"oct",k:g(e)};if(!b(e))throw new TypeError(A(e,...y,"Uint8Array"));if(!e.extractable)throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");let{ext:t,key_ops:r,alg:n,use:o,...a}=await f.subtle.exportKey("jwk",e);return a},kt=xr;async function Hr(e){return Jt(e)}async function Cr(e){return Tt(e)}async function qe(e){return kt(e)}async function Pr(e,t,r,n,o={}){let a,i,s;switch(V(e,r,"encrypt"),e){case"dir":{s=r;break}case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!Oe(r))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let{apu:c,apv:d}=o,{epk:p}=o;p||(p=(await At(r)).privateKey);let{x:m,y:K,crv:T,kty:x}=await qe(p),_=await Re(r,p,e==="ECDH-ES"?t:e,e==="ECDH-ES"?he(t):parseInt(e.slice(-5,-2),10),c,d);if(i={epk:{x:m,crv:T,kty:x}},x==="EC"&&(i.epk.y=K),c&&(i.apu=g(c)),d&&(i.apv=g(d)),e==="ECDH-ES"){s=_;break}s=n||O(t);let k=e.slice(-6);a=await le(k,_,s);break}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{s=n||O(t),a=await xt(e,r,s);break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{s=n||O(t);let{p2c:c,p2s:d}=o;({encryptedKey:a,...i}=await vt(e,r,s,c,d));break}case"A128KW":case"A192KW":case"A256KW":{s=n||O(t),a=await le(e,r,s);break}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{s=n||O(t);let{iv:c}=o;({encryptedKey:a,...i}=await Ut(e,r,s,c));break}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}return{cek:s,encryptedKey:a,parameters:i}}var Ue=Pr;var Ze=Symbol(),F=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("plaintext must be an instance of Uint8Array");this._plaintext=t}setKeyManagementParameters(t){if(this._keyManagementParameters)throw new TypeError("setKeyManagementParameters can only be called once");return this._keyManagementParameters=t,this}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._sharedUnprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._sharedUnprotectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}setContentEncryptionKey(t){if(this._cek)throw new TypeError("setContentEncryptionKey can only be called once");return this._cek=t,this}setInitializationVector(t){if(this._iv)throw new TypeError("setInitializationVector can only be called once");return this._iv=t,this}async encrypt(t,r){if(!this._protectedHeader&&!this._unprotectedHeader&&!this._sharedUnprotectedHeader)throw new u("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()");if(!R(this._protectedHeader,this._unprotectedHeader,this._sharedUnprotectedHeader))throw new u("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader,...this._sharedUnprotectedHeader};if(U(u,new Map,r==null?void 0:r.crit,this._protectedHeader,n),n.zip!==void 0){if(!this._protectedHeader||!this._protectedHeader.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(n.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:o,enc:a}=n;if(typeof o!="string"||!o)throw new u('JWE "alg" (Algorithm) Header Parameter missing or invalid');if(typeof a!="string"||!a)throw new u('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');let i;if(o==="dir"){if(this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption")}else if(o==="ECDH-ES"&&this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement");let s;{let x;({cek:s,encryptedKey:i,parameters:x}=await Ue(o,a,t,this._cek,this._keyManagementParameters)),x&&(r&&Ze in r?this._unprotectedHeader?this._unprotectedHeader={...this._unprotectedHeader,...x}:this.setUnprotectedHeader(x):this._protectedHeader?this._protectedHeader={...this._protectedHeader,...x}:this.setProtectedHeader(x))}this._iv||(this._iv=Je(a));let c,d,p;this._protectedHeader?d=E.encode(g(JSON.stringify(this._protectedHeader))):d=E.encode(""),this._aad?(p=g(this._aad),c=W(d,E.encode("."),E.encode(p))):c=d;let m,K;if(n.zip==="DEF"){let x=await((r==null?void 0:r.deflateRaw)||Et)(this._plaintext);({ciphertext:m,tag:K}=await ye(a,x,s,this._iv,c))}else({ciphertext:m,tag:K}=await ye(a,this._plaintext,s,this._iv,c));let T={ciphertext:g(m),iv:g(this._iv),tag:g(K)};return i&&(T.encrypted_key=g(i)),p&&(T.aad=p),this._protectedHeader&&(T.protected=v.decode(d)),this._sharedUnprotectedHeader&&(T.unprotected=this._sharedUnprotectedHeader),this._unprotectedHeader&&(T.header=this._unprotectedHeader),T}};var Qe=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addRecipient(...t){return this.parent.addRecipient(...t)}encrypt(...t){return this.parent.encrypt(...t)}done(){return this.parent}},je=class{constructor(t){this._recipients=[],this._plaintext=t}addRecipient(t,r){let n=new Qe(this,t,{crit:r==null?void 0:r.crit});return this._recipients.push(n),n}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}async encrypt(t){var r,n,o;if(!this._recipients.length)throw new u("at least one recipient must be added");if(t={deflateRaw:t==null?void 0:t.deflateRaw},this._recipients.length===1){let[c]=this._recipients,d=await new F(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(c.unprotectedHeader).encrypt(c.key,{...c.options,...t}),p={ciphertext:d.ciphertext,iv:d.iv,recipients:[{}],tag:d.tag};return d.aad&&(p.aad=d.aad),d.protected&&(p.protected=d.protected),d.unprotected&&(p.unprotected=d.unprotected),d.encrypted_key&&(p.recipients[0].encrypted_key=d.encrypted_key),d.header&&(p.recipients[0].header=d.header),p}let a;for(let c=0;c>3};case"RS256":case"RS384":case"RS512":return{hash:r,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return{hash:r,name:"ECDSA",namedCurve:t.namedCurve};case"EdDSA":return D()&&t.name==="NODE-ED25519"?{name:"NODE-ED25519",namedCurve:"NODE-ED25519"}:{name:t.name};default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}function Se(e,t,r){if(b(t))return ht(t,e,r),t;if(t instanceof Uint8Array){if(!e.startsWith("HS"))throw new TypeError(A(t,...y));return f.subtle.importKey("raw",t,{hash:`SHA-${e.slice(-3)}`,name:"HMAC"},!1,[r])}throw new TypeError(A(t,...y,"Uint8Array"))}var Wr=async(e,t,r,n)=>{let o=await Se(e,t,"verify");Q(e,o);let a=ge(e,o.algorithm);try{return await f.subtle.verify(a,o,r,n)}catch(i){return!1}},Bt=Wr;async function Ae(e,t,r){var n;if(!w(e))throw new h("Flattened JWS must be an object");if(e.protected===void 0&&e.header===void 0)throw new h('Flattened JWS must have either of the "protected" or "header" members');if(e.protected!==void 0&&typeof e.protected!="string")throw new h("JWS Protected Header incorrect type");if(e.payload===void 0)throw new h("JWS Payload missing");if(typeof e.signature!="string")throw new h("JWS Signature missing or incorrect type");if(e.header!==void 0&&!w(e.header))throw new h("JWS Unprotected Header incorrect type");let o={};if(e.protected)try{let k=S(e.protected);o=JSON.parse(v.decode(k))}catch(k){throw new h("JWS Protected Header is invalid")}if(!R(o,e.header))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let a={...o,...e.header},i=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,o,a),s=!0;if(i.has("b64")&&(s=o.b64,typeof s!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:c}=a;if(typeof c!="string"||!c)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');let d=r&&we("algorithms",r.algorithms);if(d&&!d.has(c))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(s){if(typeof e.payload!="string")throw new h("JWS Payload must be a string")}else if(typeof e.payload!="string"&&!(e.payload instanceof Uint8Array))throw new h("JWS Payload must be a string or an Uint8Array instance");let p=!1;typeof t=="function"&&(t=await t(o,e),p=!0),V(c,t,"verify");let m=W(E.encode((n=e.protected)!==null&&n!==void 0?n:""),E.encode("."),typeof e.payload=="string"?E.encode(e.payload):e.payload),K=S(e.signature);if(!await Bt(c,t,K,m))throw new Z;let x;s?x=S(e.payload):typeof e.payload=="string"?x=E.encode(e.payload):x=e.payload;let _={payload:x};return e.protected!==void 0&&(_.protectedHeader=o),e.header!==void 0&&(_.unprotectedHeader=e.header),p?{..._,key:t}:_}async function et(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new h("Compact JWS must be a string or Uint8Array");let{0:n,1:o,2:a,length:i}=e.split(".");if(i!==3)throw new h("Invalid Compact JWS");let s=await Ae({payload:o,protected:n,signature:a},t,r),c={payload:s.payload,protectedHeader:s.protectedHeader};return typeof t=="function"?{...c,key:s.key}:c}async function Jr(e,t,r){if(!w(e))throw new h("General JWS must be an object");if(!Array.isArray(e.signatures)||!e.signatures.every(w))throw new h("JWS Signatures missing or incorrect type");for(let n of e.signatures)try{return await Ae({header:n.header,payload:e.payload,protected:n.protected,signature:n.signature},t,r)}catch(o){}throw new Z}var ie=e=>Math.floor(e.getTime()/1e3);var Tr=/^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i,se=e=>{let t=Tr.exec(e);if(!t)throw new TypeError("Invalid time period format");let r=parseFloat(t[1]);switch(t[2].toLowerCase()){case"sec":case"secs":case"second":case"seconds":case"s":return Math.round(r);case"minute":case"minutes":case"min":case"mins":case"m":return Math.round(r*60);case"hour":case"hours":case"hr":case"hrs":case"h":return Math.round(r*3600);case"day":case"days":case"d":return Math.round(r*86400);case"week":case"weeks":case"w":return Math.round(r*604800);default:return Math.round(r*31557600)}};var Lt=e=>e.toLowerCase().replace(/^application\//,""),Ir=(e,t)=>typeof e=="string"?t.includes(e):Array.isArray(e)?t.some(Set.prototype.has.bind(new Set(e))):!1,ce=(e,t,r={})=>{let{typ:n}=r;if(n&&(typeof e.typ!="string"||Lt(e.typ)!==Lt(n)))throw new J('unexpected "typ" JWT header value',"typ","check_failed");let o;try{o=JSON.parse(v.decode(t))}catch(m){}if(!w(o))throw new H("JWT Claims Set must be a top-level JSON object");let{issuer:a}=r;if(a&&!(Array.isArray(a)?a:[a]).includes(o.iss))throw new J('unexpected "iss" claim value',"iss","check_failed");let{subject:i}=r;if(i&&o.sub!==i)throw new J('unexpected "sub" claim value',"sub","check_failed");let{audience:s}=r;if(s&&!Ir(o.aud,typeof s=="string"?[s]:s))throw new J('unexpected "aud" claim value',"aud","check_failed");let c;switch(typeof r.clockTolerance){case"string":c=se(r.clockTolerance);break;case"number":c=r.clockTolerance;break;case"undefined":c=0;break;default:throw new TypeError("Invalid clockTolerance option type")}let{currentDate:d}=r,p=ie(d||new Date);if((o.iat!==void 0||r.maxTokenAge)&&typeof o.iat!="number")throw new J('"iat" claim must be a number',"iat","invalid");if(o.nbf!==void 0){if(typeof o.nbf!="number")throw new J('"nbf" claim must be a number',"nbf","invalid");if(o.nbf>p+c)throw new J('"nbf" claim timestamp check failed',"nbf","check_failed")}if(o.exp!==void 0){if(typeof o.exp!="number")throw new J('"exp" claim must be a number',"exp","invalid");if(o.exp<=p-c)throw new re('"exp" claim timestamp check failed',"exp","check_failed")}if(r.maxTokenAge){let m=p-o.iat,K=typeof r.maxTokenAge=="number"?r.maxTokenAge:se(r.maxTokenAge);if(m-c>K)throw new re('"iat" claim timestamp check failed (too far in the past)',"iat","check_failed");if(m<0-c)throw new J('"iat" claim timestamp check failed (it should be in the past)',"iat","check_failed")}return o};async function Dr(e,t,r){var n;let o=await et(e,t,r);if(!((n=o.protectedHeader.crit)===null||n===void 0)&&n.includes("b64")&&o.protectedHeader.b64===!1)throw new H("JWTs MUST NOT use unencoded payload");let i={payload:ce(o.protectedHeader,o.payload,r),protectedHeader:o.protectedHeader};return typeof t=="function"?{...i,key:o.key}:i}async function Rr(e,t,r){let n=await Ye(e,t,r),o=ce(n.protectedHeader,n.plaintext,r),{protectedHeader:a}=n;if(a.iss!==void 0&&a.iss!==o.iss)throw new J('replicated "iss" claim header parameter mismatch',"iss","mismatch");if(a.sub!==void 0&&a.sub!==o.sub)throw new J('replicated "sub" claim header parameter mismatch',"sub","mismatch");if(a.aud!==void 0&&JSON.stringify(a.aud)!==JSON.stringify(o.aud))throw new J('replicated "aud" claim header parameter mismatch',"aud","mismatch");let i={payload:o,protectedHeader:a};return typeof t=="function"?{...i,key:n.key}:i}var be=class{constructor(t){this._flattened=new F(t)}setContentEncryptionKey(t){return this._flattened.setContentEncryptionKey(t),this}setInitializationVector(t){return this._flattened.setInitializationVector(t),this}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}setKeyManagementParameters(t){return this._flattened.setKeyManagementParameters(t),this}async encrypt(t,r){let n=await this._flattened.encrypt(t,r);return[n.protected,n.encrypted_key,n.iv,n.ciphertext,n.tag].join(".")}};var Or=async(e,t,r)=>{let n=await Se(e,t,"sign");Q(e,n);let o=await f.subtle.sign(ge(e,n.algorithm),n,r);return new Uint8Array(o)},$t=Or;var ee=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("payload must be an instance of Uint8Array");this._payload=t}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}async sign(t,r){if(!this._protectedHeader&&!this._unprotectedHeader)throw new h("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");if(!R(this._protectedHeader,this._unprotectedHeader))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader},o=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,this._protectedHeader,n),a=!0;if(o.has("b64")&&(a=this._protectedHeader.b64,typeof a!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:i}=n;if(typeof i!="string"||!i)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');V(i,t,"sign");let s=this._payload;a&&(s=E.encode(g(s)));let c;this._protectedHeader?c=E.encode(g(JSON.stringify(this._protectedHeader))):c=E.encode("");let d=W(c,E.encode("."),s),p=await $t(i,t,d),m={signature:g(p),payload:""};return a&&(m.payload=v.decode(s)),this._unprotectedHeader&&(m.header=this._unprotectedHeader),this._protectedHeader&&(m.protected=v.decode(c)),m}};var _e=class{constructor(t){this._flattened=new ee(t)}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}async sign(t,r){let n=await this._flattened.sign(t,r);if(n.payload===void 0)throw new TypeError("use the flattened module for creating JWS with b64: false");return`${n.protected}.${n.payload}.${n.signature}`}};var tt=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n}setProtectedHeader(t){if(this.protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this.protectedHeader=t,this}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addSignature(...t){return this.parent.addSignature(...t)}sign(...t){return this.parent.sign(...t)}done(){return this.parent}},rt=class{constructor(t){this._signatures=[],this._payload=t}addSignature(t,r){let n=new tt(this,t,r);return this._signatures.push(n),n}async sign(){if(!this._signatures.length)throw new h("at least one signature must be added");let t={signatures:[],payload:""};for(let r=0;r{if(typeof e!="string"||!e)throw new pe(`${t} missing or invalid`)};async function Gt(e,t){if(!w(e))throw new TypeError("JWK must be an object");if(t!=null||(t="sha256"),t!=="sha256"&&t!=="sha384"&&t!=="sha512")throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"');let r;switch(e.kty){case"EC":X(e.crv,'"crv" (Curve) Parameter'),X(e.x,'"x" (X Coordinate) Parameter'),X(e.y,'"y" (Y Coordinate) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x,y:e.y};break;case"OKP":X(e.crv,'"crv" (Subtype of Key Pair) Parameter'),X(e.x,'"x" (Public Key) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x};break;case"RSA":X(e.e,'"e" (Exponent) Parameter'),X(e.n,'"n" (Modulus) Parameter'),r={e:e.e,kty:e.kty,n:e.n};break;case"oct":X(e.k,'"k" (Key Value) Parameter'),r={k:e.k,kty:e.kty};break;default:throw new l('"kty" (Key Type) Parameter missing or unsupported')}let n=E.encode(JSON.stringify(r));return g(await Ke(t,n))}async function Ur(e,t){t!=null||(t="sha256");let r=await Gt(e,t);return`urn:ietf:params:oauth:jwk-thumbprint:sha-${t.slice(-3)}:${r}`}async function Mr(e,t){let r={...e,...t.header};if(!w(r.jwk))throw new h('"jwk" (JSON Web Key) Header Parameter must be a JSON object');let n=await j({...r.jwk,ext:!0},r.alg,!0);if(n instanceof Uint8Array||n.type!=="public")throw new h('"jwk" (JSON Web Key) Header Parameter must be a public key');return n}function Nr(e){switch(typeof e=="string"&&e.slice(0,2)){case"RS":case"PS":return"RSA";case"ES":return"EC";case"Ed":return"OKP";default:throw new l('Unsupported "alg" value for a JSON Web Key Set')}}function at(e){return e&&typeof e=="object"&&Array.isArray(e.keys)&&e.keys.every(kr)}function kr(e){return w(e)}function Br(e){return typeof structuredClone=="function"?structuredClone(e):JSON.parse(JSON.stringify(e))}var de=class{constructor(t){if(this._cached=new WeakMap,!at(t))throw new L("JSON Web Key Set malformed");this._jwks=Br(t)}async getKey(t,r){let{alg:n,kid:o}={...t,...r==null?void 0:r.header},a=Nr(n),i=this._jwks.keys.filter(d=>{let p=a===d.kty;if(p&&typeof o=="string"&&(p=o===d.kid),p&&typeof d.alg=="string"&&(p=n===d.alg),p&&typeof d.use=="string"&&(p=d.use==="sig"),p&&Array.isArray(d.key_ops)&&(p=d.key_ops.includes("verify")),p&&n==="EdDSA"&&(p=d.crv==="Ed25519"||d.crv==="Ed448"),p)switch(n){case"ES256":p=d.crv==="P-256";break;case"ES256K":p=d.crv==="secp256k1";break;case"ES384":p=d.crv==="P-384";break;case"ES512":p=d.crv==="P-521";break}return p}),{0:s,length:c}=i;if(c===0)throw new q;if(c!==1){let d=new ue,{_cached:p}=this;throw d[Symbol.asyncIterator]=async function*(){for(let m of i)try{yield await Vt(p,m,n)}catch(K){continue}},d}return Vt(this._cached,s,n)}};async function Vt(e,t,r){let n=e.get(t)||e.set(t,{}).get(t);if(n[r]===void 0){let o=await j({...t,ext:!0},r);if(o.type!=="public")throw new L("JSON Web Key Set members must be public keys");n[r]=o}return n[r]}function Lr(e){return de.prototype.getKey.bind(new de(e))}var $r=async(e,t,r)=>{let n,o,a=!1;typeof AbortController=="function"&&(n=new AbortController,o=setTimeout(()=>{a=!0,n.abort()},t));let i=await fetch(e.href,{signal:n?n.signal:void 0,redirect:"manual",headers:r.headers}).catch(s=>{throw a?new fe:s});if(o!==void 0&&clearTimeout(o),i.status!==200)throw new C("Expected 200 OK from the JSON Web Key Set HTTP response");try{return await i.json()}catch(s){throw new C("Failed to parse the JSON Web Key Set HTTP response as JSON")}},Ft=$r;var Me=class extends de{constructor(t,r){if(super({keys:[]}),this._jwks=void 0,!(t instanceof URL))throw new TypeError("url must be an instance of URL");this._url=new URL(t.href),this._options={agent:r==null?void 0:r.agent,headers:r==null?void 0:r.headers},this._timeoutDuration=typeof(r==null?void 0:r.timeoutDuration)=="number"?r==null?void 0:r.timeoutDuration:5e3,this._cooldownDuration=typeof(r==null?void 0:r.cooldownDuration)=="number"?r==null?void 0:r.cooldownDuration:3e4,this._cacheMaxAge=typeof(r==null?void 0:r.cacheMaxAge)=="number"?r==null?void 0:r.cacheMaxAge:6e5}coolingDown(){return typeof this._jwksTimestamp=="number"?Date.now(){let r=()=>{this._pendingFetch===void 0?t():setTimeout(r,5)};r()});this._pendingFetch||(this._pendingFetch=Ft(this._url,this._timeoutDuration,this._options).then(t=>{if(!at(t))throw new L("JSON Web Key Set malformed");this._jwks={keys:t.keys},this._jwksTimestamp=Date.now(),this._pendingFetch=void 0}).catch(t=>{throw this._pendingFetch=void 0,t})),await this._pendingFetch}};function Gr(e,t){return Me.prototype.getKey.bind(new Me(e,t))}var it=class extends z{encode(){let t=g(JSON.stringify({alg:"none"})),r=g(JSON.stringify(this._payload));return`${t}.${r}.`}static decode(t,r){if(typeof t!="string")throw new H("Unsecured JWT must be a string");let{0:n,1:o,2:a,length:i}=t.split(".");if(i!==3||a!=="")throw new H("Invalid Unsecured JWT");let s;try{if(s=JSON.parse(v.decode(S(n))),s.alg!=="none")throw new Error}catch(d){throw new H("Invalid Unsecured JWT")}return{payload:ce(s,S(o),r),header:s}}};var zt={};ct(zt,{decode:()=>ve,encode:()=>Vr});var Vr=g,ve=S;function Fr(e){let t;if(typeof e=="string"){let r=e.split(".");(r.length===3||r.length===5)&&([t]=r)}else if(typeof e=="object"&&e)if("protected"in e)t=e.protected;else throw new TypeError("Token does not contain a Protected Header");try{if(typeof t!="string"||!t)throw new Error;let r=JSON.parse(v.decode(ve(t)));if(!w(r))throw new Error;return r}catch(r){throw new TypeError("Invalid Token or Protected Header formatting")}}function zr(e){if(typeof e!="string")throw new H("JWTs must use Compact JWS serialization, JWT must be a string");let{1:t,length:r}=e.split(".");if(r===5)throw new H("Only JWTs using Compact JWS serialization can be decoded");if(r!==3)throw new H("Invalid JWT");if(!t)throw new H("JWTs must contain a payload");let n;try{n=ve(t)}catch(a){throw new H("Failed to parse the base64url encoded payload")}let o;try{o=JSON.parse(v.decode(n))}catch(a){throw new H("Failed to parse the decoded payload as JSON")}if(!w(o))throw new H("Invalid JWT Claims Set");return o}async function Xt(e,t){var r;let n,o,a;switch(e){case"HS256":case"HS384":case"HS512":n=parseInt(e.slice(-3),10),o={name:"HMAC",hash:`SHA-${n}`,length:n},a=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return n=parseInt(e.slice(-3),10),$(new Uint8Array(n>>3));case"A128KW":case"A192KW":case"A256KW":n=parseInt(e.slice(1,4),10),o={name:"AES-KW",length:n},a=["wrapKey","unwrapKey"];break;case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":case"A128GCM":case"A192GCM":case"A256GCM":n=parseInt(e.slice(1,4),10),o={name:"AES-GCM",length:n},a=["encrypt","decrypt"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}return f.subtle.generateKey(o,(r=t==null?void 0:t.extractable)!==null&&r!==void 0?r:!1,a)}function st(e){var t;let r=(t=e==null?void 0:e.modulusLength)!==null&&t!==void 0?t:2048;if(typeof r!="number"||r<2048)throw new l("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used");return r}async function Yt(e,t){var r,n,o,a;let i,s;switch(e){case"PS256":case"PS384":case"PS512":i={name:"RSA-PSS",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RS256":case"RS384":case"RS512":i={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":i={name:"RSA-OAEP",hash:`SHA-${parseInt(e.slice(-3),10)||1}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["decrypt","unwrapKey","encrypt","wrapKey"];break;case"ES256":i={name:"ECDSA",namedCurve:"P-256"},s=["sign","verify"];break;case"ES384":i={name:"ECDSA",namedCurve:"P-384"},s=["sign","verify"];break;case"ES512":i={name:"ECDSA",namedCurve:"P-521"},s=["sign","verify"];break;case"EdDSA":s=["sign","verify"];let c=(r=t==null?void 0:t.crv)!==null&&r!==void 0?r:"Ed25519";switch(c){case"Ed25519":case"Ed448":i={name:c};break;default:throw new l("Invalid or unsupported crv option provided")}break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{s=["deriveKey","deriveBits"];let d=(n=t==null?void 0:t.crv)!==null&&n!==void 0?n:"P-256";switch(d){case"P-256":case"P-384":case"P-521":{i={name:"ECDH",namedCurve:d};break}case"X25519":case"X448":i={name:d};break;default:throw new l("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448")}break}default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}try{return await f.subtle.generateKey(i,(o=t==null?void 0:t.extractable)!==null&&o!==void 0?o:!1,s)}catch(c){if(i.name==="Ed25519"&&(c==null?void 0:c.name)==="NotSupportedError"&&D())return i={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.generateKey(i,(a=t==null?void 0:t.extractable)!==null&&a!==void 0?a:!1,s);throw c}}async function Xr(e,t){return Yt(e,t)}async function Yr(e,t){return Xt(e,t)}export{be as CompactEncrypt,_e as CompactSign,Mr as EmbeddedJWK,ot as EncryptJWT,F as FlattenedEncrypt,ee as FlattenedSign,je as GeneralEncrypt,rt as GeneralSign,nt as SignJWT,it as UnsecuredJWT,zt as base64url,Gt as calculateJwkThumbprint,Ur as calculateJwkThumbprintUri,Ye as compactDecrypt,et as compactVerify,Lr as createLocalJWKSet,Gr as createRemoteJWKSet,zr as decodeJwt,Fr as decodeProtectedHeader,ft as errors,qe as exportJWK,Cr as exportPKCS8,Hr as exportSPKI,Ee as flattenedDecrypt,Ae as flattenedVerify,Kr as generalDecrypt,Jr as generalVerify,Xr as generateKeyPair,Yr as generateSecret,j as importJWK,hr as importPKCS8,lr as importSPKI,mr as importX509,Rr as jwtDecrypt,Dr as jwtVerify}; diff --git a/dist/browser/index.js b/dist/browser/index.js deleted file mode 100644 index 00e8cee4cd..0000000000 --- a/dist/browser/index.js +++ /dev/null @@ -1,31 +0,0 @@ -export { compactDecrypt } from './jwe/compact/decrypt.js'; -export { flattenedDecrypt } from './jwe/flattened/decrypt.js'; -export { generalDecrypt } from './jwe/general/decrypt.js'; -export { GeneralEncrypt } from './jwe/general/encrypt.js'; -export { compactVerify } from './jws/compact/verify.js'; -export { flattenedVerify } from './jws/flattened/verify.js'; -export { generalVerify } from './jws/general/verify.js'; -export { jwtVerify } from './jwt/verify.js'; -export { jwtDecrypt } from './jwt/decrypt.js'; -export { CompactEncrypt } from './jwe/compact/encrypt.js'; -export { FlattenedEncrypt } from './jwe/flattened/encrypt.js'; -export { CompactSign } from './jws/compact/sign.js'; -export { FlattenedSign } from './jws/flattened/sign.js'; -export { GeneralSign } from './jws/general/sign.js'; -export { SignJWT } from './jwt/sign.js'; -export { EncryptJWT } from './jwt/encrypt.js'; -export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.js'; -export { EmbeddedJWK } from './jwk/embedded.js'; -export { createLocalJWKSet } from './jwks/local.js'; -export { createRemoteJWKSet } from './jwks/remote.js'; -export { UnsecuredJWT } from './jwt/unsecured.js'; -export { exportPKCS8, exportSPKI, exportJWK } from './key/export.js'; -export { importSPKI, importPKCS8, importX509, importJWK } from './key/import.js'; -export { decodeProtectedHeader } from './util/decode_protected_header.js'; -export { decodeJwt } from './util/decode_jwt.js'; -import * as errors_1 from './util/errors.js'; -export { errors_1 as errors }; -export { generateKeyPair } from './key/generate_key_pair.js'; -export { generateSecret } from './key/generate_secret.js'; -import * as base64url_1 from './util/base64url.js'; -export { base64url_1 as base64url }; diff --git a/dist/browser/index.umd.js b/dist/browser/index.umd.js deleted file mode 100644 index 930812fe00..0000000000 --- a/dist/browser/index.umd.js +++ /dev/null @@ -1,3373 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jose = {})); -})(this, (function (exports) { 'use strict'; - - var __defProp = Object.defineProperty; - var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); - }; - - // dist/browser/runtime/webcrypto.js - var webcrypto_default = crypto; - var isCryptoKey = (key) => key instanceof CryptoKey; - - // dist/browser/runtime/digest.js - var digest = async (algorithm, data) => { - const subtleDigest = `SHA-${algorithm.slice(-3)}`; - return new Uint8Array(await webcrypto_default.subtle.digest(subtleDigest, data)); - }; - var digest_default = digest; - - // dist/browser/lib/buffer_utils.js - var encoder = new TextEncoder(); - var decoder = new TextDecoder(); - var MAX_INT32 = 2 ** 32; - function concat(...buffers) { - const size = buffers.reduce((acc, { length }) => acc + length, 0); - const buf = new Uint8Array(size); - let i = 0; - buffers.forEach((buffer) => { - buf.set(buffer, i); - i += buffer.length; - }); - return buf; - } - function p2s(alg, p2sInput) { - return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); - } - function writeUInt32BE(buf, value, offset) { - if (value < 0 || value >= MAX_INT32) { - throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); - } - buf.set([value >>> 24, value >>> 16, value >>> 8, value & 255], offset); - } - function uint64be(value) { - const high = Math.floor(value / MAX_INT32); - const low = value % MAX_INT32; - const buf = new Uint8Array(8); - writeUInt32BE(buf, high, 0); - writeUInt32BE(buf, low, 4); - return buf; - } - function uint32be(value) { - const buf = new Uint8Array(4); - writeUInt32BE(buf, value); - return buf; - } - function lengthAndInput(input) { - return concat(uint32be(input.length), input); - } - async function concatKdf(secret, bits, value) { - const iterations = Math.ceil((bits >> 3) / 32); - const res = new Uint8Array(iterations * 32); - for (let iter = 0; iter < iterations; iter++) { - const buf = new Uint8Array(4 + secret.length + value.length); - buf.set(uint32be(iter + 1)); - buf.set(secret, 4); - buf.set(value, 4 + secret.length); - res.set(await digest_default("sha256", buf), iter * 32); - } - return res.slice(0, bits >> 3); - } - - // dist/browser/runtime/base64url.js - var encodeBase64 = (input) => { - let unencoded = input; - if (typeof unencoded === "string") { - unencoded = encoder.encode(unencoded); - } - const CHUNK_SIZE = 32768; - const arr = []; - for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { - arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))); - } - return btoa(arr.join("")); - }; - var encode = (input) => { - return encodeBase64(input).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); - }; - var decodeBase64 = (encoded) => { - const binary = atob(encoded); - const bytes = new Uint8Array(binary.length); - for (let i = 0; i < binary.length; i++) { - bytes[i] = binary.charCodeAt(i); - } - return bytes; - }; - var decode = (input) => { - let encoded = input; - if (encoded instanceof Uint8Array) { - encoded = decoder.decode(encoded); - } - encoded = encoded.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""); - try { - return decodeBase64(encoded); - } catch (_a) { - throw new TypeError("The input to be decoded is not correctly encoded."); - } - }; - - // dist/browser/util/errors.js - var errors_exports = {}; - __export(errors_exports, { - JOSEAlgNotAllowed: () => JOSEAlgNotAllowed, - JOSEError: () => JOSEError, - JOSENotSupported: () => JOSENotSupported, - JWEDecryptionFailed: () => JWEDecryptionFailed, - JWEInvalid: () => JWEInvalid, - JWKInvalid: () => JWKInvalid, - JWKSInvalid: () => JWKSInvalid, - JWKSMultipleMatchingKeys: () => JWKSMultipleMatchingKeys, - JWKSNoMatchingKey: () => JWKSNoMatchingKey, - JWKSTimeout: () => JWKSTimeout, - JWSInvalid: () => JWSInvalid, - JWSSignatureVerificationFailed: () => JWSSignatureVerificationFailed, - JWTClaimValidationFailed: () => JWTClaimValidationFailed, - JWTExpired: () => JWTExpired, - JWTInvalid: () => JWTInvalid - }); - var JOSEError = class extends Error { - static get code() { - return "ERR_JOSE_GENERIC"; - } - constructor(message2) { - var _a; - super(message2); - this.code = "ERR_JOSE_GENERIC"; - this.name = this.constructor.name; - (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); - } - }; - var JWTClaimValidationFailed = class extends JOSEError { - static get code() { - return "ERR_JWT_CLAIM_VALIDATION_FAILED"; - } - constructor(message2, claim = "unspecified", reason = "unspecified") { - super(message2); - this.code = "ERR_JWT_CLAIM_VALIDATION_FAILED"; - this.claim = claim; - this.reason = reason; - } - }; - var JWTExpired = class extends JOSEError { - static get code() { - return "ERR_JWT_EXPIRED"; - } - constructor(message2, claim = "unspecified", reason = "unspecified") { - super(message2); - this.code = "ERR_JWT_EXPIRED"; - this.claim = claim; - this.reason = reason; - } - }; - var JOSEAlgNotAllowed = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JOSE_ALG_NOT_ALLOWED"; - } - static get code() { - return "ERR_JOSE_ALG_NOT_ALLOWED"; - } - }; - var JOSENotSupported = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JOSE_NOT_SUPPORTED"; - } - static get code() { - return "ERR_JOSE_NOT_SUPPORTED"; - } - }; - var JWEDecryptionFailed = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWE_DECRYPTION_FAILED"; - this.message = "decryption operation failed"; - } - static get code() { - return "ERR_JWE_DECRYPTION_FAILED"; - } - }; - var JWEInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWE_INVALID"; - } - static get code() { - return "ERR_JWE_INVALID"; - } - }; - var JWSInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWS_INVALID"; - } - static get code() { - return "ERR_JWS_INVALID"; - } - }; - var JWTInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWT_INVALID"; - } - static get code() { - return "ERR_JWT_INVALID"; - } - }; - var JWKInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWK_INVALID"; - } - static get code() { - return "ERR_JWK_INVALID"; - } - }; - var JWKSInvalid = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_INVALID"; - } - static get code() { - return "ERR_JWKS_INVALID"; - } - }; - var JWKSNoMatchingKey = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_NO_MATCHING_KEY"; - this.message = "no applicable key found in the JSON Web Key Set"; - } - static get code() { - return "ERR_JWKS_NO_MATCHING_KEY"; - } - }; - var JWKSMultipleMatchingKeys = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; - this.message = "multiple matching keys found in the JSON Web Key Set"; - } - static get code() { - return "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; - } - }; - var JWKSTimeout = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWKS_TIMEOUT"; - this.message = "request timed out"; - } - static get code() { - return "ERR_JWKS_TIMEOUT"; - } - }; - var JWSSignatureVerificationFailed = class extends JOSEError { - constructor() { - super(...arguments); - this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; - this.message = "signature verification failed"; - } - static get code() { - return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; - } - }; - - // dist/browser/runtime/random.js - var random_default = webcrypto_default.getRandomValues.bind(webcrypto_default); - - // dist/browser/lib/iv.js - function bitLength(alg) { - switch (alg) { - case "A128GCM": - case "A128GCMKW": - case "A192GCM": - case "A192GCMKW": - case "A256GCM": - case "A256GCMKW": - return 96; - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - return 128; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } - } - var iv_default = (alg) => random_default(new Uint8Array(bitLength(alg) >> 3)); - - // dist/browser/lib/check_iv_length.js - var checkIvLength = (enc, iv) => { - if (iv.length << 3 !== bitLength(enc)) { - throw new JWEInvalid("Invalid Initialization Vector length"); - } - }; - var check_iv_length_default = checkIvLength; - - // dist/browser/runtime/check_cek_length.js - var checkCekLength = (cek, expected) => { - const actual = cek.byteLength << 3; - if (actual !== expected) { - throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); - } - }; - var check_cek_length_default = checkCekLength; - - // dist/browser/runtime/timing_safe_equal.js - var timingSafeEqual = (a, b) => { - if (!(a instanceof Uint8Array)) { - throw new TypeError("First argument must be a buffer"); - } - if (!(b instanceof Uint8Array)) { - throw new TypeError("Second argument must be a buffer"); - } - if (a.length !== b.length) { - throw new TypeError("Input buffers must have the same length"); - } - const len = a.length; - let out = 0; - let i = -1; - while (++i < len) { - out |= a[i] ^ b[i]; - } - return out === 0; - }; - var timing_safe_equal_default = timingSafeEqual; - - // dist/browser/runtime/env.js - function isCloudflareWorkers() { - return typeof WebSocketPair !== "undefined" || typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime !== "undefined" && EdgeRuntime === "vercel"; - } - - // dist/browser/lib/crypto_key.js - function unusable(name, prop = "algorithm.name") { - return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); - } - function isAlgorithm(algorithm, name) { - return algorithm.name === name; - } - function getHashLength(hash) { - return parseInt(hash.name.slice(4), 10); - } - function getNamedCurve(alg) { - switch (alg) { - case "ES256": - return "P-256"; - case "ES384": - return "P-384"; - case "ES512": - return "P-521"; - default: - throw new Error("unreachable"); - } - } - function checkUsage(key, usages) { - if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { - let msg = "CryptoKey does not support this operation, its usages must include "; - if (usages.length > 2) { - const last = usages.pop(); - msg += `one of ${usages.join(", ")}, or ${last}.`; - } else if (usages.length === 2) { - msg += `one of ${usages[0]} or ${usages[1]}.`; - } else { - msg += `${usages[0]}.`; - } - throw new TypeError(msg); - } - } - function checkSigCryptoKey(key, alg, ...usages) { - switch (alg) { - case "HS256": - case "HS384": - case "HS512": { - if (!isAlgorithm(key.algorithm, "HMAC")) - throw unusable("HMAC"); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - case "RS256": - case "RS384": - case "RS512": { - if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5")) - throw unusable("RSASSA-PKCS1-v1_5"); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - case "PS256": - case "PS384": - case "PS512": { - if (!isAlgorithm(key.algorithm, "RSA-PSS")) - throw unusable("RSA-PSS"); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - case "EdDSA": { - if (key.algorithm.name !== "Ed25519" && key.algorithm.name !== "Ed448") { - if (isCloudflareWorkers()) { - if (isAlgorithm(key.algorithm, "NODE-ED25519")) - break; - throw unusable("Ed25519, Ed448, or NODE-ED25519"); - } - throw unusable("Ed25519 or Ed448"); - } - break; - } - case "ES256": - case "ES384": - case "ES512": { - if (!isAlgorithm(key.algorithm, "ECDSA")) - throw unusable("ECDSA"); - const expected = getNamedCurve(alg); - const actual = key.algorithm.namedCurve; - if (actual !== expected) - throw unusable(expected, "algorithm.namedCurve"); - break; - } - default: - throw new TypeError("CryptoKey does not support this operation"); - } - checkUsage(key, usages); - } - function checkEncCryptoKey(key, alg, ...usages) { - switch (alg) { - case "A128GCM": - case "A192GCM": - case "A256GCM": { - if (!isAlgorithm(key.algorithm, "AES-GCM")) - throw unusable("AES-GCM"); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, "algorithm.length"); - break; - } - case "A128KW": - case "A192KW": - case "A256KW": { - if (!isAlgorithm(key.algorithm, "AES-KW")) - throw unusable("AES-KW"); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, "algorithm.length"); - break; - } - case "ECDH": { - switch (key.algorithm.name) { - case "ECDH": - case "X25519": - case "X448": - break; - default: - throw unusable("ECDH, X25519, or X448"); - } - break; - } - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": - if (!isAlgorithm(key.algorithm, "PBKDF2")) - throw unusable("PBKDF2"); - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": { - if (!isAlgorithm(key.algorithm, "RSA-OAEP")) - throw unusable("RSA-OAEP"); - const expected = parseInt(alg.slice(9), 10) || 1; - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, "algorithm.hash"); - break; - } - default: - throw new TypeError("CryptoKey does not support this operation"); - } - checkUsage(key, usages); - } - - // dist/browser/lib/invalid_key_input.js - function message(msg, actual, ...types2) { - if (types2.length > 2) { - const last = types2.pop(); - msg += `one of type ${types2.join(", ")}, or ${last}.`; - } else if (types2.length === 2) { - msg += `one of type ${types2[0]} or ${types2[1]}.`; - } else { - msg += `of type ${types2[0]}.`; - } - if (actual == null) { - msg += ` Received ${actual}`; - } else if (typeof actual === "function" && actual.name) { - msg += ` Received function ${actual.name}`; - } else if (typeof actual === "object" && actual != null) { - if (actual.constructor && actual.constructor.name) { - msg += ` Received an instance of ${actual.constructor.name}`; - } - } - return msg; - } - var invalid_key_input_default = (actual, ...types2) => { - return message("Key must be ", actual, ...types2); - }; - function withAlg(alg, actual, ...types2) { - return message(`Key for the ${alg} algorithm must be `, actual, ...types2); - } - - // dist/browser/runtime/is_key_like.js - var is_key_like_default = (key) => { - return isCryptoKey(key); - }; - var types = ["CryptoKey"]; - - // dist/browser/runtime/decrypt.js - async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); - } - const keySize = parseInt(enc.slice(1, 4), 10); - const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["decrypt"]); - const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { - hash: `SHA-${keySize << 1}`, - name: "HMAC" - }, false, ["sign"]); - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); - const expectedTag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); - let macCheckPassed; - try { - macCheckPassed = timing_safe_equal_default(tag, expectedTag); - } catch (_a) { - } - if (!macCheckPassed) { - throw new JWEDecryptionFailed(); - } - let plaintext; - try { - plaintext = new Uint8Array(await webcrypto_default.subtle.decrypt({ iv, name: "AES-CBC" }, encKey, ciphertext)); - } catch (_b) { - } - if (!plaintext) { - throw new JWEDecryptionFailed(); - } - return plaintext; - } - async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { - let encKey; - if (cek instanceof Uint8Array) { - encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["decrypt"]); - } else { - checkEncCryptoKey(cek, enc, "decrypt"); - encKey = cek; - } - try { - return new Uint8Array(await webcrypto_default.subtle.decrypt({ - additionalData: aad, - iv, - name: "AES-GCM", - tagLength: 128 - }, encKey, concat(ciphertext, tag))); - } catch (_a) { - throw new JWEDecryptionFailed(); - } - } - var decrypt = async (enc, cek, ciphertext, iv, tag, aad) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); - } - check_iv_length_default(enc, iv); - switch (enc) { - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); - return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad); - case "A128GCM": - case "A192GCM": - case "A256GCM": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); - return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); - default: - throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); - } - }; - var decrypt_default = decrypt; - - // dist/browser/runtime/zlib.js - var inflate = async () => { - throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.'); - }; - var deflate = async () => { - throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.'); - }; - - // dist/browser/lib/is_disjoint.js - var isDisjoint = (...headers) => { - const sources = headers.filter(Boolean); - if (sources.length === 0 || sources.length === 1) { - return true; - } - let acc; - for (const header of sources) { - const parameters = Object.keys(header); - if (!acc || acc.size === 0) { - acc = new Set(parameters); - continue; - } - for (const parameter of parameters) { - if (acc.has(parameter)) { - return false; - } - acc.add(parameter); - } - } - return true; - }; - var is_disjoint_default = isDisjoint; - - // dist/browser/lib/is_object.js - function isObjectLike(value) { - return typeof value === "object" && value !== null; - } - function isObject(input) { - if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") { - return false; - } - if (Object.getPrototypeOf(input) === null) { - return true; - } - let proto = input; - while (Object.getPrototypeOf(proto) !== null) { - proto = Object.getPrototypeOf(proto); - } - return Object.getPrototypeOf(input) === proto; - } - - // dist/browser/runtime/bogus.js - var bogusWebCrypto = [ - { hash: "SHA-256", name: "HMAC" }, - true, - ["sign"] - ]; - var bogus_default = bogusWebCrypto; - - // dist/browser/runtime/aeskw.js - function checkKeySize(key, alg) { - if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) { - throw new TypeError(`Invalid key size for alg: ${alg}`); - } - } - function getCryptoKey(key, alg, usage) { - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, usage); - return key; - } - if (key instanceof Uint8Array) { - return webcrypto_default.subtle.importKey("raw", key, "AES-KW", true, [usage]); - } - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); - } - var wrap = async (alg, key, cek) => { - const cryptoKey = await getCryptoKey(key, alg, "wrapKey"); - checkKeySize(cryptoKey, alg); - const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, cryptoKey, "AES-KW")); - }; - var unwrap = async (alg, key, encryptedKey) => { - const cryptoKey = await getCryptoKey(key, alg, "unwrapKey"); - checkKeySize(cryptoKey, alg); - const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, cryptoKey, "AES-KW", ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); - }; - - // dist/browser/runtime/ecdhes.js - async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { - if (!isCryptoKey(publicKey)) { - throw new TypeError(invalid_key_input_default(publicKey, ...types)); - } - checkEncCryptoKey(publicKey, "ECDH"); - if (!isCryptoKey(privateKey)) { - throw new TypeError(invalid_key_input_default(privateKey, ...types)); - } - checkEncCryptoKey(privateKey, "ECDH", "deriveBits"); - const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); - let length; - if (publicKey.algorithm.name === "X25519") { - length = 256; - } else if (publicKey.algorithm.name === "X448") { - length = 448; - } else { - length = Math.ceil(parseInt(publicKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3; - } - const sharedSecret = new Uint8Array(await webcrypto_default.subtle.deriveBits({ - name: publicKey.algorithm.name, - public: publicKey - }, privateKey, length)); - return concatKdf(sharedSecret, keyLength, value); - } - async function generateEpk(key) { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - return webcrypto_default.subtle.generateKey(key.algorithm, true, ["deriveBits"]); - } - function ecdhAllowed(key) { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - return ["P-256", "P-384", "P-521"].includes(key.algorithm.namedCurve) || key.algorithm.name === "X25519" || key.algorithm.name === "X448"; - } - - // dist/browser/lib/check_p2s.js - function checkP2s(p2s2) { - if (!(p2s2 instanceof Uint8Array) || p2s2.length < 8) { - throw new JWEInvalid("PBES2 Salt Input must be 8 or more octets"); - } - } - - // dist/browser/runtime/pbes2kw.js - function getCryptoKey2(key, alg) { - if (key instanceof Uint8Array) { - return webcrypto_default.subtle.importKey("raw", key, "PBKDF2", false, ["deriveBits"]); - } - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, "deriveBits", "deriveKey"); - return key; - } - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); - } - async function deriveKey2(p2s2, alg, p2c, key) { - checkP2s(p2s2); - const salt = p2s(alg, p2s2); - const keylen = parseInt(alg.slice(13, 16), 10); - const subtleAlg = { - hash: `SHA-${alg.slice(8, 11)}`, - iterations: p2c, - name: "PBKDF2", - salt - }; - const wrapAlg = { - length: keylen, - name: "AES-KW" - }; - const cryptoKey = await getCryptoKey2(key, alg); - if (cryptoKey.usages.includes("deriveBits")) { - return new Uint8Array(await webcrypto_default.subtle.deriveBits(subtleAlg, cryptoKey, keylen)); - } - if (cryptoKey.usages.includes("deriveKey")) { - return webcrypto_default.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ["wrapKey", "unwrapKey"]); - } - throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"'); - } - var encrypt = async (alg, key, cek, p2c = 2048, p2s2 = random_default(new Uint8Array(16))) => { - const derived = await deriveKey2(p2s2, alg, p2c, key); - const encryptedKey = await wrap(alg.slice(-6), derived, cek); - return { encryptedKey, p2c, p2s: encode(p2s2) }; - }; - var decrypt2 = async (alg, key, encryptedKey, p2c, p2s2) => { - const derived = await deriveKey2(p2s2, alg, p2c, key); - return unwrap(alg.slice(-6), derived, encryptedKey); - }; - - // dist/browser/runtime/subtle_rsaes.js - function subtleRsaEs(alg) { - switch (alg) { - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - return "RSA-OAEP"; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } - } - - // dist/browser/runtime/check_key_length.js - var check_key_length_default = (alg, key) => { - if (alg.startsWith("RS") || alg.startsWith("PS")) { - const { modulusLength } = key.algorithm; - if (typeof modulusLength !== "number" || modulusLength < 2048) { - throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); - } - } - }; - - // dist/browser/runtime/rsaes.js - var encrypt2 = async (alg, key, cek) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - checkEncCryptoKey(key, alg, "encrypt", "wrapKey"); - check_key_length_default(alg, key); - if (key.usages.includes("encrypt")) { - return new Uint8Array(await webcrypto_default.subtle.encrypt(subtleRsaEs(alg), key, cek)); - } - if (key.usages.includes("wrapKey")) { - const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, key, subtleRsaEs(alg))); - } - throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation'); - }; - var decrypt3 = async (alg, key, encryptedKey) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - checkEncCryptoKey(key, alg, "decrypt", "unwrapKey"); - check_key_length_default(alg, key); - if (key.usages.includes("decrypt")) { - return new Uint8Array(await webcrypto_default.subtle.decrypt(subtleRsaEs(alg), key, encryptedKey)); - } - if (key.usages.includes("unwrapKey")) { - const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, key, subtleRsaEs(alg), ...bogus_default); - return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); - } - throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation'); - }; - - // dist/browser/lib/cek.js - function bitLength2(alg) { - switch (alg) { - case "A128GCM": - return 128; - case "A192GCM": - return 192; - case "A256GCM": - case "A128CBC-HS256": - return 256; - case "A192CBC-HS384": - return 384; - case "A256CBC-HS512": - return 512; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } - } - var cek_default = (alg) => random_default(new Uint8Array(bitLength2(alg) >> 3)); - - // dist/browser/lib/format_pem.js - var format_pem_default = (b64, descriptor) => { - const newlined = (b64.match(/.{1,64}/g) || []).join("\n"); - return `-----BEGIN ${descriptor}----- -${newlined} ------END ${descriptor}-----`; - }; - - // dist/browser/runtime/asn1.js - var genericExport = async (keyType, keyFormat, key) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - if (!key.extractable) { - throw new TypeError("CryptoKey is not extractable"); - } - if (key.type !== keyType) { - throw new TypeError(`key is not a ${keyType} key`); - } - return format_pem_default(encodeBase64(new Uint8Array(await webcrypto_default.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`); - }; - var toSPKI = (key) => { - return genericExport("public", "spki", key); - }; - var toPKCS8 = (key) => { - return genericExport("private", "pkcs8", key); - }; - var findOid = (keyData, oid, from = 0) => { - if (from === 0) { - oid.unshift(oid.length); - oid.unshift(6); - } - let i = keyData.indexOf(oid[0], from); - if (i === -1) - return false; - const sub = keyData.subarray(i, i + oid.length); - if (sub.length !== oid.length) - return false; - return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1); - }; - var getNamedCurve2 = (keyData) => { - switch (true) { - case findOid(keyData, [42, 134, 72, 206, 61, 3, 1, 7]): - return "P-256"; - case findOid(keyData, [43, 129, 4, 0, 34]): - return "P-384"; - case findOid(keyData, [43, 129, 4, 0, 35]): - return "P-521"; - case findOid(keyData, [43, 101, 110]): - return "X25519"; - case findOid(keyData, [43, 101, 111]): - return "X448"; - case findOid(keyData, [43, 101, 112]): - return "Ed25519"; - case findOid(keyData, [43, 101, 113]): - return "Ed448"; - default: - throw new JOSENotSupported("Invalid or unsupported EC Key Curve or OKP Key Sub Type"); - } - }; - var genericImport = async (replace, keyFormat, pem, alg, options) => { - var _a, _b; - let algorithm; - let keyUsages; - const keyData = new Uint8Array(atob(pem.replace(replace, "")).split("").map((c) => c.charCodeAt(0))); - const isPublic = keyFormat === "spki"; - switch (alg) { - case "PS256": - case "PS384": - case "PS512": - algorithm = { name: "RSA-PSS", hash: `SHA-${alg.slice(-3)}` }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "RS256": - case "RS384": - case "RS512": - algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.slice(-3)}` }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - algorithm = { - name: "RSA-OAEP", - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}` - }; - keyUsages = isPublic ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"]; - break; - case "ES256": - algorithm = { name: "ECDSA", namedCurve: "P-256" }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "ES384": - algorithm = { name: "ECDSA", namedCurve: "P-384" }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "ES512": - algorithm = { name: "ECDSA", namedCurve: "P-521" }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - const namedCurve = getNamedCurve2(keyData); - algorithm = namedCurve.startsWith("P-") ? { name: "ECDH", namedCurve } : { name: namedCurve }; - keyUsages = isPublic ? [] : ["deriveBits"]; - break; - } - case "EdDSA": - algorithm = { name: getNamedCurve2(keyData) }; - keyUsages = isPublic ? ["verify"] : ["sign"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value'); - } - try { - return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); - } catch (err) { - if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { - algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages); - } - throw err; - } - }; - var fromPKCS8 = (pem, alg, options) => { - return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, "pkcs8", pem, alg, options); - }; - var fromSPKI = (pem, alg, options) => { - return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "spki", pem, alg, options); - }; - function getElement(seq) { - let result = []; - let next = 0; - while (next < seq.length) { - let nextPart = parseElement(seq.subarray(next)); - result.push(nextPart); - next += nextPart.byteLength; - } - return result; - } - function parseElement(bytes) { - let position = 0; - let tag = bytes[0] & 31; - position++; - if (tag === 31) { - tag = 0; - while (bytes[position] >= 128) { - tag = tag * 128 + bytes[position] - 128; - position++; - } - tag = tag * 128 + bytes[position] - 128; - position++; - } - let length = 0; - if (bytes[position] < 128) { - length = bytes[position]; - position++; - } else if (length === 128) { - length = 0; - while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { - if (length > bytes.byteLength) { - throw new TypeError("invalid indefinite form length"); - } - length++; - } - const byteLength2 = position + length + 2; - return { - byteLength: byteLength2, - contents: bytes.subarray(position, position + length), - raw: bytes.subarray(0, byteLength2) - }; - } else { - let numberOfDigits = bytes[position] & 127; - position++; - length = 0; - for (let i = 0; i < numberOfDigits; i++) { - length = length * 256 + bytes[position]; - position++; - } - } - const byteLength = position + length; - return { - byteLength, - contents: bytes.subarray(position, byteLength), - raw: bytes.subarray(0, byteLength) - }; - } - function spkiFromX509(buf) { - const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents); - return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 160 ? 6 : 5].raw); - } - function getSPKI(x509) { - const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ""); - const raw = decodeBase64(pem); - return format_pem_default(spkiFromX509(raw), "PUBLIC KEY"); - } - var fromX509 = (pem, alg, options) => { - let spki; - try { - spki = getSPKI(pem); - } catch (cause) { - throw new TypeError("failed to parse the X.509 certificate", { cause }); - } - return fromSPKI(spki, alg, options); - }; - - // dist/browser/runtime/jwk_to_key.js - function subtleMapping(jwk) { - let algorithm; - let keyUsages; - switch (jwk.kty) { - case "oct": { - switch (jwk.alg) { - case "HS256": - case "HS384": - case "HS512": - algorithm = { name: "HMAC", hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = ["sign", "verify"]; - break; - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`); - case "A128GCM": - case "A192GCM": - case "A256GCM": - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": - algorithm = { name: "AES-GCM" }; - keyUsages = ["encrypt", "decrypt"]; - break; - case "A128KW": - case "A192KW": - case "A256KW": - algorithm = { name: "AES-KW" }; - keyUsages = ["wrapKey", "unwrapKey"]; - break; - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": - algorithm = { name: "PBKDF2" }; - keyUsages = ["deriveBits"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case "RSA": { - switch (jwk.alg) { - case "PS256": - case "PS384": - case "PS512": - algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "RS256": - case "RS384": - case "RS512": - algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - algorithm = { - name: "RSA-OAEP", - hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}` - }; - keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case "EC": { - switch (jwk.alg) { - case "ES256": - algorithm = { name: "ECDSA", namedCurve: "P-256" }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ES384": - algorithm = { name: "ECDSA", namedCurve: "P-384" }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ES512": - algorithm = { name: "ECDSA", namedCurve: "P-521" }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": - algorithm = { name: "ECDH", namedCurve: jwk.crv }; - keyUsages = jwk.d ? ["deriveBits"] : []; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case "OKP": { - switch (jwk.alg) { - case "EdDSA": - algorithm = { name: jwk.crv }; - keyUsages = jwk.d ? ["sign"] : ["verify"]; - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": - algorithm = { name: jwk.crv }; - keyUsages = jwk.d ? ["deriveBits"] : []; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); - } - return { algorithm, keyUsages }; - } - var parse = async (jwk) => { - var _a, _b; - if (!jwk.alg) { - throw new TypeError('"alg" argument is required when "jwk.alg" is not present'); - } - const { algorithm, keyUsages } = subtleMapping(jwk); - const rest = [ - algorithm, - (_a = jwk.ext) !== null && _a !== void 0 ? _a : false, - (_b = jwk.key_ops) !== null && _b !== void 0 ? _b : keyUsages - ]; - if (algorithm.name === "PBKDF2") { - return webcrypto_default.subtle.importKey("raw", decode(jwk.k), ...rest); - } - const keyData = { ...jwk }; - delete keyData.alg; - delete keyData.use; - try { - return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); - } catch (err) { - if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { - rest[0] = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); - } - throw err; - } - }; - var jwk_to_key_default = parse; - - // dist/browser/key/import.js - async function importSPKI(spki, alg, options) { - if (typeof spki !== "string" || spki.indexOf("-----BEGIN PUBLIC KEY-----") !== 0) { - throw new TypeError('"spki" must be SPKI formatted string'); - } - return fromSPKI(spki, alg, options); - } - async function importX509(x509, alg, options) { - if (typeof x509 !== "string" || x509.indexOf("-----BEGIN CERTIFICATE-----") !== 0) { - throw new TypeError('"x509" must be X.509 formatted string'); - } - return fromX509(x509, alg, options); - } - async function importPKCS8(pkcs8, alg, options) { - if (typeof pkcs8 !== "string" || pkcs8.indexOf("-----BEGIN PRIVATE KEY-----") !== 0) { - throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); - } - return fromPKCS8(pkcs8, alg, options); - } - async function importJWK(jwk, alg, octAsKeyObject) { - var _a; - if (!isObject(jwk)) { - throw new TypeError("JWK must be an object"); - } - alg || (alg = jwk.alg); - switch (jwk.kty) { - case "oct": - if (typeof jwk.k !== "string" || !jwk.k) { - throw new TypeError('missing "k" (Key Value) Parameter value'); - } - octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : octAsKeyObject = jwk.ext !== true; - if (octAsKeyObject) { - return jwk_to_key_default({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); - } - return decode(jwk.k); - case "RSA": - if (jwk.oth !== void 0) { - throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); - } - case "EC": - case "OKP": - return jwk_to_key_default({ ...jwk, alg }); - default: - throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); - } - } - - // dist/browser/lib/check_key_type.js - var symmetricTypeCheck = (alg, key) => { - if (key instanceof Uint8Array) - return; - if (!is_key_like_default(key)) { - throw new TypeError(withAlg(alg, key, ...types, "Uint8Array")); - } - if (key.type !== "secret") { - throw new TypeError(`${types.join(" or ")} instances for symmetric algorithms must be of type "secret"`); - } - }; - var asymmetricTypeCheck = (alg, key, usage) => { - if (!is_key_like_default(key)) { - throw new TypeError(withAlg(alg, key, ...types)); - } - if (key.type === "secret") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`); - } - if (usage === "sign" && key.type === "public") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`); - } - if (usage === "decrypt" && key.type === "public") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`); - } - if (key.algorithm && usage === "verify" && key.type === "private") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`); - } - if (key.algorithm && usage === "encrypt" && key.type === "private") { - throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`); - } - }; - var checkKeyType = (alg, key, usage) => { - const symmetric = alg.startsWith("HS") || alg === "dir" || alg.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(alg); - if (symmetric) { - symmetricTypeCheck(alg, key); - } else { - asymmetricTypeCheck(alg, key, usage); - } - }; - var check_key_type_default = checkKeyType; - - // dist/browser/runtime/encrypt.js - async function cbcEncrypt(enc, plaintext, cek, iv, aad) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); - } - const keySize = parseInt(enc.slice(1, 4), 10); - const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["encrypt"]); - const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { - hash: `SHA-${keySize << 1}`, - name: "HMAC" - }, false, ["sign"]); - const ciphertext = new Uint8Array(await webcrypto_default.subtle.encrypt({ - iv, - name: "AES-CBC" - }, encKey, plaintext)); - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); - const tag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); - return { ciphertext, tag }; - } - async function gcmEncrypt(enc, plaintext, cek, iv, aad) { - let encKey; - if (cek instanceof Uint8Array) { - encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["encrypt"]); - } else { - checkEncCryptoKey(cek, enc, "encrypt"); - encKey = cek; - } - const encrypted = new Uint8Array(await webcrypto_default.subtle.encrypt({ - additionalData: aad, - iv, - name: "AES-GCM", - tagLength: 128 - }, encKey, plaintext)); - const tag = encrypted.slice(-16); - const ciphertext = encrypted.slice(0, -16); - return { ciphertext, tag }; - } - var encrypt3 = async (enc, plaintext, cek, iv, aad) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); - } - check_iv_length_default(enc, iv); - switch (enc) { - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); - return cbcEncrypt(enc, plaintext, cek, iv, aad); - case "A128GCM": - case "A192GCM": - case "A256GCM": - if (cek instanceof Uint8Array) - check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); - return gcmEncrypt(enc, plaintext, cek, iv, aad); - default: - throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); - } - }; - var encrypt_default = encrypt3; - - // dist/browser/lib/aesgcmkw.js - async function wrap2(alg, key, cek, iv) { - const jweAlgorithm = alg.slice(0, 7); - iv || (iv = iv_default(jweAlgorithm)); - const { ciphertext: encryptedKey, tag } = await encrypt_default(jweAlgorithm, cek, key, iv, new Uint8Array(0)); - return { encryptedKey, iv: encode(iv), tag: encode(tag) }; - } - async function unwrap2(alg, key, encryptedKey, iv, tag) { - const jweAlgorithm = alg.slice(0, 7); - return decrypt_default(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); - } - - // dist/browser/lib/decrypt_key_management.js - async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { - check_key_type_default(alg, key, "decrypt"); - switch (alg) { - case "dir": { - if (encryptedKey !== void 0) - throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); - return key; - } - case "ECDH-ES": - if (encryptedKey !== void 0) - throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - if (!isObject(joseHeader.epk)) - throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); - if (!ecdhAllowed(key)) - throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); - const epk = await importJWK(joseHeader.epk, alg); - let partyUInfo; - let partyVInfo; - if (joseHeader.apu !== void 0) { - if (typeof joseHeader.apu !== "string") - throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); - partyUInfo = decode(joseHeader.apu); - } - if (joseHeader.apv !== void 0) { - if (typeof joseHeader.apv !== "string") - throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); - partyVInfo = decode(joseHeader.apv); - } - const sharedSecret = await deriveKey(epk, key, alg === "ECDH-ES" ? joseHeader.enc : alg, alg === "ECDH-ES" ? bitLength2(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); - if (alg === "ECDH-ES") - return sharedSecret; - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - return unwrap(alg.slice(-6), sharedSecret, encryptedKey); - } - case "RSA1_5": - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - return decrypt3(alg, key, encryptedKey); - } - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - if (typeof joseHeader.p2c !== "number") - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); - const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 1e4; - if (joseHeader.p2c > p2cLimit) - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); - if (typeof joseHeader.p2s !== "string") - throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); - return decrypt2(alg, key, encryptedKey, joseHeader.p2c, decode(joseHeader.p2s)); - } - case "A128KW": - case "A192KW": - case "A256KW": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - return unwrap(alg, key, encryptedKey); - } - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": { - if (encryptedKey === void 0) - throw new JWEInvalid("JWE Encrypted Key missing"); - if (typeof joseHeader.iv !== "string") - throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); - if (typeof joseHeader.tag !== "string") - throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); - const iv = decode(joseHeader.iv); - const tag = decode(joseHeader.tag); - return unwrap2(alg, key, encryptedKey, iv, tag); - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } - } - var decrypt_key_management_default = decryptKeyManagement; - - // dist/browser/lib/validate_crit.js - function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { - if (joseHeader.crit !== void 0 && protectedHeader.crit === void 0) { - throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); - } - if (!protectedHeader || protectedHeader.crit === void 0) { - return /* @__PURE__ */ new Set(); - } - if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) { - throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); - } - let recognized; - if (recognizedOption !== void 0) { - recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); - } else { - recognized = recognizedDefault; - } - for (const parameter of protectedHeader.crit) { - if (!recognized.has(parameter)) { - throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); - } - if (joseHeader[parameter] === void 0) { - throw new Err(`Extension Header Parameter "${parameter}" is missing`); - } else if (recognized.get(parameter) && protectedHeader[parameter] === void 0) { - throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); - } - } - return new Set(protectedHeader.crit); - } - var validate_crit_default = validateCrit; - - // dist/browser/lib/validate_algorithms.js - var validateAlgorithms = (option, algorithms) => { - if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) { - throw new TypeError(`"${option}" option must be an array of strings`); - } - if (!algorithms) { - return void 0; - } - return new Set(algorithms); - }; - var validate_algorithms_default = validateAlgorithms; - - // dist/browser/jwe/flattened/decrypt.js - async function flattenedDecrypt(jwe, key, options) { - var _a; - if (!isObject(jwe)) { - throw new JWEInvalid("Flattened JWE must be an object"); - } - if (jwe.protected === void 0 && jwe.header === void 0 && jwe.unprotected === void 0) { - throw new JWEInvalid("JOSE Header missing"); - } - if (typeof jwe.iv !== "string") { - throw new JWEInvalid("JWE Initialization Vector missing or incorrect type"); - } - if (typeof jwe.ciphertext !== "string") { - throw new JWEInvalid("JWE Ciphertext missing or incorrect type"); - } - if (typeof jwe.tag !== "string") { - throw new JWEInvalid("JWE Authentication Tag missing or incorrect type"); - } - if (jwe.protected !== void 0 && typeof jwe.protected !== "string") { - throw new JWEInvalid("JWE Protected Header incorrect type"); - } - if (jwe.encrypted_key !== void 0 && typeof jwe.encrypted_key !== "string") { - throw new JWEInvalid("JWE Encrypted Key incorrect type"); - } - if (jwe.aad !== void 0 && typeof jwe.aad !== "string") { - throw new JWEInvalid("JWE AAD incorrect type"); - } - if (jwe.header !== void 0 && !isObject(jwe.header)) { - throw new JWEInvalid("JWE Shared Unprotected Header incorrect type"); - } - if (jwe.unprotected !== void 0 && !isObject(jwe.unprotected)) { - throw new JWEInvalid("JWE Per-Recipient Unprotected Header incorrect type"); - } - let parsedProt; - if (jwe.protected) { - try { - const protectedHeader2 = decode(jwe.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader2)); - } catch (_b) { - throw new JWEInvalid("JWE Protected Header is invalid"); - } - } - if (!is_disjoint_default(parsedProt, jwe.header, jwe.unprotected)) { - throw new JWEInvalid("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint"); - } - const joseHeader = { - ...parsedProt, - ...jwe.header, - ...jwe.unprotected - }; - validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - if (joseHeader.zip !== void 0) { - if (!parsedProt || !parsedProt.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== "DEF") { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWEInvalid("missing JWE Algorithm (alg) in JWE Header"); - } - if (typeof enc !== "string" || !enc) { - throw new JWEInvalid("missing JWE Encryption Algorithm (enc) in JWE Header"); - } - const keyManagementAlgorithms = options && validate_algorithms_default("keyManagementAlgorithms", options.keyManagementAlgorithms); - const contentEncryptionAlgorithms = options && validate_algorithms_default("contentEncryptionAlgorithms", options.contentEncryptionAlgorithms); - if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { - throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); - } - let encryptedKey; - if (jwe.encrypted_key !== void 0) { - encryptedKey = decode(jwe.encrypted_key); - } - let resolvedKey = false; - if (typeof key === "function") { - key = await key(parsedProt, jwe); - resolvedKey = true; - } - let cek; - try { - cek = await decrypt_key_management_default(alg, key, encryptedKey, joseHeader, options); - } catch (err) { - if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { - throw err; - } - cek = cek_default(enc); - } - const iv = decode(jwe.iv); - const tag = decode(jwe.tag); - const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ""); - let additionalData; - if (jwe.aad !== void 0) { - additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(jwe.aad)); - } else { - additionalData = protectedHeader; - } - let plaintext = await decrypt_default(enc, cek, decode(jwe.ciphertext), iv, tag, additionalData); - if (joseHeader.zip === "DEF") { - plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); - } - const result = { plaintext }; - if (jwe.protected !== void 0) { - result.protectedHeader = parsedProt; - } - if (jwe.aad !== void 0) { - result.additionalAuthenticatedData = decode(jwe.aad); - } - if (jwe.unprotected !== void 0) { - result.sharedUnprotectedHeader = jwe.unprotected; - } - if (jwe.header !== void 0) { - result.unprotectedHeader = jwe.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; - } - - // dist/browser/jwe/compact/decrypt.js - async function compactDecrypt(jwe, key, options) { - if (jwe instanceof Uint8Array) { - jwe = decoder.decode(jwe); - } - if (typeof jwe !== "string") { - throw new JWEInvalid("Compact JWE must be a string or Uint8Array"); - } - const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length } = jwe.split("."); - if (length !== 5) { - throw new JWEInvalid("Invalid Compact JWE"); - } - const decrypted = await flattenedDecrypt({ - ciphertext, - iv: iv || void 0, - protected: protectedHeader || void 0, - tag: tag || void 0, - encrypted_key: encryptedKey || void 0 - }, key, options); - const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; - if (typeof key === "function") { - return { ...result, key: decrypted.key }; - } - return result; - } - - // dist/browser/jwe/general/decrypt.js - async function generalDecrypt(jwe, key, options) { - if (!isObject(jwe)) { - throw new JWEInvalid("General JWE must be an object"); - } - if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { - throw new JWEInvalid("JWE Recipients missing or incorrect type"); - } - if (!jwe.recipients.length) { - throw new JWEInvalid("JWE Recipients has no members"); - } - for (const recipient of jwe.recipients) { - try { - return await flattenedDecrypt({ - aad: jwe.aad, - ciphertext: jwe.ciphertext, - encrypted_key: recipient.encrypted_key, - header: recipient.header, - iv: jwe.iv, - protected: jwe.protected, - tag: jwe.tag, - unprotected: jwe.unprotected - }, key, options); - } catch (_a) { - } - } - throw new JWEDecryptionFailed(); - } - - // dist/browser/runtime/key_to_jwk.js - var keyToJWK = async (key) => { - if (key instanceof Uint8Array) { - return { - kty: "oct", - k: encode(key) - }; - } - if (!isCryptoKey(key)) { - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); - } - if (!key.extractable) { - throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK"); - } - const { ext, key_ops, alg, use, ...jwk } = await webcrypto_default.subtle.exportKey("jwk", key); - return jwk; - }; - var key_to_jwk_default = keyToJWK; - - // dist/browser/key/export.js - async function exportSPKI(key) { - return toSPKI(key); - } - async function exportPKCS8(key) { - return toPKCS8(key); - } - async function exportJWK(key) { - return key_to_jwk_default(key); - } - - // dist/browser/lib/encrypt_key_management.js - async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { - let encryptedKey; - let parameters; - let cek; - check_key_type_default(alg, key, "encrypt"); - switch (alg) { - case "dir": { - cek = key; - break; - } - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - if (!ecdhAllowed(key)) { - throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); - } - const { apu, apv } = providedParameters; - let { epk: ephemeralKey } = providedParameters; - ephemeralKey || (ephemeralKey = (await generateEpk(key)).privateKey); - const { x, y, crv, kty } = await exportJWK(ephemeralKey); - const sharedSecret = await deriveKey(key, ephemeralKey, alg === "ECDH-ES" ? enc : alg, alg === "ECDH-ES" ? bitLength2(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); - parameters = { epk: { x, crv, kty } }; - if (kty === "EC") - parameters.epk.y = y; - if (apu) - parameters.apu = encode(apu); - if (apv) - parameters.apv = encode(apv); - if (alg === "ECDH-ES") { - cek = sharedSecret; - break; - } - cek = providedCek || cek_default(enc); - const kwAlg = alg.slice(-6); - encryptedKey = await wrap(kwAlg, sharedSecret, cek); - break; - } - case "RSA1_5": - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": { - cek = providedCek || cek_default(enc); - encryptedKey = await encrypt2(alg, key, cek); - break; - } - case "PBES2-HS256+A128KW": - case "PBES2-HS384+A192KW": - case "PBES2-HS512+A256KW": { - cek = providedCek || cek_default(enc); - const { p2c, p2s: p2s2 } = providedParameters; - ({ encryptedKey, ...parameters } = await encrypt(alg, key, cek, p2c, p2s2)); - break; - } - case "A128KW": - case "A192KW": - case "A256KW": { - cek = providedCek || cek_default(enc); - encryptedKey = await wrap(alg, key, cek); - break; - } - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": { - cek = providedCek || cek_default(enc); - const { iv } = providedParameters; - ({ encryptedKey, ...parameters } = await wrap2(alg, key, cek, iv)); - break; - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } - return { cek, encryptedKey, parameters }; - } - var encrypt_key_management_default = encryptKeyManagement; - - // dist/browser/jwe/flattened/encrypt.js - var unprotected = Symbol(); - var FlattenedEncrypt = class { - constructor(plaintext) { - if (!(plaintext instanceof Uint8Array)) { - throw new TypeError("plaintext must be an instance of Uint8Array"); - } - this._plaintext = plaintext; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError("setKeyManagementParameters can only be called once"); - } - this._keyManagementParameters = parameters; - return this; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._sharedUnprotectedHeader) { - throw new TypeError("setSharedUnprotectedHeader can only be called once"); - } - this._sharedUnprotectedHeader = sharedUnprotectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError("setContentEncryptionKey can only be called once"); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError("setInitializationVector can only be called once"); - } - this._iv = iv; - return this; - } - async encrypt(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { - throw new JWEInvalid("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()"); - } - if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { - throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...this._sharedUnprotectedHeader - }; - validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== void 0) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== "DEF") { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (typeof enc !== "string" || !enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - let encryptedKey; - if (alg === "dir") { - if (this._cek) { - throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption"); - } - } else if (alg === "ECDH-ES") { - if (this._cek) { - throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement"); - } - } - let cek; - { - let parameters; - ({ cek, encryptedKey, parameters } = await encrypt_key_management_default(alg, enc, key, this._cek, this._keyManagementParameters)); - if (parameters) { - if (options && unprotected in options) { - if (!this._unprotectedHeader) { - this.setUnprotectedHeader(parameters); - } else { - this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; - } - } else { - if (!this._protectedHeader) { - this.setProtectedHeader(parameters); - } else { - this._protectedHeader = { ...this._protectedHeader, ...parameters }; - } - } - } - } - this._iv || (this._iv = iv_default(enc)); - let additionalData; - let protectedHeader; - let aadMember; - if (this._protectedHeader) { - protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); - } else { - protectedHeader = encoder.encode(""); - } - if (this._aad) { - aadMember = encode(this._aad); - additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(aadMember)); - } else { - additionalData = protectedHeader; - } - let ciphertext; - let tag; - if (joseHeader.zip === "DEF") { - const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); - ({ ciphertext, tag } = await encrypt_default(enc, deflated, cek, this._iv, additionalData)); - } else { - ({ ciphertext, tag } = await encrypt_default(enc, this._plaintext, cek, this._iv, additionalData)); - } - const jwe = { - ciphertext: encode(ciphertext), - iv: encode(this._iv), - tag: encode(tag) - }; - if (encryptedKey) { - jwe.encrypted_key = encode(encryptedKey); - } - if (aadMember) { - jwe.aad = aadMember; - } - if (this._protectedHeader) { - jwe.protected = decoder.decode(protectedHeader); - } - if (this._sharedUnprotectedHeader) { - jwe.unprotected = this._sharedUnprotectedHeader; - } - if (this._unprotectedHeader) { - jwe.header = this._unprotectedHeader; - } - return jwe; - } - }; - - // dist/browser/jwe/general/encrypt.js - var IndividualRecipient = class { - constructor(enc, key, options) { - this.parent = enc; - this.key = key; - this.options = options; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addRecipient(...args) { - return this.parent.addRecipient(...args); - } - encrypt(...args) { - return this.parent.encrypt(...args); - } - done() { - return this.parent; - } - }; - var GeneralEncrypt = class { - constructor(plaintext) { - this._recipients = []; - this._plaintext = plaintext; - } - addRecipient(key, options) { - const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); - this._recipients.push(recipient); - return recipient; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError("setSharedUnprotectedHeader can only be called once"); - } - this._unprotectedHeader = sharedUnprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - async encrypt(options) { - var _a, _b, _c; - if (!this._recipients.length) { - throw new JWEInvalid("at least one recipient must be added"); - } - options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; - if (this._recipients.length === 1) { - const [recipient] = this._recipients; - const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).encrypt(recipient.key, { ...recipient.options, ...options }); - let jwe2 = { - ciphertext: flattened.ciphertext, - iv: flattened.iv, - recipients: [{}], - tag: flattened.tag - }; - if (flattened.aad) - jwe2.aad = flattened.aad; - if (flattened.protected) - jwe2.protected = flattened.protected; - if (flattened.unprotected) - jwe2.unprotected = flattened.unprotected; - if (flattened.encrypted_key) - jwe2.recipients[0].encrypted_key = flattened.encrypted_key; - if (flattened.header) - jwe2.recipients[0].header = flattened.header; - return jwe2; - } - let enc; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { - throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader - }; - const { alg } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (alg === "dir" || alg === "ECDH-ES") { - throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); - } - if (typeof joseHeader.enc !== "string" || !joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - if (!enc) { - enc = joseHeader.enc; - } else if (enc !== joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); - } - validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), recipient.options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== void 0) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - } - } - const cek = cek_default(enc); - let jwe = { - ciphertext: "", - iv: "", - recipients: [], - tag: "" - }; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - const target = {}; - jwe.recipients.push(target); - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader - }; - const p2c = joseHeader.alg.startsWith("PBES2") ? 2048 + i : void 0; - if (i === 0) { - const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setContentEncryptionKey(cek).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).setKeyManagementParameters({ p2c }).encrypt(recipient.key, { - ...recipient.options, - ...options, - [unprotected]: true - }); - jwe.ciphertext = flattened.ciphertext; - jwe.iv = flattened.iv; - jwe.tag = flattened.tag; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - target.encrypted_key = flattened.encrypted_key; - if (flattened.header) - target.header = flattened.header; - continue; - } - const { encryptedKey, parameters } = await encrypt_key_management_default(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); - target.encrypted_key = encode(encryptedKey); - if (recipient.unprotectedHeader || parameters) - target.header = { ...recipient.unprotectedHeader, ...parameters }; - } - return jwe; - } - }; - - // dist/browser/runtime/subtle_dsa.js - function subtleDsa(alg, algorithm) { - const hash = `SHA-${alg.slice(-3)}`; - switch (alg) { - case "HS256": - case "HS384": - case "HS512": - return { hash, name: "HMAC" }; - case "PS256": - case "PS384": - case "PS512": - return { hash, name: "RSA-PSS", saltLength: alg.slice(-3) >> 3 }; - case "RS256": - case "RS384": - case "RS512": - return { hash, name: "RSASSA-PKCS1-v1_5" }; - case "ES256": - case "ES384": - case "ES512": - return { hash, name: "ECDSA", namedCurve: algorithm.namedCurve }; - case "EdDSA": - if (isCloudflareWorkers() && algorithm.name === "NODE-ED25519") { - return { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - } - return { name: algorithm.name }; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } - } - - // dist/browser/runtime/get_sign_verify_key.js - function getCryptoKey3(alg, key, usage) { - if (isCryptoKey(key)) { - checkSigCryptoKey(key, alg, usage); - return key; - } - if (key instanceof Uint8Array) { - if (!alg.startsWith("HS")) { - throw new TypeError(invalid_key_input_default(key, ...types)); - } - return webcrypto_default.subtle.importKey("raw", key, { hash: `SHA-${alg.slice(-3)}`, name: "HMAC" }, false, [usage]); - } - throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); - } - - // dist/browser/runtime/verify.js - var verify = async (alg, key, signature, data) => { - const cryptoKey = await getCryptoKey3(alg, key, "verify"); - check_key_length_default(alg, cryptoKey); - const algorithm = subtleDsa(alg, cryptoKey.algorithm); - try { - return await webcrypto_default.subtle.verify(algorithm, cryptoKey, signature, data); - } catch (_a) { - return false; - } - }; - var verify_default = verify; - - // dist/browser/jws/flattened/verify.js - async function flattenedVerify(jws, key, options) { - var _a; - if (!isObject(jws)) { - throw new JWSInvalid("Flattened JWS must be an object"); - } - if (jws.protected === void 0 && jws.header === void 0) { - throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); - } - if (jws.protected !== void 0 && typeof jws.protected !== "string") { - throw new JWSInvalid("JWS Protected Header incorrect type"); - } - if (jws.payload === void 0) { - throw new JWSInvalid("JWS Payload missing"); - } - if (typeof jws.signature !== "string") { - throw new JWSInvalid("JWS Signature missing or incorrect type"); - } - if (jws.header !== void 0 && !isObject(jws.header)) { - throw new JWSInvalid("JWS Unprotected Header incorrect type"); - } - let parsedProt = {}; - if (jws.protected) { - try { - const protectedHeader = decode(jws.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader)); - } catch (_b) { - throw new JWSInvalid("JWS Protected Header is invalid"); - } - } - if (!is_disjoint_default(parsedProt, jws.header)) { - throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); - } - const joseHeader = { - ...parsedProt, - ...jws.header - }; - const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - let b64 = true; - if (extensions.has("b64")) { - b64 = parsedProt.b64; - if (typeof b64 !== "boolean") { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - const algorithms = options && validate_algorithms_default("algorithms", options.algorithms); - if (algorithms && !algorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (b64) { - if (typeof jws.payload !== "string") { - throw new JWSInvalid("JWS Payload must be a string"); - } - } else if (typeof jws.payload !== "string" && !(jws.payload instanceof Uint8Array)) { - throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance"); - } - let resolvedKey = false; - if (typeof key === "function") { - key = await key(parsedProt, jws); - resolvedKey = true; - } - check_key_type_default(alg, key, "verify"); - const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ""), encoder.encode("."), typeof jws.payload === "string" ? encoder.encode(jws.payload) : jws.payload); - const signature = decode(jws.signature); - const verified = await verify_default(alg, key, signature, data); - if (!verified) { - throw new JWSSignatureVerificationFailed(); - } - let payload; - if (b64) { - payload = decode(jws.payload); - } else if (typeof jws.payload === "string") { - payload = encoder.encode(jws.payload); - } else { - payload = jws.payload; - } - const result = { payload }; - if (jws.protected !== void 0) { - result.protectedHeader = parsedProt; - } - if (jws.header !== void 0) { - result.unprotectedHeader = jws.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; - } - - // dist/browser/jws/compact/verify.js - async function compactVerify(jws, key, options) { - if (jws instanceof Uint8Array) { - jws = decoder.decode(jws); - } - if (typeof jws !== "string") { - throw new JWSInvalid("Compact JWS must be a string or Uint8Array"); - } - const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split("."); - if (length !== 3) { - throw new JWSInvalid("Invalid Compact JWS"); - } - const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); - const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; - if (typeof key === "function") { - return { ...result, key: verified.key }; - } - return result; - } - - // dist/browser/jws/general/verify.js - async function generalVerify(jws, key, options) { - if (!isObject(jws)) { - throw new JWSInvalid("General JWS must be an object"); - } - if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { - throw new JWSInvalid("JWS Signatures missing or incorrect type"); - } - for (const signature of jws.signatures) { - try { - return await flattenedVerify({ - header: signature.header, - payload: jws.payload, - protected: signature.protected, - signature: signature.signature - }, key, options); - } catch (_a) { - } - } - throw new JWSSignatureVerificationFailed(); - } - - // dist/browser/lib/epoch.js - var epoch_default = (date) => Math.floor(date.getTime() / 1e3); - - // dist/browser/lib/secs.js - var minute = 60; - var hour = minute * 60; - var day = hour * 24; - var week = day * 7; - var year = day * 365.25; - var REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; - var secs_default = (str) => { - const matched = REGEX.exec(str); - if (!matched) { - throw new TypeError("Invalid time period format"); - } - const value = parseFloat(matched[1]); - const unit = matched[2].toLowerCase(); - switch (unit) { - case "sec": - case "secs": - case "second": - case "seconds": - case "s": - return Math.round(value); - case "minute": - case "minutes": - case "min": - case "mins": - case "m": - return Math.round(value * minute); - case "hour": - case "hours": - case "hr": - case "hrs": - case "h": - return Math.round(value * hour); - case "day": - case "days": - case "d": - return Math.round(value * day); - case "week": - case "weeks": - case "w": - return Math.round(value * week); - default: - return Math.round(value * year); - } - }; - - // dist/browser/lib/jwt_claims_set.js - var normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ""); - var checkAudiencePresence = (audPayload, audOption) => { - if (typeof audPayload === "string") { - return audOption.includes(audPayload); - } - if (Array.isArray(audPayload)) { - return audOption.some(Set.prototype.has.bind(new Set(audPayload))); - } - return false; - }; - var jwt_claims_set_default = (protectedHeader, encodedPayload, options = {}) => { - const { typ } = options; - if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { - throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', "typ", "check_failed"); - } - let payload; - try { - payload = JSON.parse(decoder.decode(encodedPayload)); - } catch (_a) { - } - if (!isObject(payload)) { - throw new JWTInvalid("JWT Claims Set must be a top-level JSON object"); - } - const { issuer } = options; - if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { - throw new JWTClaimValidationFailed('unexpected "iss" claim value', "iss", "check_failed"); - } - const { subject } = options; - if (subject && payload.sub !== subject) { - throw new JWTClaimValidationFailed('unexpected "sub" claim value', "sub", "check_failed"); - } - const { audience } = options; - if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) { - throw new JWTClaimValidationFailed('unexpected "aud" claim value', "aud", "check_failed"); - } - let tolerance; - switch (typeof options.clockTolerance) { - case "string": - tolerance = secs_default(options.clockTolerance); - break; - case "number": - tolerance = options.clockTolerance; - break; - case "undefined": - tolerance = 0; - break; - default: - throw new TypeError("Invalid clockTolerance option type"); - } - const { currentDate } = options; - const now = epoch_default(currentDate || /* @__PURE__ */ new Date()); - if ((payload.iat !== void 0 || options.maxTokenAge) && typeof payload.iat !== "number") { - throw new JWTClaimValidationFailed('"iat" claim must be a number', "iat", "invalid"); - } - if (payload.nbf !== void 0) { - if (typeof payload.nbf !== "number") { - throw new JWTClaimValidationFailed('"nbf" claim must be a number', "nbf", "invalid"); - } - if (payload.nbf > now + tolerance) { - throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', "nbf", "check_failed"); - } - } - if (payload.exp !== void 0) { - if (typeof payload.exp !== "number") { - throw new JWTClaimValidationFailed('"exp" claim must be a number', "exp", "invalid"); - } - if (payload.exp <= now - tolerance) { - throw new JWTExpired('"exp" claim timestamp check failed', "exp", "check_failed"); - } - } - if (options.maxTokenAge) { - const age = now - payload.iat; - const max = typeof options.maxTokenAge === "number" ? options.maxTokenAge : secs_default(options.maxTokenAge); - if (age - tolerance > max) { - throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', "iat", "check_failed"); - } - if (age < 0 - tolerance) { - throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', "iat", "check_failed"); - } - } - return payload; - }; - - // dist/browser/jwt/verify.js - async function jwtVerify(jwt, key, options) { - var _a; - const verified = await compactVerify(jwt, key, options); - if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes("b64")) && verified.protectedHeader.b64 === false) { - throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); - } - const payload = jwt_claims_set_default(verified.protectedHeader, verified.payload, options); - const result = { payload, protectedHeader: verified.protectedHeader }; - if (typeof key === "function") { - return { ...result, key: verified.key }; - } - return result; - } - - // dist/browser/jwt/decrypt.js - async function jwtDecrypt(jwt, key, options) { - const decrypted = await compactDecrypt(jwt, key, options); - const payload = jwt_claims_set_default(decrypted.protectedHeader, decrypted.plaintext, options); - const { protectedHeader } = decrypted; - if (protectedHeader.iss !== void 0 && protectedHeader.iss !== payload.iss) { - throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', "iss", "mismatch"); - } - if (protectedHeader.sub !== void 0 && protectedHeader.sub !== payload.sub) { - throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', "sub", "mismatch"); - } - if (protectedHeader.aud !== void 0 && JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { - throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', "aud", "mismatch"); - } - const result = { payload, protectedHeader }; - if (typeof key === "function") { - return { ...result, key: decrypted.key }; - } - return result; - } - - // dist/browser/jwe/compact/encrypt.js - var CompactEncrypt = class { - constructor(plaintext) { - this._flattened = new FlattenedEncrypt(plaintext); - } - setContentEncryptionKey(cek) { - this._flattened.setContentEncryptionKey(cek); - return this; - } - setInitializationVector(iv) { - this._flattened.setInitializationVector(iv); - return this; - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - setKeyManagementParameters(parameters) { - this._flattened.setKeyManagementParameters(parameters); - return this; - } - async encrypt(key, options) { - const jwe = await this._flattened.encrypt(key, options); - return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join("."); - } - }; - - // dist/browser/runtime/sign.js - var sign = async (alg, key, data) => { - const cryptoKey = await getCryptoKey3(alg, key, "sign"); - check_key_length_default(alg, cryptoKey); - const signature = await webcrypto_default.subtle.sign(subtleDsa(alg, cryptoKey.algorithm), cryptoKey, data); - return new Uint8Array(signature); - }; - var sign_default = sign; - - // dist/browser/jws/flattened/sign.js - var FlattenedSign = class { - constructor(payload) { - if (!(payload instanceof Uint8Array)) { - throw new TypeError("payload must be an instance of Uint8Array"); - } - this._payload = payload; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - async sign(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader) { - throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()"); - } - if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader)) { - throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader - }; - const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - let b64 = true; - if (extensions.has("b64")) { - b64 = this._protectedHeader.b64; - if (typeof b64 !== "boolean") { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== "string" || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - check_key_type_default(alg, key, "sign"); - let payload = this._payload; - if (b64) { - payload = encoder.encode(encode(payload)); - } - let protectedHeader; - if (this._protectedHeader) { - protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); - } else { - protectedHeader = encoder.encode(""); - } - const data = concat(protectedHeader, encoder.encode("."), payload); - const signature = await sign_default(alg, key, data); - const jws = { - signature: encode(signature), - payload: "" - }; - if (b64) { - jws.payload = decoder.decode(payload); - } - if (this._unprotectedHeader) { - jws.header = this._unprotectedHeader; - } - if (this._protectedHeader) { - jws.protected = decoder.decode(protectedHeader); - } - return jws; - } - }; - - // dist/browser/jws/compact/sign.js - var CompactSign = class { - constructor(payload) { - this._flattened = new FlattenedSign(payload); - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - async sign(key, options) { - const jws = await this._flattened.sign(key, options); - if (jws.payload === void 0) { - throw new TypeError("use the flattened module for creating JWS with b64: false"); - } - return `${jws.protected}.${jws.payload}.${jws.signature}`; - } - }; - - // dist/browser/jws/general/sign.js - var IndividualSignature = class { - constructor(sig, key, options) { - this.parent = sig; - this.key = key; - this.options = options; - } - setProtectedHeader(protectedHeader) { - if (this.protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this.protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError("setUnprotectedHeader can only be called once"); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addSignature(...args) { - return this.parent.addSignature(...args); - } - sign(...args) { - return this.parent.sign(...args); - } - done() { - return this.parent; - } - }; - var GeneralSign = class { - constructor(payload) { - this._signatures = []; - this._payload = payload; - } - addSignature(key, options) { - const signature = new IndividualSignature(this, key, options); - this._signatures.push(signature); - return signature; - } - async sign() { - if (!this._signatures.length) { - throw new JWSInvalid("at least one signature must be added"); - } - const jws = { - signatures: [], - payload: "" - }; - for (let i = 0; i < this._signatures.length; i++) { - const signature = this._signatures[i]; - const flattened = new FlattenedSign(this._payload); - flattened.setProtectedHeader(signature.protectedHeader); - flattened.setUnprotectedHeader(signature.unprotectedHeader); - const { payload, ...rest } = await flattened.sign(signature.key, signature.options); - if (i === 0) { - jws.payload = payload; - } else if (jws.payload !== payload) { - throw new JWSInvalid("inconsistent use of JWS Unencoded Payload Option (RFC7797)"); - } - jws.signatures.push(rest); - } - return jws; - } - }; - - // dist/browser/jwt/produce.js - var ProduceJWT = class { - constructor(payload) { - if (!isObject(payload)) { - throw new TypeError("JWT Claims Set MUST be an object"); - } - this._payload = payload; - } - setIssuer(issuer) { - this._payload = { ...this._payload, iss: issuer }; - return this; - } - setSubject(subject) { - this._payload = { ...this._payload, sub: subject }; - return this; - } - setAudience(audience) { - this._payload = { ...this._payload, aud: audience }; - return this; - } - setJti(jwtId) { - this._payload = { ...this._payload, jti: jwtId }; - return this; - } - setNotBefore(input) { - if (typeof input === "number") { - this._payload = { ...this._payload, nbf: input }; - } else { - this._payload = { ...this._payload, nbf: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; - } - return this; - } - setExpirationTime(input) { - if (typeof input === "number") { - this._payload = { ...this._payload, exp: input }; - } else { - this._payload = { ...this._payload, exp: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; - } - return this; - } - setIssuedAt(input) { - if (typeof input === "undefined") { - this._payload = { ...this._payload, iat: epoch_default(/* @__PURE__ */ new Date()) }; - } else { - this._payload = { ...this._payload, iat: input }; - } - return this; - } - }; - - // dist/browser/jwt/sign.js - var SignJWT = class extends ProduceJWT { - setProtectedHeader(protectedHeader) { - this._protectedHeader = protectedHeader; - return this; - } - async sign(key, options) { - var _a; - const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); - sig.setProtectedHeader(this._protectedHeader); - if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && this._protectedHeader.crit.includes("b64") && this._protectedHeader.b64 === false) { - throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); - } - return sig.sign(key, options); - } - }; - - // dist/browser/jwt/encrypt.js - var EncryptJWT = class extends ProduceJWT { - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError("setProtectedHeader can only be called once"); - } - this._protectedHeader = protectedHeader; - return this; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError("setKeyManagementParameters can only be called once"); - } - this._keyManagementParameters = parameters; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError("setContentEncryptionKey can only be called once"); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError("setInitializationVector can only be called once"); - } - this._iv = iv; - return this; - } - replicateIssuerAsHeader() { - this._replicateIssuerAsHeader = true; - return this; - } - replicateSubjectAsHeader() { - this._replicateSubjectAsHeader = true; - return this; - } - replicateAudienceAsHeader() { - this._replicateAudienceAsHeader = true; - return this; - } - async encrypt(key, options) { - const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); - if (this._replicateIssuerAsHeader) { - this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; - } - if (this._replicateSubjectAsHeader) { - this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; - } - if (this._replicateAudienceAsHeader) { - this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; - } - enc.setProtectedHeader(this._protectedHeader); - if (this._iv) { - enc.setInitializationVector(this._iv); - } - if (this._cek) { - enc.setContentEncryptionKey(this._cek); - } - if (this._keyManagementParameters) { - enc.setKeyManagementParameters(this._keyManagementParameters); - } - return enc.encrypt(key, options); - } - }; - - // dist/browser/jwk/thumbprint.js - var check = (value, description) => { - if (typeof value !== "string" || !value) { - throw new JWKInvalid(`${description} missing or invalid`); - } - }; - async function calculateJwkThumbprint(jwk, digestAlgorithm) { - if (!isObject(jwk)) { - throw new TypeError("JWK must be an object"); - } - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; - if (digestAlgorithm !== "sha256" && digestAlgorithm !== "sha384" && digestAlgorithm !== "sha512") { - throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); - } - let components; - switch (jwk.kty) { - case "EC": - check(jwk.crv, '"crv" (Curve) Parameter'); - check(jwk.x, '"x" (X Coordinate) Parameter'); - check(jwk.y, '"y" (Y Coordinate) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; - break; - case "OKP": - check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); - check(jwk.x, '"x" (Public Key) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; - break; - case "RSA": - check(jwk.e, '"e" (Exponent) Parameter'); - check(jwk.n, '"n" (Modulus) Parameter'); - components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; - break; - case "oct": - check(jwk.k, '"k" (Key Value) Parameter'); - components = { k: jwk.k, kty: jwk.kty }; - break; - default: - throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); - } - const data = encoder.encode(JSON.stringify(components)); - return encode(await digest_default(digestAlgorithm, data)); - } - async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; - const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); - return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; - } - - // dist/browser/jwk/embedded.js - async function EmbeddedJWK(protectedHeader, token) { - const joseHeader = { - ...protectedHeader, - ...token.header - }; - if (!isObject(joseHeader.jwk)) { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); - } - const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); - if (key instanceof Uint8Array || key.type !== "public") { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); - } - return key; - } - - // dist/browser/jwks/local.js - function getKtyFromAlg(alg) { - switch (typeof alg === "string" && alg.slice(0, 2)) { - case "RS": - case "PS": - return "RSA"; - case "ES": - return "EC"; - case "Ed": - return "OKP"; - default: - throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); - } - } - function isJWKSLike(jwks) { - return jwks && typeof jwks === "object" && Array.isArray(jwks.keys) && jwks.keys.every(isJWKLike); - } - function isJWKLike(key) { - return isObject(key); - } - function clone(obj) { - if (typeof structuredClone === "function") { - return structuredClone(obj); - } - return JSON.parse(JSON.stringify(obj)); - } - var LocalJWKSet = class { - constructor(jwks) { - this._cached = /* @__PURE__ */ new WeakMap(); - if (!isJWKSLike(jwks)) { - throw new JWKSInvalid("JSON Web Key Set malformed"); - } - this._jwks = clone(jwks); - } - async getKey(protectedHeader, token) { - const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; - const kty = getKtyFromAlg(alg); - const candidates = this._jwks.keys.filter((jwk2) => { - let candidate = kty === jwk2.kty; - if (candidate && typeof kid === "string") { - candidate = kid === jwk2.kid; - } - if (candidate && typeof jwk2.alg === "string") { - candidate = alg === jwk2.alg; - } - if (candidate && typeof jwk2.use === "string") { - candidate = jwk2.use === "sig"; - } - if (candidate && Array.isArray(jwk2.key_ops)) { - candidate = jwk2.key_ops.includes("verify"); - } - if (candidate && alg === "EdDSA") { - candidate = jwk2.crv === "Ed25519" || jwk2.crv === "Ed448"; - } - if (candidate) { - switch (alg) { - case "ES256": - candidate = jwk2.crv === "P-256"; - break; - case "ES256K": - candidate = jwk2.crv === "secp256k1"; - break; - case "ES384": - candidate = jwk2.crv === "P-384"; - break; - case "ES512": - candidate = jwk2.crv === "P-521"; - break; - } - } - return candidate; - }); - const { 0: jwk, length } = candidates; - if (length === 0) { - throw new JWKSNoMatchingKey(); - } else if (length !== 1) { - const error = new JWKSMultipleMatchingKeys(); - const { _cached } = this; - error[Symbol.asyncIterator] = async function* () { - for (const jwk2 of candidates) { - try { - yield await importWithAlgCache(_cached, jwk2, alg); - } catch (_a) { - continue; - } - } - }; - throw error; - } - return importWithAlgCache(this._cached, jwk, alg); - } - }; - async function importWithAlgCache(cache, jwk, alg) { - const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); - if (cached[alg] === void 0) { - const keyObject = await importJWK({ ...jwk, ext: true }, alg); - if (keyObject.type !== "public") { - throw new JWKSInvalid("JSON Web Key Set members must be public keys"); - } - cached[alg] = keyObject; - } - return cached[alg]; - } - function createLocalJWKSet(jwks) { - return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); - } - - // dist/browser/runtime/fetch_jwks.js - var fetchJwks = async (url, timeout, options) => { - let controller; - let id; - let timedOut = false; - if (typeof AbortController === "function") { - controller = new AbortController(); - id = setTimeout(() => { - timedOut = true; - controller.abort(); - }, timeout); - } - const response = await fetch(url.href, { - signal: controller ? controller.signal : void 0, - redirect: "manual", - headers: options.headers - }).catch((err) => { - if (timedOut) - throw new JWKSTimeout(); - throw err; - }); - if (id !== void 0) - clearTimeout(id); - if (response.status !== 200) { - throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response"); - } - try { - return await response.json(); - } catch (_a) { - throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON"); - } - }; - var fetch_jwks_default = fetchJwks; - - // dist/browser/jwks/remote.js - var RemoteJWKSet = class extends LocalJWKSet { - constructor(url, options) { - super({ keys: [] }); - this._jwks = void 0; - if (!(url instanceof URL)) { - throw new TypeError("url must be an instance of URL"); - } - this._url = new URL(url.href); - this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; - this._timeoutDuration = typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === "number" ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5e3; - this._cooldownDuration = typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === "number" ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 3e4; - this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === "number" ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 6e5; - } - coolingDown() { - return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cooldownDuration : false; - } - fresh() { - return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cacheMaxAge : false; - } - async getKey(protectedHeader, token) { - if (!this._jwks || !this.fresh()) { - await this.reload(); - } - try { - return await super.getKey(protectedHeader, token); - } catch (err) { - if (err instanceof JWKSNoMatchingKey) { - if (this.coolingDown() === false) { - await this.reload(); - return super.getKey(protectedHeader, token); - } - } - throw err; - } - } - async reload() { - if (this._pendingFetch && isCloudflareWorkers()) { - return new Promise((resolve) => { - const isDone = () => { - if (this._pendingFetch === void 0) { - resolve(); - } else { - setTimeout(isDone, 5); - } - }; - isDone(); - }); - } - if (!this._pendingFetch) { - this._pendingFetch = fetch_jwks_default(this._url, this._timeoutDuration, this._options).then((json) => { - if (!isJWKSLike(json)) { - throw new JWKSInvalid("JSON Web Key Set malformed"); - } - this._jwks = { keys: json.keys }; - this._jwksTimestamp = Date.now(); - this._pendingFetch = void 0; - }).catch((err) => { - this._pendingFetch = void 0; - throw err; - }); - } - await this._pendingFetch; - } - }; - function createRemoteJWKSet(url, options) { - return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); - } - - // dist/browser/jwt/unsecured.js - var UnsecuredJWT = class extends ProduceJWT { - encode() { - const header = encode(JSON.stringify({ alg: "none" })); - const payload = encode(JSON.stringify(this._payload)); - return `${header}.${payload}.`; - } - static decode(jwt, options) { - if (typeof jwt !== "string") { - throw new JWTInvalid("Unsecured JWT must be a string"); - } - const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split("."); - if (length !== 3 || signature !== "") { - throw new JWTInvalid("Invalid Unsecured JWT"); - } - let header; - try { - header = JSON.parse(decoder.decode(decode(encodedHeader))); - if (header.alg !== "none") - throw new Error(); - } catch (_a) { - throw new JWTInvalid("Invalid Unsecured JWT"); - } - const payload = jwt_claims_set_default(header, decode(encodedPayload), options); - return { payload, header }; - } - }; - - // dist/browser/util/base64url.js - var base64url_exports2 = {}; - __export(base64url_exports2, { - decode: () => decode2, - encode: () => encode2 - }); - var encode2 = encode; - var decode2 = decode; - - // dist/browser/util/decode_protected_header.js - function decodeProtectedHeader(token) { - let protectedB64u; - if (typeof token === "string") { - const parts = token.split("."); - if (parts.length === 3 || parts.length === 5) { - [protectedB64u] = parts; - } - } else if (typeof token === "object" && token) { - if ("protected" in token) { - protectedB64u = token.protected; - } else { - throw new TypeError("Token does not contain a Protected Header"); - } - } - try { - if (typeof protectedB64u !== "string" || !protectedB64u) { - throw new Error(); - } - const result = JSON.parse(decoder.decode(decode2(protectedB64u))); - if (!isObject(result)) { - throw new Error(); - } - return result; - } catch (_a) { - throw new TypeError("Invalid Token or Protected Header formatting"); - } - } - - // dist/browser/util/decode_jwt.js - function decodeJwt(jwt) { - if (typeof jwt !== "string") - throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string"); - const { 1: payload, length } = jwt.split("."); - if (length === 5) - throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded"); - if (length !== 3) - throw new JWTInvalid("Invalid JWT"); - if (!payload) - throw new JWTInvalid("JWTs must contain a payload"); - let decoded; - try { - decoded = decode2(payload); - } catch (_a) { - throw new JWTInvalid("Failed to parse the base64url encoded payload"); - } - let result; - try { - result = JSON.parse(decoder.decode(decoded)); - } catch (_b) { - throw new JWTInvalid("Failed to parse the decoded payload as JSON"); - } - if (!isObject(result)) - throw new JWTInvalid("Invalid JWT Claims Set"); - return result; - } - - // dist/browser/runtime/generate.js - async function generateSecret(alg, options) { - var _a; - let length; - let algorithm; - let keyUsages; - switch (alg) { - case "HS256": - case "HS384": - case "HS512": - length = parseInt(alg.slice(-3), 10); - algorithm = { name: "HMAC", hash: `SHA-${length}`, length }; - keyUsages = ["sign", "verify"]; - break; - case "A128CBC-HS256": - case "A192CBC-HS384": - case "A256CBC-HS512": - length = parseInt(alg.slice(-3), 10); - return random_default(new Uint8Array(length >> 3)); - case "A128KW": - case "A192KW": - case "A256KW": - length = parseInt(alg.slice(1, 4), 10); - algorithm = { name: "AES-KW", length }; - keyUsages = ["wrapKey", "unwrapKey"]; - break; - case "A128GCMKW": - case "A192GCMKW": - case "A256GCMKW": - case "A128GCM": - case "A192GCM": - case "A256GCM": - length = parseInt(alg.slice(1, 4), 10); - algorithm = { name: "AES-GCM", length }; - keyUsages = ["encrypt", "decrypt"]; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - return webcrypto_default.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); - } - function getModulusLengthOption(options) { - var _a; - const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; - if (typeof modulusLength !== "number" || modulusLength < 2048) { - throw new JOSENotSupported("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used"); - } - return modulusLength; - } - async function generateKeyPair(alg, options) { - var _a, _b, _c, _d; - let algorithm; - let keyUsages; - switch (alg) { - case "PS256": - case "PS384": - case "PS512": - algorithm = { - name: "RSA-PSS", - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: getModulusLengthOption(options) - }; - keyUsages = ["sign", "verify"]; - break; - case "RS256": - case "RS384": - case "RS512": - algorithm = { - name: "RSASSA-PKCS1-v1_5", - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: getModulusLengthOption(options) - }; - keyUsages = ["sign", "verify"]; - break; - case "RSA-OAEP": - case "RSA-OAEP-256": - case "RSA-OAEP-384": - case "RSA-OAEP-512": - algorithm = { - name: "RSA-OAEP", - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: getModulusLengthOption(options) - }; - keyUsages = ["decrypt", "unwrapKey", "encrypt", "wrapKey"]; - break; - case "ES256": - algorithm = { name: "ECDSA", namedCurve: "P-256" }; - keyUsages = ["sign", "verify"]; - break; - case "ES384": - algorithm = { name: "ECDSA", namedCurve: "P-384" }; - keyUsages = ["sign", "verify"]; - break; - case "ES512": - algorithm = { name: "ECDSA", namedCurve: "P-521" }; - keyUsages = ["sign", "verify"]; - break; - case "EdDSA": - keyUsages = ["sign", "verify"]; - const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : "Ed25519"; - switch (crv) { - case "Ed25519": - case "Ed448": - algorithm = { name: crv }; - break; - default: - throw new JOSENotSupported("Invalid or unsupported crv option provided"); - } - break; - case "ECDH-ES": - case "ECDH-ES+A128KW": - case "ECDH-ES+A192KW": - case "ECDH-ES+A256KW": { - keyUsages = ["deriveKey", "deriveBits"]; - const crv2 = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : "P-256"; - switch (crv2) { - case "P-256": - case "P-384": - case "P-521": { - algorithm = { name: "ECDH", namedCurve: crv2 }; - break; - } - case "X25519": - case "X448": - algorithm = { name: crv2 }; - break; - default: - throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448"); - } - break; - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - try { - return await webcrypto_default.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages); - } catch (err) { - if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { - algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; - return await webcrypto_default.subtle.generateKey(algorithm, (_d = options === null || options === void 0 ? void 0 : options.extractable) !== null && _d !== void 0 ? _d : false, keyUsages); - } - throw err; - } - } - - // dist/browser/key/generate_key_pair.js - async function generateKeyPair2(alg, options) { - return generateKeyPair(alg, options); - } - - // dist/browser/key/generate_secret.js - async function generateSecret2(alg, options) { - return generateSecret(alg, options); - } - - exports.CompactEncrypt = CompactEncrypt; - exports.CompactSign = CompactSign; - exports.EmbeddedJWK = EmbeddedJWK; - exports.EncryptJWT = EncryptJWT; - exports.FlattenedEncrypt = FlattenedEncrypt; - exports.FlattenedSign = FlattenedSign; - exports.GeneralEncrypt = GeneralEncrypt; - exports.GeneralSign = GeneralSign; - exports.SignJWT = SignJWT; - exports.UnsecuredJWT = UnsecuredJWT; - exports.base64url = base64url_exports2; - exports.calculateJwkThumbprint = calculateJwkThumbprint; - exports.calculateJwkThumbprintUri = calculateJwkThumbprintUri; - exports.compactDecrypt = compactDecrypt; - exports.compactVerify = compactVerify; - exports.createLocalJWKSet = createLocalJWKSet; - exports.createRemoteJWKSet = createRemoteJWKSet; - exports.decodeJwt = decodeJwt; - exports.decodeProtectedHeader = decodeProtectedHeader; - exports.errors = errors_exports; - exports.exportJWK = exportJWK; - exports.exportPKCS8 = exportPKCS8; - exports.exportSPKI = exportSPKI; - exports.flattenedDecrypt = flattenedDecrypt; - exports.flattenedVerify = flattenedVerify; - exports.generalDecrypt = generalDecrypt; - exports.generalVerify = generalVerify; - exports.generateKeyPair = generateKeyPair2; - exports.generateSecret = generateSecret2; - exports.importJWK = importJWK; - exports.importPKCS8 = importPKCS8; - exports.importSPKI = importSPKI; - exports.importX509 = importX509; - exports.jwtDecrypt = jwtDecrypt; - exports.jwtVerify = jwtVerify; - -})); diff --git a/dist/browser/index.umd.min.js b/dist/browser/index.umd.min.js deleted file mode 100644 index cccfe2676d..0000000000 --- a/dist/browser/index.umd.min.js +++ /dev/null @@ -1,5 +0,0 @@ -(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports):typeof define==='function'&&define.amd?define(['exports'],f):(g=typeof globalThis!=='undefined'?globalThis:g||self,f(g.jose={}));})(this,(function(exports){'use strict';var qt=Object.defineProperty;var ct=(e,t)=>{for(var r in t)qt(e,r,{get:t[r],enumerable:!0});};var f=crypto,b=e=>e instanceof CryptoKey;var Zt=async(e,t)=>{let r=`SHA-${e.slice(-3)}`;return new Uint8Array(await f.subtle.digest(r,t))},Ke=Zt;var E=new TextEncoder,v=new TextDecoder,xe=2**32;function W(...e){let t=e.reduce((o,{length:a})=>o+a,0),r=new Uint8Array(t),n=0;return e.forEach(o=>{r.set(o,n),n+=o.length;}),r}function dt(e,t){return W(E.encode(e),new Uint8Array([0]),t)}function ke(e,t,r){if(t<0||t>=xe)throw new RangeError(`value must be >= 0 and <= ${xe-1}. Received ${t}`);e.set([t>>>24,t>>>16,t>>>8,t&255],r);}function He(e){let t=Math.floor(e/xe),r=e%xe,n=new Uint8Array(8);return ke(n,t,0),ke(n,r,4),n}function Ce(e){let t=new Uint8Array(4);return ke(t,e),t}function Pe(e){return W(Ce(e.length),e)}async function pt(e,t,r){let n=Math.ceil((t>>3)/32),o=new Uint8Array(n*32);for(let a=0;a>3)}var We=e=>{let t=e;typeof t=="string"&&(t=E.encode(t));let r=32768,n=[];for(let o=0;oWe(e).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_"),Be=e=>{let t=atob(e),r=new Uint8Array(t.length);for(let n=0;n{let t=e;t instanceof Uint8Array&&(t=v.decode(t)),t=t.replace(/-/g,"+").replace(/_/g,"/").replace(/\s/g,"");try{return Be(t)}catch(r){throw new TypeError("The input to be decoded is not correctly encoded.")}};var ft={};ct(ft,{JOSEAlgNotAllowed:()=>B,JOSEError:()=>C,JOSENotSupported:()=>l,JWEDecryptionFailed:()=>M,JWEInvalid:()=>u,JWKInvalid:()=>pe,JWKSInvalid:()=>L,JWKSMultipleMatchingKeys:()=>ue,JWKSNoMatchingKey:()=>q,JWKSTimeout:()=>fe,JWSInvalid:()=>h,JWSSignatureVerificationFailed:()=>Z,JWTClaimValidationFailed:()=>J,JWTExpired:()=>re,JWTInvalid:()=>H});var C=class extends Error{static get code(){return "ERR_JOSE_GENERIC"}constructor(t){var r;super(t),this.code="ERR_JOSE_GENERIC",this.name=this.constructor.name,(r=Error.captureStackTrace)===null||r===void 0||r.call(Error,this,this.constructor);}},J=class extends C{static get code(){return "ERR_JWT_CLAIM_VALIDATION_FAILED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_CLAIM_VALIDATION_FAILED",this.claim=r,this.reason=n;}},re=class extends C{static get code(){return "ERR_JWT_EXPIRED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_EXPIRED",this.claim=r,this.reason=n;}},B=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_ALG_NOT_ALLOWED";}static get code(){return "ERR_JOSE_ALG_NOT_ALLOWED"}},l=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_NOT_SUPPORTED";}static get code(){return "ERR_JOSE_NOT_SUPPORTED"}},M=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_DECRYPTION_FAILED",this.message="decryption operation failed";}static get code(){return "ERR_JWE_DECRYPTION_FAILED"}},u=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_INVALID";}static get code(){return "ERR_JWE_INVALID"}},h=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_INVALID";}static get code(){return "ERR_JWS_INVALID"}},H=class extends C{constructor(){super(...arguments),this.code="ERR_JWT_INVALID";}static get code(){return "ERR_JWT_INVALID"}},pe=class extends C{constructor(){super(...arguments),this.code="ERR_JWK_INVALID";}static get code(){return "ERR_JWK_INVALID"}},L=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_INVALID";}static get code(){return "ERR_JWKS_INVALID"}},q=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_NO_MATCHING_KEY",this.message="no applicable key found in the JSON Web Key Set";}static get code(){return "ERR_JWKS_NO_MATCHING_KEY"}},ue=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_MULTIPLE_MATCHING_KEYS",this.message="multiple matching keys found in the JSON Web Key Set";}static get code(){return "ERR_JWKS_MULTIPLE_MATCHING_KEYS"}},fe=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_TIMEOUT",this.message="request timed out";}static get code(){return "ERR_JWKS_TIMEOUT"}},Z=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED",this.message="signature verification failed";}static get code(){return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"}};var $=f.getRandomValues.bind(f);function Le(e){switch(e){case"A128GCM":case"A128GCMKW":case"A192GCM":case"A192GCMKW":case"A256GCM":case"A256GCMKW":return 96;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return 128;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var Je=e=>$(new Uint8Array(Le(e)>>3));var Qt=(e,t)=>{if(t.length<<3!==Le(e))throw new u("Invalid Initialization Vector length")},Te=Qt;var jt=(e,t)=>{let r=e.byteLength<<3;if(r!==t)throw new u(`Invalid Content Encryption Key length. Expected ${t} bits, got ${r} bits`)},ne=jt;var er=(e,t)=>{if(!(e instanceof Uint8Array))throw new TypeError("First argument must be a buffer");if(!(t instanceof Uint8Array))throw new TypeError("Second argument must be a buffer");if(e.length!==t.length)throw new TypeError("Input buffers must have the same length");let r=e.length,n=0,o=-1;for(;++oe.usages.includes(r))){let r="CryptoKey does not support this operation, its usages must include ";if(t.length>2){let n=t.pop();r+=`one of ${t.join(", ")}, or ${n}.`;}else t.length===2?r+=`one of ${t[0]} or ${t[1]}.`:r+=`${t[0]}.`;throw new TypeError(r)}}function ht(e,t,...r){switch(t){case"HS256":case"HS384":case"HS512":{if(!N(e.algorithm,"HMAC"))throw P("HMAC");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"RS256":case"RS384":case"RS512":{if(!N(e.algorithm,"RSASSA-PKCS1-v1_5"))throw P("RSASSA-PKCS1-v1_5");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"PS256":case"PS384":case"PS512":{if(!N(e.algorithm,"RSA-PSS"))throw P("RSA-PSS");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"EdDSA":{if(e.algorithm.name!=="Ed25519"&&e.algorithm.name!=="Ed448"){if(D()){if(N(e.algorithm,"NODE-ED25519"))break;throw P("Ed25519, Ed448, or NODE-ED25519")}throw P("Ed25519 or Ed448")}break}case"ES256":case"ES384":case"ES512":{if(!N(e.algorithm,"ECDSA"))throw P("ECDSA");let n=tr(t);if(e.algorithm.namedCurve!==n)throw P(n,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r);}function I(e,t,...r){switch(t){case"A128GCM":case"A192GCM":case"A256GCM":{if(!N(e.algorithm,"AES-GCM"))throw P("AES-GCM");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"A128KW":case"A192KW":case"A256KW":{if(!N(e.algorithm,"AES-KW"))throw P("AES-KW");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"ECDH":{switch(e.algorithm.name){case"ECDH":case"X25519":case"X448":break;default:throw P("ECDH, X25519, or X448")}break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":if(!N(e.algorithm,"PBKDF2"))throw P("PBKDF2");break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(!N(e.algorithm,"RSA-OAEP"))throw P("RSA-OAEP");let n=parseInt(t.slice(9),10)||1;if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r);}function yt(e,t,...r){if(r.length>2){let n=r.pop();e+=`one of type ${r.join(", ")}, or ${n}.`;}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t=="function"&&t.name?e+=` Received function ${t.name}`:typeof t=="object"&&t!=null&&t.constructor&&t.constructor.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var A=(e,...t)=>yt("Key must be ",e,...t);function $e(e,t,...r){return yt(`Key for the ${e} algorithm must be `,t,...r)}var Ge=e=>b(e),y=["CryptoKey"];async function rr(e,t,r,n,o,a){if(!(t instanceof Uint8Array))throw new TypeError(A(t,"Uint8Array"));let i=parseInt(e.slice(1,4),10),s=await f.subtle.importKey("raw",t.subarray(i>>3),"AES-CBC",!1,["decrypt"]),c=await f.subtle.importKey("raw",t.subarray(0,i>>3),{hash:`SHA-${i<<1}`,name:"HMAC"},!1,["sign"]),d=W(a,n,r,He(a.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",c,d)).slice(0,i>>3)),m;try{m=lt(o,p);}catch(T){}if(!m)throw new M;let K;try{K=new Uint8Array(await f.subtle.decrypt({iv:n,name:"AES-CBC"},s,r));}catch(T){}if(!K)throw new M;return K}async function nr(e,t,r,n,o,a){let i;t instanceof Uint8Array?i=await f.subtle.importKey("raw",t,"AES-GCM",!1,["decrypt"]):(I(t,e,"decrypt"),i=t);try{return new Uint8Array(await f.subtle.decrypt({additionalData:a,iv:n,name:"AES-GCM",tagLength:128},i,W(r,o)))}catch(s){throw new M}}var or=async(e,t,r,n,o,a)=>{if(!b(t)&&!(t instanceof Uint8Array))throw new TypeError(A(t,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(-3),10)),rr(e,t,r,n,o,a);case"A128GCM":case"A192GCM":case"A256GCM":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(1,4),10)),nr(e,t,r,n,o,a);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},De=or;var wt=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.')},Et=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.')};var ar=(...e)=>{let t=e.filter(Boolean);if(t.length===0||t.length===1)return !0;let r;for(let n of t){let o=Object.keys(n);if(!r||r.size===0){r=new Set(o);continue}for(let a of o){if(r.has(a))return !1;r.add(a);}}return !0},R=ar;function ir(e){return typeof e=="object"&&e!==null}function w(e){if(!ir(e)||Object.prototype.toString.call(e)!=="[object Object]")return !1;if(Object.getPrototypeOf(e)===null)return !0;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}var sr=[{hash:"SHA-256",name:"HMAC"},!0,["sign"]],oe=sr;function gt(e,t){if(e.algorithm.length!==parseInt(t.slice(1,4),10))throw new TypeError(`Invalid key size for alg: ${t}`)}function St(e,t,r){if(b(e))return I(e,t,r),e;if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"AES-KW",!0,[r]);throw new TypeError(A(e,...y,"Uint8Array"))}var le=async(e,t,r)=>{let n=await St(t,e,"wrapKey");gt(n,e);let o=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",o,n,"AES-KW"))},me=async(e,t,r)=>{let n=await St(t,e,"unwrapKey");gt(n,e);let o=await f.subtle.unwrapKey("raw",r,n,"AES-KW",...oe);return new Uint8Array(await f.subtle.exportKey("raw",o))};async function Re(e,t,r,n,o=new Uint8Array(0),a=new Uint8Array(0)){if(!b(e))throw new TypeError(A(e,...y));if(I(e,"ECDH"),!b(t))throw new TypeError(A(t,...y));I(t,"ECDH","deriveBits");let i=W(Pe(E.encode(r)),Pe(o),Pe(a),Ce(n)),s;e.algorithm.name==="X25519"?s=256:e.algorithm.name==="X448"?s=448:s=Math.ceil(parseInt(e.algorithm.namedCurve.substr(-3),10)/8)<<3;let c=new Uint8Array(await f.subtle.deriveBits({name:e.algorithm.name,public:e},t,s));return pt(c,n,i)}async function At(e){if(!b(e))throw new TypeError(A(e,...y));return f.subtle.generateKey(e.algorithm,!0,["deriveBits"])}function Oe(e){if(!b(e))throw new TypeError(A(e,...y));return ["P-256","P-384","P-521"].includes(e.algorithm.namedCurve)||e.algorithm.name==="X25519"||e.algorithm.name==="X448"}function Ve(e){if(!(e instanceof Uint8Array)||e.length<8)throw new u("PBES2 Salt Input must be 8 or more octets")}function cr(e,t){if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"PBKDF2",!1,["deriveBits"]);if(b(e))return I(e,t,"deriveBits","deriveKey"),e;throw new TypeError(A(e,...y,"Uint8Array"))}async function _t(e,t,r,n){Ve(e);let o=dt(t,e),a=parseInt(t.slice(13,16),10),i={hash:`SHA-${t.slice(8,11)}`,iterations:r,name:"PBKDF2",salt:o},s={length:a,name:"AES-KW"},c=await cr(n,t);if(c.usages.includes("deriveBits"))return new Uint8Array(await f.subtle.deriveBits(i,c,a));if(c.usages.includes("deriveKey"))return f.subtle.deriveKey(i,c,s,!1,["wrapKey","unwrapKey"]);throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"')}var vt=async(e,t,r,n=2048,o=$(new Uint8Array(16)))=>{let a=await _t(o,e,n,t);return {encryptedKey:await le(e.slice(-6),a,r),p2c:n,p2s:g(o)}},Kt=async(e,t,r,n,o)=>{let a=await _t(o,e,n,t);return me(e.slice(-6),a,r)};function ae(e){switch(e){case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":return "RSA-OAEP";default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}var Q=(e,t)=>{if(e.startsWith("RS")||e.startsWith("PS")){let{modulusLength:r}=t.algorithm;if(typeof r!="number"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}};var xt=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"encrypt","wrapKey"),Q(e,t),t.usages.includes("encrypt"))return new Uint8Array(await f.subtle.encrypt(ae(e),t,r));if(t.usages.includes("wrapKey")){let n=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",n,t,ae(e)))}throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation')},Ht=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"decrypt","unwrapKey"),Q(e,t),t.usages.includes("decrypt"))return new Uint8Array(await f.subtle.decrypt(ae(e),t,r));if(t.usages.includes("unwrapKey")){let n=await f.subtle.unwrapKey("raw",r,t,ae(e),...oe);return new Uint8Array(await f.subtle.exportKey("raw",n))}throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation')};function he(e){switch(e){case"A128GCM":return 128;case"A192GCM":return 192;case"A256GCM":case"A128CBC-HS256":return 256;case"A192CBC-HS384":return 384;case"A256CBC-HS512":return 512;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var O=e=>$(new Uint8Array(he(e)>>3));var Fe=(e,t)=>{let r=(e.match(/.{1,64}/g)||[]).join(` -`);return `-----BEGIN ${t}----- -${r} ------END ${t}-----`};var Wt=async(e,t,r)=>{if(!b(r))throw new TypeError(A(r,...y));if(!r.extractable)throw new TypeError("CryptoKey is not extractable");if(r.type!==e)throw new TypeError(`key is not a ${e} key`);return Fe(We(new Uint8Array(await f.subtle.exportKey(t,r))),`${e.toUpperCase()} KEY`)},Jt=e=>Wt("public","spki",e),Tt=e=>Wt("private","pkcs8",e),G=(e,t,r=0)=>{r===0&&(t.unshift(t.length),t.unshift(6));let n=e.indexOf(t[0],r);if(n===-1)return !1;let o=e.subarray(n,n+t.length);return o.length!==t.length?!1:o.every((a,i)=>a===t[i])||G(e,t,n+1)},Ct=e=>{switch(!0){case G(e,[42,134,72,206,61,3,1,7]):return "P-256";case G(e,[43,129,4,0,34]):return "P-384";case G(e,[43,129,4,0,35]):return "P-521";case G(e,[43,101,110]):return "X25519";case G(e,[43,101,111]):return "X448";case G(e,[43,101,112]):return "Ed25519";case G(e,[43,101,113]):return "Ed448";default:throw new l("Invalid or unsupported EC Key Curve or OKP Key Sub Type")}},It=async(e,t,r,n,o)=>{var a,i;let s,c,d=new Uint8Array(atob(r.replace(e,"")).split("").map(m=>m.charCodeAt(0))),p=t==="spki";switch(n){case"PS256":case"PS384":case"PS512":s={name:"RSA-PSS",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RS256":case"RS384":case"RS512":s={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":s={name:"RSA-OAEP",hash:`SHA-${parseInt(n.slice(-3),10)||1}`},c=p?["encrypt","wrapKey"]:["decrypt","unwrapKey"];break;case"ES256":s={name:"ECDSA",namedCurve:"P-256"},c=p?["verify"]:["sign"];break;case"ES384":s={name:"ECDSA",namedCurve:"P-384"},c=p?["verify"]:["sign"];break;case"ES512":s={name:"ECDSA",namedCurve:"P-521"},c=p?["verify"]:["sign"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{let m=Ct(d);s=m.startsWith("P-")?{name:"ECDH",namedCurve:m}:{name:m},c=p?[]:["deriveBits"];break}case"EdDSA":s={name:Ct(d)},c=p?["verify"]:["sign"];break;default:throw new l('Invalid or unsupported "alg" (Algorithm) value')}try{return await f.subtle.importKey(t,d,s,(a=o==null?void 0:o.extractable)!==null&&a!==void 0?a:!1,c)}catch(m){if(s.name==="Ed25519"&&(m==null?void 0:m.name)==="NotSupportedError"&&D())return s={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey(t,d,s,(i=o==null?void 0:o.extractable)!==null&&i!==void 0?i:!1,c);throw m}},Dt=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g,"pkcs8",e,t,r),ze=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g,"spki",e,t,r);function Pt(e){let t=[],r=0;for(;r=128;)r=r*128+e[t]-128,t++;r=r*128+e[t]-128,t++;}let n=0;if(e[t]<128)n=e[t],t++;else if(n===128){for(n=0;e[t+n]!==0||e[t+n+1]!==0;){if(n>e.byteLength)throw new TypeError("invalid indefinite form length");n++;}let a=t+n+2;return {byteLength:a,contents:e.subarray(t,t+n),raw:e.subarray(0,a)}}else {let a=e[t]&127;t++,n=0;for(let i=0;i{let n;try{n=pr(e);}catch(o){throw new TypeError("failed to parse the X.509 certificate",{cause:o})}return ze(n,t,r)};function ur(e){let t,r;switch(e.kty){case"oct":{switch(e.alg){case"HS256":case"HS384":case"HS512":t={name:"HMAC",hash:`SHA-${e.alg.slice(-3)}`},r=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":throw new l(`${e.alg} keys cannot be imported as CryptoKey instances`);case"A128GCM":case"A192GCM":case"A256GCM":case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":t={name:"AES-GCM"},r=["encrypt","decrypt"];break;case"A128KW":case"A192KW":case"A256KW":t={name:"AES-KW"},r=["wrapKey","unwrapKey"];break;case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":t={name:"PBKDF2"},r=["deriveBits"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"RSA":{switch(e.alg){case"PS256":case"PS384":case"PS512":t={name:"RSA-PSS",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":t={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":t={name:"RSA-OAEP",hash:`SHA-${parseInt(e.alg.slice(-3),10)||1}`},r=e.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"EC":{switch(e.alg){case"ES256":t={name:"ECDSA",namedCurve:"P-256"},r=e.d?["sign"]:["verify"];break;case"ES384":t={name:"ECDSA",namedCurve:"P-384"},r=e.d?["sign"]:["verify"];break;case"ES512":t={name:"ECDSA",namedCurve:"P-521"},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:"ECDH",namedCurve:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"OKP":{switch(e.alg){case"EdDSA":t={name:e.crv},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}default:throw new l('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return {algorithm:t,keyUsages:r}}var fr=async e=>{var t,r;if(!e.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');let{algorithm:n,keyUsages:o}=ur(e),a=[n,(t=e.ext)!==null&&t!==void 0?t:!1,(r=e.key_ops)!==null&&r!==void 0?r:o];if(n.name==="PBKDF2")return f.subtle.importKey("raw",S(e.k),...a);let i={...e};delete i.alg,delete i.use;try{return await f.subtle.importKey("jwk",i,...a)}catch(s){if(n.name==="Ed25519"&&(s==null?void 0:s.name)==="NotSupportedError"&&D())return a[0]={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey("jwk",i,...a);throw s}},Xe=fr;async function lr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PUBLIC KEY-----")!==0)throw new TypeError('"spki" must be SPKI formatted string');return ze(e,t,r)}async function mr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN CERTIFICATE-----")!==0)throw new TypeError('"x509" must be X.509 formatted string');return Ot(e,t,r)}async function hr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PRIVATE KEY-----")!==0)throw new TypeError('"pkcs8" must be PKCS#8 formatted string');return Dt(e,t,r)}async function j(e,t,r){var n;if(!w(e))throw new TypeError("JWK must be an object");switch(t||(t=e.alg),e.kty){case"oct":if(typeof e.k!="string"||!e.k)throw new TypeError('missing "k" (Key Value) Parameter value');return r!=null||(r=e.ext!==!0),r?Xe({...e,alg:t,ext:(n=e.ext)!==null&&n!==void 0?n:!1}):S(e.k);case"RSA":if(e.oth!==void 0)throw new l('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');case"EC":case"OKP":return Xe({...e,alg:t});default:throw new l('Unsupported "kty" (Key Type) Parameter value')}}var yr=(e,t)=>{if(!(t instanceof Uint8Array)){if(!Ge(t))throw new TypeError($e(e,t,...y,"Uint8Array"));if(t.type!=="secret")throw new TypeError(`${y.join(" or ")} instances for symmetric algorithms must be of type "secret"`)}},wr=(e,t,r)=>{if(!Ge(t))throw new TypeError($e(e,t,...y));if(t.type==="secret")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`);if(r==="sign"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`);if(r==="decrypt"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`);if(t.algorithm&&r==="verify"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`);if(t.algorithm&&r==="encrypt"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`)},Er=(e,t,r)=>{e.startsWith("HS")||e==="dir"||e.startsWith("PBES2")||/^A\d{3}(?:GCM)?KW$/.test(e)?yr(e,t):wr(e,t,r);},V=Er;async function gr(e,t,r,n,o){if(!(r instanceof Uint8Array))throw new TypeError(A(r,"Uint8Array"));let a=parseInt(e.slice(1,4),10),i=await f.subtle.importKey("raw",r.subarray(a>>3),"AES-CBC",!1,["encrypt"]),s=await f.subtle.importKey("raw",r.subarray(0,a>>3),{hash:`SHA-${a<<1}`,name:"HMAC"},!1,["sign"]),c=new Uint8Array(await f.subtle.encrypt({iv:n,name:"AES-CBC"},i,t)),d=W(o,n,c,He(o.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",s,d)).slice(0,a>>3));return {ciphertext:c,tag:p}}async function Sr(e,t,r,n,o){let a;r instanceof Uint8Array?a=await f.subtle.importKey("raw",r,"AES-GCM",!1,["encrypt"]):(I(r,e,"encrypt"),a=r);let i=new Uint8Array(await f.subtle.encrypt({additionalData:o,iv:n,name:"AES-GCM",tagLength:128},a,t)),s=i.slice(-16);return {ciphertext:i.slice(0,-16),tag:s}}var Ar=async(e,t,r,n,o)=>{if(!b(r)&&!(r instanceof Uint8Array))throw new TypeError(A(r,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(-3),10)),gr(e,t,r,n,o);case"A128GCM":case"A192GCM":case"A256GCM":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(1,4),10)),Sr(e,t,r,n,o);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},ye=Ar;async function Ut(e,t,r,n){let o=e.slice(0,7);n||(n=Je(o));let{ciphertext:a,tag:i}=await ye(o,r,t,n,new Uint8Array(0));return {encryptedKey:a,iv:g(n),tag:g(i)}}async function Mt(e,t,r,n,o){let a=e.slice(0,7);return De(a,t,r,n,o,new Uint8Array(0))}async function br(e,t,r,n,o){switch(V(e,t,"decrypt"),e){case"dir":{if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");return t}case"ECDH-ES":if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!w(n.epk))throw new u('JOSE Header "epk" (Ephemeral Public Key) missing or invalid');if(!Oe(t))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let a=await j(n.epk,e),i,s;if(n.apu!==void 0){if(typeof n.apu!="string")throw new u('JOSE Header "apu" (Agreement PartyUInfo) invalid');i=S(n.apu);}if(n.apv!==void 0){if(typeof n.apv!="string")throw new u('JOSE Header "apv" (Agreement PartyVInfo) invalid');s=S(n.apv);}let c=await Re(a,t,e==="ECDH-ES"?n.enc:e,e==="ECDH-ES"?he(n.enc):parseInt(e.slice(-5,-2),10),i,s);if(e==="ECDH-ES")return c;if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e.slice(-6),c,r)}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(r===void 0)throw new u("JWE Encrypted Key missing");return Ht(e,t,r)}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.p2c!="number")throw new u('JOSE Header "p2c" (PBES2 Count) missing or invalid');let a=(o==null?void 0:o.maxPBES2Count)||1e4;if(n.p2c>a)throw new u('JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds');if(typeof n.p2s!="string")throw new u('JOSE Header "p2s" (PBES2 Salt) missing or invalid');return Kt(e,t,r,n.p2c,S(n.p2s))}case"A128KW":case"A192KW":case"A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e,t,r)}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.iv!="string")throw new u('JOSE Header "iv" (Initialization Vector) missing or invalid');if(typeof n.tag!="string")throw new u('JOSE Header "tag" (Authentication Tag) missing or invalid');let a=S(n.iv),i=S(n.tag);return Mt(e,t,r,a,i)}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}}var Nt=br;function _r(e,t,r,n,o){if(o.crit!==void 0&&n.crit===void 0)throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');if(!n||n.crit===void 0)return new Set;if(!Array.isArray(n.crit)||n.crit.length===0||n.crit.some(i=>typeof i!="string"||i.length===0))throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let a;r!==void 0?a=new Map([...Object.entries(r),...t.entries()]):a=t;for(let i of n.crit){if(!a.has(i))throw new l(`Extension Header Parameter "${i}" is not recognized`);if(o[i]===void 0)throw new e(`Extension Header Parameter "${i}" is missing`);if(a.get(i)&&n[i]===void 0)throw new e(`Extension Header Parameter "${i}" MUST be integrity protected`)}return new Set(n.crit)}var U=_r;var vr=(e,t)=>{if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!="string")))throw new TypeError(`"${e}" option must be an array of strings`);if(t)return new Set(t)},we=vr;async function Ee(e,t,r){var n;if(!w(e))throw new u("Flattened JWE must be an object");if(e.protected===void 0&&e.header===void 0&&e.unprotected===void 0)throw new u("JOSE Header missing");if(typeof e.iv!="string")throw new u("JWE Initialization Vector missing or incorrect type");if(typeof e.ciphertext!="string")throw new u("JWE Ciphertext missing or incorrect type");if(typeof e.tag!="string")throw new u("JWE Authentication Tag missing or incorrect type");if(e.protected!==void 0&&typeof e.protected!="string")throw new u("JWE Protected Header incorrect type");if(e.encrypted_key!==void 0&&typeof e.encrypted_key!="string")throw new u("JWE Encrypted Key incorrect type");if(e.aad!==void 0&&typeof e.aad!="string")throw new u("JWE AAD incorrect type");if(e.header!==void 0&&!w(e.header))throw new u("JWE Shared Unprotected Header incorrect type");if(e.unprotected!==void 0&&!w(e.unprotected))throw new u("JWE Per-Recipient Unprotected Header incorrect type");let o;if(e.protected)try{let Y=S(e.protected);o=JSON.parse(v.decode(Y));}catch(Y){throw new u("JWE Protected Header is invalid")}if(!R(o,e.header,e.unprotected))throw new u("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint");let a={...o,...e.header,...e.unprotected};if(U(u,new Map,r==null?void 0:r.crit,o,a),a.zip!==void 0){if(!o||!o.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(a.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:i,enc:s}=a;if(typeof i!="string"||!i)throw new u("missing JWE Algorithm (alg) in JWE Header");if(typeof s!="string"||!s)throw new u("missing JWE Encryption Algorithm (enc) in JWE Header");let c=r&&we("keyManagementAlgorithms",r.keyManagementAlgorithms),d=r&&we("contentEncryptionAlgorithms",r.contentEncryptionAlgorithms);if(c&&!c.has(i))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(d&&!d.has(s))throw new B('"enc" (Encryption Algorithm) Header Parameter not allowed');let p;e.encrypted_key!==void 0&&(p=S(e.encrypted_key));let m=!1;typeof t=="function"&&(t=await t(o,e),m=!0);let K;try{K=await Nt(i,t,p,a,r);}catch(Y){if(Y instanceof TypeError||Y instanceof u||Y instanceof l)throw Y;K=O(s);}let T=S(e.iv),x=S(e.tag),_=E.encode((n=e.protected)!==null&&n!==void 0?n:""),k;e.aad!==void 0?k=W(_,E.encode("."),E.encode(e.aad)):k=_;let Ne=await De(s,K,S(e.ciphertext),T,x,k);a.zip==="DEF"&&(Ne=await((r==null?void 0:r.inflateRaw)||wt)(Ne));let te={plaintext:Ne};return e.protected!==void 0&&(te.protectedHeader=o),e.aad!==void 0&&(te.additionalAuthenticatedData=S(e.aad)),e.unprotected!==void 0&&(te.sharedUnprotectedHeader=e.unprotected),e.header!==void 0&&(te.unprotectedHeader=e.header),m?{...te,key:t}:te}async function Ye(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new u("Compact JWE must be a string or Uint8Array");let{0:n,1:o,2:a,3:i,4:s,length:c}=e.split(".");if(c!==5)throw new u("Invalid Compact JWE");let d=await Ee({ciphertext:i,iv:a||void 0,protected:n||void 0,tag:s||void 0,encrypted_key:o||void 0},t,r),p={plaintext:d.plaintext,protectedHeader:d.protectedHeader};return typeof t=="function"?{...p,key:d.key}:p}async function Kr(e,t,r){if(!w(e))throw new u("General JWE must be an object");if(!Array.isArray(e.recipients)||!e.recipients.every(w))throw new u("JWE Recipients missing or incorrect type");if(!e.recipients.length)throw new u("JWE Recipients has no members");for(let n of e.recipients)try{return await Ee({aad:e.aad,ciphertext:e.ciphertext,encrypted_key:n.encrypted_key,header:n.header,iv:e.iv,protected:e.protected,tag:e.tag,unprotected:e.unprotected},t,r)}catch(o){}throw new M}var xr=async e=>{if(e instanceof Uint8Array)return {kty:"oct",k:g(e)};if(!b(e))throw new TypeError(A(e,...y,"Uint8Array"));if(!e.extractable)throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");let{ext:t,key_ops:r,alg:n,use:o,...a}=await f.subtle.exportKey("jwk",e);return a},kt=xr;async function Hr(e){return Jt(e)}async function Cr(e){return Tt(e)}async function qe(e){return kt(e)}async function Pr(e,t,r,n,o={}){let a,i,s;switch(V(e,r,"encrypt"),e){case"dir":{s=r;break}case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!Oe(r))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let{apu:c,apv:d}=o,{epk:p}=o;p||(p=(await At(r)).privateKey);let{x:m,y:K,crv:T,kty:x}=await qe(p),_=await Re(r,p,e==="ECDH-ES"?t:e,e==="ECDH-ES"?he(t):parseInt(e.slice(-5,-2),10),c,d);if(i={epk:{x:m,crv:T,kty:x}},x==="EC"&&(i.epk.y=K),c&&(i.apu=g(c)),d&&(i.apv=g(d)),e==="ECDH-ES"){s=_;break}s=n||O(t);let k=e.slice(-6);a=await le(k,_,s);break}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{s=n||O(t),a=await xt(e,r,s);break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{s=n||O(t);let{p2c:c,p2s:d}=o;({encryptedKey:a,...i}=await vt(e,r,s,c,d));break}case"A128KW":case"A192KW":case"A256KW":{s=n||O(t),a=await le(e,r,s);break}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{s=n||O(t);let{iv:c}=o;({encryptedKey:a,...i}=await Ut(e,r,s,c));break}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}return {cek:s,encryptedKey:a,parameters:i}}var Ue=Pr;var Ze=Symbol(),F=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("plaintext must be an instance of Uint8Array");this._plaintext=t;}setKeyManagementParameters(t){if(this._keyManagementParameters)throw new TypeError("setKeyManagementParameters can only be called once");return this._keyManagementParameters=t,this}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._sharedUnprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._sharedUnprotectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}setContentEncryptionKey(t){if(this._cek)throw new TypeError("setContentEncryptionKey can only be called once");return this._cek=t,this}setInitializationVector(t){if(this._iv)throw new TypeError("setInitializationVector can only be called once");return this._iv=t,this}async encrypt(t,r){if(!this._protectedHeader&&!this._unprotectedHeader&&!this._sharedUnprotectedHeader)throw new u("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()");if(!R(this._protectedHeader,this._unprotectedHeader,this._sharedUnprotectedHeader))throw new u("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader,...this._sharedUnprotectedHeader};if(U(u,new Map,r==null?void 0:r.crit,this._protectedHeader,n),n.zip!==void 0){if(!this._protectedHeader||!this._protectedHeader.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(n.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:o,enc:a}=n;if(typeof o!="string"||!o)throw new u('JWE "alg" (Algorithm) Header Parameter missing or invalid');if(typeof a!="string"||!a)throw new u('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');let i;if(o==="dir"){if(this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption")}else if(o==="ECDH-ES"&&this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement");let s;{let x;(({cek:s,encryptedKey:i,parameters:x}=await Ue(o,a,t,this._cek,this._keyManagementParameters))),x&&(r&&Ze in r?this._unprotectedHeader?this._unprotectedHeader={...this._unprotectedHeader,...x}:this.setUnprotectedHeader(x):this._protectedHeader?this._protectedHeader={...this._protectedHeader,...x}:this.setProtectedHeader(x));}this._iv||(this._iv=Je(a));let c,d,p;this._protectedHeader?d=E.encode(g(JSON.stringify(this._protectedHeader))):d=E.encode(""),this._aad?(p=g(this._aad),c=W(d,E.encode("."),E.encode(p))):c=d;let m,K;if(n.zip==="DEF"){let x=await((r==null?void 0:r.deflateRaw)||Et)(this._plaintext);({ciphertext:m,tag:K}=await ye(a,x,s,this._iv,c));}else ({ciphertext:m,tag:K}=await ye(a,this._plaintext,s,this._iv,c));let T={ciphertext:g(m),iv:g(this._iv),tag:g(K)};return i&&(T.encrypted_key=g(i)),p&&(T.aad=p),this._protectedHeader&&(T.protected=v.decode(d)),this._sharedUnprotectedHeader&&(T.unprotected=this._sharedUnprotectedHeader),this._unprotectedHeader&&(T.header=this._unprotectedHeader),T}};var Qe=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n;}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addRecipient(...t){return this.parent.addRecipient(...t)}encrypt(...t){return this.parent.encrypt(...t)}done(){return this.parent}},je=class{constructor(t){this._recipients=[],this._plaintext=t;}addRecipient(t,r){let n=new Qe(this,t,{crit:r==null?void 0:r.crit});return this._recipients.push(n),n}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}async encrypt(t){var r,n,o;if(!this._recipients.length)throw new u("at least one recipient must be added");if(t={deflateRaw:t==null?void 0:t.deflateRaw},this._recipients.length===1){let[c]=this._recipients,d=await new F(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(c.unprotectedHeader).encrypt(c.key,{...c.options,...t}),p={ciphertext:d.ciphertext,iv:d.iv,recipients:[{}],tag:d.tag};return d.aad&&(p.aad=d.aad),d.protected&&(p.protected=d.protected),d.unprotected&&(p.unprotected=d.unprotected),d.encrypted_key&&(p.recipients[0].encrypted_key=d.encrypted_key),d.header&&(p.recipients[0].header=d.header),p}let a;for(let c=0;c>3};case"RS256":case"RS384":case"RS512":return {hash:r,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return {hash:r,name:"ECDSA",namedCurve:t.namedCurve};case"EdDSA":return D()&&t.name==="NODE-ED25519"?{name:"NODE-ED25519",namedCurve:"NODE-ED25519"}:{name:t.name};default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}function Se(e,t,r){if(b(t))return ht(t,e,r),t;if(t instanceof Uint8Array){if(!e.startsWith("HS"))throw new TypeError(A(t,...y));return f.subtle.importKey("raw",t,{hash:`SHA-${e.slice(-3)}`,name:"HMAC"},!1,[r])}throw new TypeError(A(t,...y,"Uint8Array"))}var Wr=async(e,t,r,n)=>{let o=await Se(e,t,"verify");Q(e,o);let a=ge(e,o.algorithm);try{return await f.subtle.verify(a,o,r,n)}catch(i){return !1}},Bt=Wr;async function Ae(e,t,r){var n;if(!w(e))throw new h("Flattened JWS must be an object");if(e.protected===void 0&&e.header===void 0)throw new h('Flattened JWS must have either of the "protected" or "header" members');if(e.protected!==void 0&&typeof e.protected!="string")throw new h("JWS Protected Header incorrect type");if(e.payload===void 0)throw new h("JWS Payload missing");if(typeof e.signature!="string")throw new h("JWS Signature missing or incorrect type");if(e.header!==void 0&&!w(e.header))throw new h("JWS Unprotected Header incorrect type");let o={};if(e.protected)try{let k=S(e.protected);o=JSON.parse(v.decode(k));}catch(k){throw new h("JWS Protected Header is invalid")}if(!R(o,e.header))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let a={...o,...e.header},i=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,o,a),s=!0;if(i.has("b64")&&(s=o.b64,typeof s!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:c}=a;if(typeof c!="string"||!c)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');let d=r&&we("algorithms",r.algorithms);if(d&&!d.has(c))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(s){if(typeof e.payload!="string")throw new h("JWS Payload must be a string")}else if(typeof e.payload!="string"&&!(e.payload instanceof Uint8Array))throw new h("JWS Payload must be a string or an Uint8Array instance");let p=!1;typeof t=="function"&&(t=await t(o,e),p=!0),V(c,t,"verify");let m=W(E.encode((n=e.protected)!==null&&n!==void 0?n:""),E.encode("."),typeof e.payload=="string"?E.encode(e.payload):e.payload),K=S(e.signature);if(!await Bt(c,t,K,m))throw new Z;let x;s?x=S(e.payload):typeof e.payload=="string"?x=E.encode(e.payload):x=e.payload;let _={payload:x};return e.protected!==void 0&&(_.protectedHeader=o),e.header!==void 0&&(_.unprotectedHeader=e.header),p?{..._,key:t}:_}async function et(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new h("Compact JWS must be a string or Uint8Array");let{0:n,1:o,2:a,length:i}=e.split(".");if(i!==3)throw new h("Invalid Compact JWS");let s=await Ae({payload:o,protected:n,signature:a},t,r),c={payload:s.payload,protectedHeader:s.protectedHeader};return typeof t=="function"?{...c,key:s.key}:c}async function Jr(e,t,r){if(!w(e))throw new h("General JWS must be an object");if(!Array.isArray(e.signatures)||!e.signatures.every(w))throw new h("JWS Signatures missing or incorrect type");for(let n of e.signatures)try{return await Ae({header:n.header,payload:e.payload,protected:n.protected,signature:n.signature},t,r)}catch(o){}throw new Z}var ie=e=>Math.floor(e.getTime()/1e3);var Tr=/^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i,se=e=>{let t=Tr.exec(e);if(!t)throw new TypeError("Invalid time period format");let r=parseFloat(t[1]);switch(t[2].toLowerCase()){case"sec":case"secs":case"second":case"seconds":case"s":return Math.round(r);case"minute":case"minutes":case"min":case"mins":case"m":return Math.round(r*60);case"hour":case"hours":case"hr":case"hrs":case"h":return Math.round(r*3600);case"day":case"days":case"d":return Math.round(r*86400);case"week":case"weeks":case"w":return Math.round(r*604800);default:return Math.round(r*31557600)}};var Lt=e=>e.toLowerCase().replace(/^application\//,""),Ir=(e,t)=>typeof e=="string"?t.includes(e):Array.isArray(e)?t.some(Set.prototype.has.bind(new Set(e))):!1,ce=(e,t,r={})=>{let{typ:n}=r;if(n&&(typeof e.typ!="string"||Lt(e.typ)!==Lt(n)))throw new J('unexpected "typ" JWT header value',"typ","check_failed");let o;try{o=JSON.parse(v.decode(t));}catch(m){}if(!w(o))throw new H("JWT Claims Set must be a top-level JSON object");let{issuer:a}=r;if(a&&!(Array.isArray(a)?a:[a]).includes(o.iss))throw new J('unexpected "iss" claim value',"iss","check_failed");let{subject:i}=r;if(i&&o.sub!==i)throw new J('unexpected "sub" claim value',"sub","check_failed");let{audience:s}=r;if(s&&!Ir(o.aud,typeof s=="string"?[s]:s))throw new J('unexpected "aud" claim value',"aud","check_failed");let c;switch(typeof r.clockTolerance){case"string":c=se(r.clockTolerance);break;case"number":c=r.clockTolerance;break;case"undefined":c=0;break;default:throw new TypeError("Invalid clockTolerance option type")}let{currentDate:d}=r,p=ie(d||new Date);if((o.iat!==void 0||r.maxTokenAge)&&typeof o.iat!="number")throw new J('"iat" claim must be a number',"iat","invalid");if(o.nbf!==void 0){if(typeof o.nbf!="number")throw new J('"nbf" claim must be a number',"nbf","invalid");if(o.nbf>p+c)throw new J('"nbf" claim timestamp check failed',"nbf","check_failed")}if(o.exp!==void 0){if(typeof o.exp!="number")throw new J('"exp" claim must be a number',"exp","invalid");if(o.exp<=p-c)throw new re('"exp" claim timestamp check failed',"exp","check_failed")}if(r.maxTokenAge){let m=p-o.iat,K=typeof r.maxTokenAge=="number"?r.maxTokenAge:se(r.maxTokenAge);if(m-c>K)throw new re('"iat" claim timestamp check failed (too far in the past)',"iat","check_failed");if(m<0-c)throw new J('"iat" claim timestamp check failed (it should be in the past)',"iat","check_failed")}return o};async function Dr(e,t,r){var n;let o=await et(e,t,r);if(!((n=o.protectedHeader.crit)===null||n===void 0)&&n.includes("b64")&&o.protectedHeader.b64===!1)throw new H("JWTs MUST NOT use unencoded payload");let i={payload:ce(o.protectedHeader,o.payload,r),protectedHeader:o.protectedHeader};return typeof t=="function"?{...i,key:o.key}:i}async function Rr(e,t,r){let n=await Ye(e,t,r),o=ce(n.protectedHeader,n.plaintext,r),{protectedHeader:a}=n;if(a.iss!==void 0&&a.iss!==o.iss)throw new J('replicated "iss" claim header parameter mismatch',"iss","mismatch");if(a.sub!==void 0&&a.sub!==o.sub)throw new J('replicated "sub" claim header parameter mismatch',"sub","mismatch");if(a.aud!==void 0&&JSON.stringify(a.aud)!==JSON.stringify(o.aud))throw new J('replicated "aud" claim header parameter mismatch',"aud","mismatch");let i={payload:o,protectedHeader:a};return typeof t=="function"?{...i,key:n.key}:i}var be=class{constructor(t){this._flattened=new F(t);}setContentEncryptionKey(t){return this._flattened.setContentEncryptionKey(t),this}setInitializationVector(t){return this._flattened.setInitializationVector(t),this}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}setKeyManagementParameters(t){return this._flattened.setKeyManagementParameters(t),this}async encrypt(t,r){let n=await this._flattened.encrypt(t,r);return [n.protected,n.encrypted_key,n.iv,n.ciphertext,n.tag].join(".")}};var Or=async(e,t,r)=>{let n=await Se(e,t,"sign");Q(e,n);let o=await f.subtle.sign(ge(e,n.algorithm),n,r);return new Uint8Array(o)},$t=Or;var ee=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("payload must be an instance of Uint8Array");this._payload=t;}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}async sign(t,r){if(!this._protectedHeader&&!this._unprotectedHeader)throw new h("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");if(!R(this._protectedHeader,this._unprotectedHeader))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader},o=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,this._protectedHeader,n),a=!0;if(o.has("b64")&&(a=this._protectedHeader.b64,typeof a!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:i}=n;if(typeof i!="string"||!i)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');V(i,t,"sign");let s=this._payload;a&&(s=E.encode(g(s)));let c;this._protectedHeader?c=E.encode(g(JSON.stringify(this._protectedHeader))):c=E.encode("");let d=W(c,E.encode("."),s),p=await $t(i,t,d),m={signature:g(p),payload:""};return a&&(m.payload=v.decode(s)),this._unprotectedHeader&&(m.header=this._unprotectedHeader),this._protectedHeader&&(m.protected=v.decode(c)),m}};var _e=class{constructor(t){this._flattened=new ee(t);}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}async sign(t,r){let n=await this._flattened.sign(t,r);if(n.payload===void 0)throw new TypeError("use the flattened module for creating JWS with b64: false");return `${n.protected}.${n.payload}.${n.signature}`}};var tt=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n;}setProtectedHeader(t){if(this.protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this.protectedHeader=t,this}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addSignature(...t){return this.parent.addSignature(...t)}sign(...t){return this.parent.sign(...t)}done(){return this.parent}},rt=class{constructor(t){this._signatures=[],this._payload=t;}addSignature(t,r){let n=new tt(this,t,r);return this._signatures.push(n),n}async sign(){if(!this._signatures.length)throw new h("at least one signature must be added");let t={signatures:[],payload:""};for(let r=0;r{if(typeof e!="string"||!e)throw new pe(`${t} missing or invalid`)};async function Gt(e,t){if(!w(e))throw new TypeError("JWK must be an object");if(t!=null||(t="sha256"),t!=="sha256"&&t!=="sha384"&&t!=="sha512")throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"');let r;switch(e.kty){case"EC":X(e.crv,'"crv" (Curve) Parameter'),X(e.x,'"x" (X Coordinate) Parameter'),X(e.y,'"y" (Y Coordinate) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x,y:e.y};break;case"OKP":X(e.crv,'"crv" (Subtype of Key Pair) Parameter'),X(e.x,'"x" (Public Key) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x};break;case"RSA":X(e.e,'"e" (Exponent) Parameter'),X(e.n,'"n" (Modulus) Parameter'),r={e:e.e,kty:e.kty,n:e.n};break;case"oct":X(e.k,'"k" (Key Value) Parameter'),r={k:e.k,kty:e.kty};break;default:throw new l('"kty" (Key Type) Parameter missing or unsupported')}let n=E.encode(JSON.stringify(r));return g(await Ke(t,n))}async function Ur(e,t){t!=null||(t="sha256");let r=await Gt(e,t);return `urn:ietf:params:oauth:jwk-thumbprint:sha-${t.slice(-3)}:${r}`}async function Mr(e,t){let r={...e,...t.header};if(!w(r.jwk))throw new h('"jwk" (JSON Web Key) Header Parameter must be a JSON object');let n=await j({...r.jwk,ext:!0},r.alg,!0);if(n instanceof Uint8Array||n.type!=="public")throw new h('"jwk" (JSON Web Key) Header Parameter must be a public key');return n}function Nr(e){switch(typeof e=="string"&&e.slice(0,2)){case"RS":case"PS":return "RSA";case"ES":return "EC";case"Ed":return "OKP";default:throw new l('Unsupported "alg" value for a JSON Web Key Set')}}function at(e){return e&&typeof e=="object"&&Array.isArray(e.keys)&&e.keys.every(kr)}function kr(e){return w(e)}function Br(e){return typeof structuredClone=="function"?structuredClone(e):JSON.parse(JSON.stringify(e))}var de=class{constructor(t){if(this._cached=new WeakMap,!at(t))throw new L("JSON Web Key Set malformed");this._jwks=Br(t);}async getKey(t,r){let{alg:n,kid:o}={...t,...r==null?void 0:r.header},a=Nr(n),i=this._jwks.keys.filter(d=>{let p=a===d.kty;if(p&&typeof o=="string"&&(p=o===d.kid),p&&typeof d.alg=="string"&&(p=n===d.alg),p&&typeof d.use=="string"&&(p=d.use==="sig"),p&&Array.isArray(d.key_ops)&&(p=d.key_ops.includes("verify")),p&&n==="EdDSA"&&(p=d.crv==="Ed25519"||d.crv==="Ed448"),p)switch(n){case"ES256":p=d.crv==="P-256";break;case"ES256K":p=d.crv==="secp256k1";break;case"ES384":p=d.crv==="P-384";break;case"ES512":p=d.crv==="P-521";break}return p}),{0:s,length:c}=i;if(c===0)throw new q;if(c!==1){let d=new ue,{_cached:p}=this;throw d[Symbol.asyncIterator]=async function*(){for(let m of i)try{yield await Vt(p,m,n);}catch(K){continue}},d}return Vt(this._cached,s,n)}};async function Vt(e,t,r){let n=e.get(t)||e.set(t,{}).get(t);if(n[r]===void 0){let o=await j({...t,ext:!0},r);if(o.type!=="public")throw new L("JSON Web Key Set members must be public keys");n[r]=o;}return n[r]}function Lr(e){return de.prototype.getKey.bind(new de(e))}var $r=async(e,t,r)=>{let n,o,a=!1;typeof AbortController=="function"&&(n=new AbortController,o=setTimeout(()=>{a=!0,n.abort();},t));let i=await fetch(e.href,{signal:n?n.signal:void 0,redirect:"manual",headers:r.headers}).catch(s=>{throw a?new fe:s});if(o!==void 0&&clearTimeout(o),i.status!==200)throw new C("Expected 200 OK from the JSON Web Key Set HTTP response");try{return await i.json()}catch(s){throw new C("Failed to parse the JSON Web Key Set HTTP response as JSON")}},Ft=$r;var Me=class extends de{constructor(t,r){if(super({keys:[]}),this._jwks=void 0,!(t instanceof URL))throw new TypeError("url must be an instance of URL");this._url=new URL(t.href),this._options={agent:r==null?void 0:r.agent,headers:r==null?void 0:r.headers},this._timeoutDuration=typeof(r==null?void 0:r.timeoutDuration)=="number"?r==null?void 0:r.timeoutDuration:5e3,this._cooldownDuration=typeof(r==null?void 0:r.cooldownDuration)=="number"?r==null?void 0:r.cooldownDuration:3e4,this._cacheMaxAge=typeof(r==null?void 0:r.cacheMaxAge)=="number"?r==null?void 0:r.cacheMaxAge:6e5;}coolingDown(){return typeof this._jwksTimestamp=="number"?Date.now(){let r=()=>{this._pendingFetch===void 0?t():setTimeout(r,5);};r();});this._pendingFetch||(this._pendingFetch=Ft(this._url,this._timeoutDuration,this._options).then(t=>{if(!at(t))throw new L("JSON Web Key Set malformed");this._jwks={keys:t.keys},this._jwksTimestamp=Date.now(),this._pendingFetch=void 0;}).catch(t=>{throw this._pendingFetch=void 0,t})),await this._pendingFetch;}};function Gr(e,t){return Me.prototype.getKey.bind(new Me(e,t))}var it=class extends z{encode(){let t=g(JSON.stringify({alg:"none"})),r=g(JSON.stringify(this._payload));return `${t}.${r}.`}static decode(t,r){if(typeof t!="string")throw new H("Unsecured JWT must be a string");let{0:n,1:o,2:a,length:i}=t.split(".");if(i!==3||a!=="")throw new H("Invalid Unsecured JWT");let s;try{if(s=JSON.parse(v.decode(S(n))),s.alg!=="none")throw new Error}catch(d){throw new H("Invalid Unsecured JWT")}return {payload:ce(s,S(o),r),header:s}}};var zt={};ct(zt,{decode:()=>ve,encode:()=>Vr});var Vr=g,ve=S;function Fr(e){let t;if(typeof e=="string"){let r=e.split(".");(r.length===3||r.length===5)&&([t]=r);}else if(typeof e=="object"&&e)if("protected"in e)t=e.protected;else throw new TypeError("Token does not contain a Protected Header");try{if(typeof t!="string"||!t)throw new Error;let r=JSON.parse(v.decode(ve(t)));if(!w(r))throw new Error;return r}catch(r){throw new TypeError("Invalid Token or Protected Header formatting")}}function zr(e){if(typeof e!="string")throw new H("JWTs must use Compact JWS serialization, JWT must be a string");let{1:t,length:r}=e.split(".");if(r===5)throw new H("Only JWTs using Compact JWS serialization can be decoded");if(r!==3)throw new H("Invalid JWT");if(!t)throw new H("JWTs must contain a payload");let n;try{n=ve(t);}catch(a){throw new H("Failed to parse the base64url encoded payload")}let o;try{o=JSON.parse(v.decode(n));}catch(a){throw new H("Failed to parse the decoded payload as JSON")}if(!w(o))throw new H("Invalid JWT Claims Set");return o}async function Xt(e,t){var r;let n,o,a;switch(e){case"HS256":case"HS384":case"HS512":n=parseInt(e.slice(-3),10),o={name:"HMAC",hash:`SHA-${n}`,length:n},a=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return n=parseInt(e.slice(-3),10),$(new Uint8Array(n>>3));case"A128KW":case"A192KW":case"A256KW":n=parseInt(e.slice(1,4),10),o={name:"AES-KW",length:n},a=["wrapKey","unwrapKey"];break;case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":case"A128GCM":case"A192GCM":case"A256GCM":n=parseInt(e.slice(1,4),10),o={name:"AES-GCM",length:n},a=["encrypt","decrypt"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}return f.subtle.generateKey(o,(r=t==null?void 0:t.extractable)!==null&&r!==void 0?r:!1,a)}function st(e){var t;let r=(t=e==null?void 0:e.modulusLength)!==null&&t!==void 0?t:2048;if(typeof r!="number"||r<2048)throw new l("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used");return r}async function Yt(e,t){var r,n,o,a;let i,s;switch(e){case"PS256":case"PS384":case"PS512":i={name:"RSA-PSS",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RS256":case"RS384":case"RS512":i={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":i={name:"RSA-OAEP",hash:`SHA-${parseInt(e.slice(-3),10)||1}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["decrypt","unwrapKey","encrypt","wrapKey"];break;case"ES256":i={name:"ECDSA",namedCurve:"P-256"},s=["sign","verify"];break;case"ES384":i={name:"ECDSA",namedCurve:"P-384"},s=["sign","verify"];break;case"ES512":i={name:"ECDSA",namedCurve:"P-521"},s=["sign","verify"];break;case"EdDSA":s=["sign","verify"];let c=(r=t==null?void 0:t.crv)!==null&&r!==void 0?r:"Ed25519";switch(c){case"Ed25519":case"Ed448":i={name:c};break;default:throw new l("Invalid or unsupported crv option provided")}break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{s=["deriveKey","deriveBits"];let d=(n=t==null?void 0:t.crv)!==null&&n!==void 0?n:"P-256";switch(d){case"P-256":case"P-384":case"P-521":{i={name:"ECDH",namedCurve:d};break}case"X25519":case"X448":i={name:d};break;default:throw new l("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448")}break}default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}try{return await f.subtle.generateKey(i,(o=t==null?void 0:t.extractable)!==null&&o!==void 0?o:!1,s)}catch(c){if(i.name==="Ed25519"&&(c==null?void 0:c.name)==="NotSupportedError"&&D())return i={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.generateKey(i,(a=t==null?void 0:t.extractable)!==null&&a!==void 0?a:!1,s);throw c}}async function Xr(e,t){return Yt(e,t)}async function Yr(e,t){return Xt(e,t)} -exports.CompactEncrypt=be;exports.CompactSign=_e;exports.EmbeddedJWK=Mr;exports.EncryptJWT=ot;exports.FlattenedEncrypt=F;exports.FlattenedSign=ee;exports.GeneralEncrypt=je;exports.GeneralSign=rt;exports.SignJWT=nt;exports.UnsecuredJWT=it;exports.base64url=zt;exports.calculateJwkThumbprint=Gt;exports.calculateJwkThumbprintUri=Ur;exports.compactDecrypt=Ye;exports.compactVerify=et;exports.createLocalJWKSet=Lr;exports.createRemoteJWKSet=Gr;exports.decodeJwt=zr;exports.decodeProtectedHeader=Fr;exports.errors=ft;exports.exportJWK=qe;exports.exportPKCS8=Cr;exports.exportSPKI=Hr;exports.flattenedDecrypt=Ee;exports.flattenedVerify=Ae;exports.generalDecrypt=Kr;exports.generalVerify=Jr;exports.generateKeyPair=Xr;exports.generateSecret=Yr;exports.importJWK=j;exports.importPKCS8=hr;exports.importSPKI=lr;exports.importX509=mr;exports.jwtDecrypt=Rr;exports.jwtVerify=Dr;})); \ No newline at end of file diff --git a/dist/browser/jwe/compact/decrypt.js b/dist/browser/jwe/compact/decrypt.js deleted file mode 100644 index 129aeb6e39..0000000000 --- a/dist/browser/jwe/compact/decrypt.js +++ /dev/null @@ -1,27 +0,0 @@ -import { flattenedDecrypt } from '../flattened/decrypt.js'; -import { JWEInvalid } from '../../util/errors.js'; -import { decoder } from '../../lib/buffer_utils.js'; -export async function compactDecrypt(jwe, key, options) { - if (jwe instanceof Uint8Array) { - jwe = decoder.decode(jwe); - } - if (typeof jwe !== 'string') { - throw new JWEInvalid('Compact JWE must be a string or Uint8Array'); - } - const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.'); - if (length !== 5) { - throw new JWEInvalid('Invalid Compact JWE'); - } - const decrypted = await flattenedDecrypt({ - ciphertext, - iv: (iv || undefined), - protected: protectedHeader || undefined, - tag: (tag || undefined), - encrypted_key: encryptedKey || undefined, - }, key, options); - const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: decrypted.key }; - } - return result; -} diff --git a/dist/browser/jwe/compact/encrypt.js b/dist/browser/jwe/compact/encrypt.js deleted file mode 100644 index e689139465..0000000000 --- a/dist/browser/jwe/compact/encrypt.js +++ /dev/null @@ -1,26 +0,0 @@ -import { FlattenedEncrypt } from '../flattened/encrypt.js'; -export class CompactEncrypt { - constructor(plaintext) { - this._flattened = new FlattenedEncrypt(plaintext); - } - setContentEncryptionKey(cek) { - this._flattened.setContentEncryptionKey(cek); - return this; - } - setInitializationVector(iv) { - this._flattened.setInitializationVector(iv); - return this; - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - setKeyManagementParameters(parameters) { - this._flattened.setKeyManagementParameters(parameters); - return this; - } - async encrypt(key, options) { - const jwe = await this._flattened.encrypt(key, options); - return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.'); - } -} diff --git a/dist/browser/jwe/flattened/decrypt.js b/dist/browser/jwe/flattened/decrypt.js deleted file mode 100644 index 2373a48f54..0000000000 --- a/dist/browser/jwe/flattened/decrypt.js +++ /dev/null @@ -1,137 +0,0 @@ -import { decode as base64url } from '../../runtime/base64url.js'; -import decrypt from '../../runtime/decrypt.js'; -import { inflate } from '../../runtime/zlib.js'; -import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import isObject from '../../lib/is_object.js'; -import decryptKeyManagement from '../../lib/decrypt_key_management.js'; -import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; -import generateCek from '../../lib/cek.js'; -import validateCrit from '../../lib/validate_crit.js'; -import validateAlgorithms from '../../lib/validate_algorithms.js'; -export async function flattenedDecrypt(jwe, key, options) { - var _a; - if (!isObject(jwe)) { - throw new JWEInvalid('Flattened JWE must be an object'); - } - if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { - throw new JWEInvalid('JOSE Header missing'); - } - if (typeof jwe.iv !== 'string') { - throw new JWEInvalid('JWE Initialization Vector missing or incorrect type'); - } - if (typeof jwe.ciphertext !== 'string') { - throw new JWEInvalid('JWE Ciphertext missing or incorrect type'); - } - if (typeof jwe.tag !== 'string') { - throw new JWEInvalid('JWE Authentication Tag missing or incorrect type'); - } - if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { - throw new JWEInvalid('JWE Protected Header incorrect type'); - } - if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { - throw new JWEInvalid('JWE Encrypted Key incorrect type'); - } - if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { - throw new JWEInvalid('JWE AAD incorrect type'); - } - if (jwe.header !== undefined && !isObject(jwe.header)) { - throw new JWEInvalid('JWE Shared Unprotected Header incorrect type'); - } - if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) { - throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type'); - } - let parsedProt; - if (jwe.protected) { - try { - const protectedHeader = base64url(jwe.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader)); - } - catch (_b) { - throw new JWEInvalid('JWE Protected Header is invalid'); - } - } - if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) { - throw new JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...parsedProt, - ...jwe.header, - ...jwe.unprotected, - }; - validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - if (joseHeader.zip !== undefined) { - if (!parsedProt || !parsedProt.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== 'DEF') { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header'); - } - if (typeof enc !== 'string' || !enc) { - throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header'); - } - const keyManagementAlgorithms = options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms); - const contentEncryptionAlgorithms = options && - validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms); - if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { - throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); - } - let encryptedKey; - if (jwe.encrypted_key !== undefined) { - encryptedKey = base64url(jwe.encrypted_key); - } - let resolvedKey = false; - if (typeof key === 'function') { - key = await key(parsedProt, jwe); - resolvedKey = true; - } - let cek; - try { - cek = await decryptKeyManagement(alg, key, encryptedKey, joseHeader, options); - } - catch (err) { - if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { - throw err; - } - cek = generateCek(enc); - } - const iv = base64url(jwe.iv); - const tag = base64url(jwe.tag); - const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ''); - let additionalData; - if (jwe.aad !== undefined) { - additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(jwe.aad)); - } - else { - additionalData = protectedHeader; - } - let plaintext = await decrypt(enc, cek, base64url(jwe.ciphertext), iv, tag, additionalData); - if (joseHeader.zip === 'DEF') { - plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); - } - const result = { plaintext }; - if (jwe.protected !== undefined) { - result.protectedHeader = parsedProt; - } - if (jwe.aad !== undefined) { - result.additionalAuthenticatedData = base64url(jwe.aad); - } - if (jwe.unprotected !== undefined) { - result.sharedUnprotectedHeader = jwe.unprotected; - } - if (jwe.header !== undefined) { - result.unprotectedHeader = jwe.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} diff --git a/dist/browser/jwe/flattened/encrypt.js b/dist/browser/jwe/flattened/encrypt.js deleted file mode 100644 index 1e60ecd8c4..0000000000 --- a/dist/browser/jwe/flattened/encrypt.js +++ /dev/null @@ -1,175 +0,0 @@ -import { encode as base64url } from '../../runtime/base64url.js'; -import encrypt from '../../runtime/encrypt.js'; -import { deflate } from '../../runtime/zlib.js'; -import generateIv from '../../lib/iv.js'; -import encryptKeyManagement from '../../lib/encrypt_key_management.js'; -import { JOSENotSupported, JWEInvalid } from '../../util/errors.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; -import validateCrit from '../../lib/validate_crit.js'; -export const unprotected = Symbol(); -export class FlattenedEncrypt { - constructor(plaintext) { - if (!(plaintext instanceof Uint8Array)) { - throw new TypeError('plaintext must be an instance of Uint8Array'); - } - this._plaintext = plaintext; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once'); - } - this._keyManagementParameters = parameters; - return this; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._sharedUnprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once'); - } - this._sharedUnprotectedHeader = sharedUnprotectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once'); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once'); - } - this._iv = iv; - return this; - } - async encrypt(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { - throw new JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()'); - } - if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { - throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...this._sharedUnprotectedHeader, - }; - validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== 'DEF') { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (typeof enc !== 'string' || !enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - let encryptedKey; - if (alg === 'dir') { - if (this._cek) { - throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption'); - } - } - else if (alg === 'ECDH-ES') { - if (this._cek) { - throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement'); - } - } - let cek; - { - let parameters; - ({ cek, encryptedKey, parameters } = await encryptKeyManagement(alg, enc, key, this._cek, this._keyManagementParameters)); - if (parameters) { - if (options && unprotected in options) { - if (!this._unprotectedHeader) { - this.setUnprotectedHeader(parameters); - } - else { - this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; - } - } - else { - if (!this._protectedHeader) { - this.setProtectedHeader(parameters); - } - else { - this._protectedHeader = { ...this._protectedHeader, ...parameters }; - } - } - } - } - this._iv || (this._iv = generateIv(enc)); - let additionalData; - let protectedHeader; - let aadMember; - if (this._protectedHeader) { - protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); - } - else { - protectedHeader = encoder.encode(''); - } - if (this._aad) { - aadMember = base64url(this._aad); - additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember)); - } - else { - additionalData = protectedHeader; - } - let ciphertext; - let tag; - if (joseHeader.zip === 'DEF') { - const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); - ({ ciphertext, tag } = await encrypt(enc, deflated, cek, this._iv, additionalData)); - } - else { - ; - ({ ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData)); - } - const jwe = { - ciphertext: base64url(ciphertext), - iv: base64url(this._iv), - tag: base64url(tag), - }; - if (encryptedKey) { - jwe.encrypted_key = base64url(encryptedKey); - } - if (aadMember) { - jwe.aad = aadMember; - } - if (this._protectedHeader) { - jwe.protected = decoder.decode(protectedHeader); - } - if (this._sharedUnprotectedHeader) { - jwe.unprotected = this._sharedUnprotectedHeader; - } - if (this._unprotectedHeader) { - jwe.header = this._unprotectedHeader; - } - return jwe; - } -} diff --git a/dist/browser/jwe/general/decrypt.js b/dist/browser/jwe/general/decrypt.js deleted file mode 100644 index d21b6d1fa8..0000000000 --- a/dist/browser/jwe/general/decrypt.js +++ /dev/null @@ -1,31 +0,0 @@ -import { flattenedDecrypt } from '../flattened/decrypt.js'; -import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.js'; -import isObject from '../../lib/is_object.js'; -export async function generalDecrypt(jwe, key, options) { - if (!isObject(jwe)) { - throw new JWEInvalid('General JWE must be an object'); - } - if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { - throw new JWEInvalid('JWE Recipients missing or incorrect type'); - } - if (!jwe.recipients.length) { - throw new JWEInvalid('JWE Recipients has no members'); - } - for (const recipient of jwe.recipients) { - try { - return await flattenedDecrypt({ - aad: jwe.aad, - ciphertext: jwe.ciphertext, - encrypted_key: recipient.encrypted_key, - header: recipient.header, - iv: jwe.iv, - protected: jwe.protected, - tag: jwe.tag, - unprotected: jwe.unprotected, - }, key, options); - } - catch (_a) { - } - } - throw new JWEDecryptionFailed(); -} diff --git a/dist/browser/jwe/general/encrypt.js b/dist/browser/jwe/general/encrypt.js deleted file mode 100644 index 3ee53dec44..0000000000 --- a/dist/browser/jwe/general/encrypt.js +++ /dev/null @@ -1,178 +0,0 @@ -import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.js'; -import { JWEInvalid } from '../../util/errors.js'; -import generateCek from '../../lib/cek.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import encryptKeyManagement from '../../lib/encrypt_key_management.js'; -import { encode as base64url } from '../../runtime/base64url.js'; -import validateCrit from '../../lib/validate_crit.js'; -class IndividualRecipient { - constructor(enc, key, options) { - this.parent = enc; - this.key = key; - this.options = options; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addRecipient(...args) { - return this.parent.addRecipient(...args); - } - encrypt(...args) { - return this.parent.encrypt(...args); - } - done() { - return this.parent; - } -} -export class GeneralEncrypt { - constructor(plaintext) { - this._recipients = []; - this._plaintext = plaintext; - } - addRecipient(key, options) { - const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); - this._recipients.push(recipient); - return recipient; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = sharedUnprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - async encrypt(options) { - var _a, _b, _c; - if (!this._recipients.length) { - throw new JWEInvalid('at least one recipient must be added'); - } - options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; - if (this._recipients.length === 1) { - const [recipient] = this._recipients; - const flattened = await new FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader) - .encrypt(recipient.key, { ...recipient.options, ...options }); - let jwe = { - ciphertext: flattened.ciphertext, - iv: flattened.iv, - recipients: [{}], - tag: flattened.tag, - }; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - if (flattened.encrypted_key) - jwe.recipients[0].encrypted_key = flattened.encrypted_key; - if (flattened.header) - jwe.recipients[0].header = flattened.header; - return jwe; - } - let enc; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { - throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - }; - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (alg === 'dir' || alg === 'ECDH-ES') { - throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); - } - if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - if (!enc) { - enc = joseHeader.enc; - } - else if (enc !== joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); - } - validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - } - } - const cek = generateCek(enc); - let jwe = { - ciphertext: '', - iv: '', - recipients: [], - tag: '', - }; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - const target = {}; - jwe.recipients.push(target); - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - }; - const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined; - if (i === 0) { - const flattened = await new FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setContentEncryptionKey(cek) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader) - .setKeyManagementParameters({ p2c }) - .encrypt(recipient.key, { - ...recipient.options, - ...options, - [unprotected]: true, - }); - jwe.ciphertext = flattened.ciphertext; - jwe.iv = flattened.iv; - jwe.tag = flattened.tag; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - target.encrypted_key = flattened.encrypted_key; - if (flattened.header) - target.header = flattened.header; - continue; - } - const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || - ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || - ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); - target.encrypted_key = base64url(encryptedKey); - if (recipient.unprotectedHeader || parameters) - target.header = { ...recipient.unprotectedHeader, ...parameters }; - } - return jwe; - } -} diff --git a/dist/browser/jwk/embedded.js b/dist/browser/jwk/embedded.js deleted file mode 100644 index 58db282552..0000000000 --- a/dist/browser/jwk/embedded.js +++ /dev/null @@ -1,17 +0,0 @@ -import { importJWK } from '../key/import.js'; -import isObject from '../lib/is_object.js'; -import { JWSInvalid } from '../util/errors.js'; -export async function EmbeddedJWK(protectedHeader, token) { - const joseHeader = { - ...protectedHeader, - ...token.header, - }; - if (!isObject(joseHeader.jwk)) { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); - } - const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); - if (key instanceof Uint8Array || key.type !== 'public') { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); - } - return key; -} diff --git a/dist/browser/jwk/thumbprint.js b/dist/browser/jwk/thumbprint.js deleted file mode 100644 index 49f86b1743..0000000000 --- a/dist/browser/jwk/thumbprint.js +++ /dev/null @@ -1,53 +0,0 @@ -import digest from '../runtime/digest.js'; -import { encode as base64url } from '../runtime/base64url.js'; -import { JOSENotSupported, JWKInvalid } from '../util/errors.js'; -import { encoder } from '../lib/buffer_utils.js'; -import isObject from '../lib/is_object.js'; -const check = (value, description) => { - if (typeof value !== 'string' || !value) { - throw new JWKInvalid(`${description} missing or invalid`); - } -}; -export async function calculateJwkThumbprint(jwk, digestAlgorithm) { - if (!isObject(jwk)) { - throw new TypeError('JWK must be an object'); - } - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); - if (digestAlgorithm !== 'sha256' && - digestAlgorithm !== 'sha384' && - digestAlgorithm !== 'sha512') { - throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); - } - let components; - switch (jwk.kty) { - case 'EC': - check(jwk.crv, '"crv" (Curve) Parameter'); - check(jwk.x, '"x" (X Coordinate) Parameter'); - check(jwk.y, '"y" (Y Coordinate) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; - break; - case 'OKP': - check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); - check(jwk.x, '"x" (Public Key) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; - break; - case 'RSA': - check(jwk.e, '"e" (Exponent) Parameter'); - check(jwk.n, '"n" (Modulus) Parameter'); - components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; - break; - case 'oct': - check(jwk.k, '"k" (Key Value) Parameter'); - components = { k: jwk.k, kty: jwk.kty }; - break; - default: - throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); - } - const data = encoder.encode(JSON.stringify(components)); - return base64url(await digest(digestAlgorithm, data)); -} -export async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); - const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); - return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; -} diff --git a/dist/browser/jwks/local.js b/dist/browser/jwks/local.js deleted file mode 100644 index a6763bb49f..0000000000 --- a/dist/browser/jwks/local.js +++ /dev/null @@ -1,113 +0,0 @@ -import { importJWK } from '../key/import.js'; -import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js'; -import isObject from '../lib/is_object.js'; -function getKtyFromAlg(alg) { - switch (typeof alg === 'string' && alg.slice(0, 2)) { - case 'RS': - case 'PS': - return 'RSA'; - case 'ES': - return 'EC'; - case 'Ed': - return 'OKP'; - default: - throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); - } -} -export function isJWKSLike(jwks) { - return (jwks && - typeof jwks === 'object' && - Array.isArray(jwks.keys) && - jwks.keys.every(isJWKLike)); -} -function isJWKLike(key) { - return isObject(key); -} -function clone(obj) { - if (typeof structuredClone === 'function') { - return structuredClone(obj); - } - return JSON.parse(JSON.stringify(obj)); -} -export class LocalJWKSet { - constructor(jwks) { - this._cached = new WeakMap(); - if (!isJWKSLike(jwks)) { - throw new JWKSInvalid('JSON Web Key Set malformed'); - } - this._jwks = clone(jwks); - } - async getKey(protectedHeader, token) { - const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; - const kty = getKtyFromAlg(alg); - const candidates = this._jwks.keys.filter((jwk) => { - let candidate = kty === jwk.kty; - if (candidate && typeof kid === 'string') { - candidate = kid === jwk.kid; - } - if (candidate && typeof jwk.alg === 'string') { - candidate = alg === jwk.alg; - } - if (candidate && typeof jwk.use === 'string') { - candidate = jwk.use === 'sig'; - } - if (candidate && Array.isArray(jwk.key_ops)) { - candidate = jwk.key_ops.includes('verify'); - } - if (candidate && alg === 'EdDSA') { - candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'; - } - if (candidate) { - switch (alg) { - case 'ES256': - candidate = jwk.crv === 'P-256'; - break; - case 'ES256K': - candidate = jwk.crv === 'secp256k1'; - break; - case 'ES384': - candidate = jwk.crv === 'P-384'; - break; - case 'ES512': - candidate = jwk.crv === 'P-521'; - break; - } - } - return candidate; - }); - const { 0: jwk, length } = candidates; - if (length === 0) { - throw new JWKSNoMatchingKey(); - } - else if (length !== 1) { - const error = new JWKSMultipleMatchingKeys(); - const { _cached } = this; - error[Symbol.asyncIterator] = async function* () { - for (const jwk of candidates) { - try { - yield await importWithAlgCache(_cached, jwk, alg); - } - catch (_a) { - continue; - } - } - }; - throw error; - } - return importWithAlgCache(this._cached, jwk, alg); - } -} -async function importWithAlgCache(cache, jwk, alg) { - const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); - if (cached[alg] === undefined) { - const keyObject = await importJWK({ ...jwk, ext: true }, alg); - if (keyObject.type !== 'public') { - throw new JWKSInvalid('JSON Web Key Set members must be public keys'); - } - cached[alg] = keyObject; - } - return cached[alg]; -} -export function createLocalJWKSet(jwks) { - return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); -} diff --git a/dist/browser/jwks/remote.js b/dist/browser/jwks/remote.js deleted file mode 100644 index 574ccff83b..0000000000 --- a/dist/browser/jwks/remote.js +++ /dev/null @@ -1,81 +0,0 @@ -import fetchJwks from '../runtime/fetch_jwks.js'; -import { isCloudflareWorkers } from '../runtime/env.js'; -import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.js'; -import { isJWKSLike, LocalJWKSet } from './local.js'; -class RemoteJWKSet extends LocalJWKSet { - constructor(url, options) { - super({ keys: [] }); - this._jwks = undefined; - if (!(url instanceof URL)) { - throw new TypeError('url must be an instance of URL'); - } - this._url = new URL(url.href); - this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; - this._timeoutDuration = - typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000; - this._cooldownDuration = - typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000; - this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000; - } - coolingDown() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cooldownDuration - : false; - } - fresh() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cacheMaxAge - : false; - } - async getKey(protectedHeader, token) { - if (!this._jwks || !this.fresh()) { - await this.reload(); - } - try { - return await super.getKey(protectedHeader, token); - } - catch (err) { - if (err instanceof JWKSNoMatchingKey) { - if (this.coolingDown() === false) { - await this.reload(); - return super.getKey(protectedHeader, token); - } - } - throw err; - } - } - async reload() { - if (this._pendingFetch && isCloudflareWorkers()) { - return new Promise((resolve) => { - const isDone = () => { - if (this._pendingFetch === undefined) { - resolve(); - } - else { - setTimeout(isDone, 5); - } - }; - isDone(); - }); - } - if (!this._pendingFetch) { - this._pendingFetch = fetchJwks(this._url, this._timeoutDuration, this._options) - .then((json) => { - if (!isJWKSLike(json)) { - throw new JWKSInvalid('JSON Web Key Set malformed'); - } - this._jwks = { keys: json.keys }; - this._jwksTimestamp = Date.now(); - this._pendingFetch = undefined; - }) - .catch((err) => { - this._pendingFetch = undefined; - throw err; - }); - } - await this._pendingFetch; - } -} -export function createRemoteJWKSet(url, options) { - return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); -} diff --git a/dist/browser/jws/compact/sign.js b/dist/browser/jws/compact/sign.js deleted file mode 100644 index b8e5ba0e2b..0000000000 --- a/dist/browser/jws/compact/sign.js +++ /dev/null @@ -1,17 +0,0 @@ -import { FlattenedSign } from '../flattened/sign.js'; -export class CompactSign { - constructor(payload) { - this._flattened = new FlattenedSign(payload); - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - async sign(key, options) { - const jws = await this._flattened.sign(key, options); - if (jws.payload === undefined) { - throw new TypeError('use the flattened module for creating JWS with b64: false'); - } - return `${jws.protected}.${jws.payload}.${jws.signature}`; - } -} diff --git a/dist/browser/jws/compact/verify.js b/dist/browser/jws/compact/verify.js deleted file mode 100644 index c651ffb944..0000000000 --- a/dist/browser/jws/compact/verify.js +++ /dev/null @@ -1,21 +0,0 @@ -import { flattenedVerify } from '../flattened/verify.js'; -import { JWSInvalid } from '../../util/errors.js'; -import { decoder } from '../../lib/buffer_utils.js'; -export async function compactVerify(jws, key, options) { - if (jws instanceof Uint8Array) { - jws = decoder.decode(jws); - } - if (typeof jws !== 'string') { - throw new JWSInvalid('Compact JWS must be a string or Uint8Array'); - } - const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.'); - if (length !== 3) { - throw new JWSInvalid('Invalid Compact JWS'); - } - const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); - const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: verified.key }; - } - return result; -} diff --git a/dist/browser/jws/flattened/sign.js b/dist/browser/jws/flattened/sign.js deleted file mode 100644 index 76ae289654..0000000000 --- a/dist/browser/jws/flattened/sign.js +++ /dev/null @@ -1,81 +0,0 @@ -import { encode as base64url } from '../../runtime/base64url.js'; -import sign from '../../runtime/sign.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import { JWSInvalid } from '../../util/errors.js'; -import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; -import checkKeyType from '../../lib/check_key_type.js'; -import validateCrit from '../../lib/validate_crit.js'; -export class FlattenedSign { - constructor(payload) { - if (!(payload instanceof Uint8Array)) { - throw new TypeError('payload must be an instance of Uint8Array'); - } - this._payload = payload; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - async sign(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader) { - throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); - } - if (!isDisjoint(this._protectedHeader, this._unprotectedHeader)) { - throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - }; - const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - let b64 = true; - if (extensions.has('b64')) { - b64 = this._protectedHeader.b64; - if (typeof b64 !== 'boolean') { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - checkKeyType(alg, key, 'sign'); - let payload = this._payload; - if (b64) { - payload = encoder.encode(base64url(payload)); - } - let protectedHeader; - if (this._protectedHeader) { - protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); - } - else { - protectedHeader = encoder.encode(''); - } - const data = concat(protectedHeader, encoder.encode('.'), payload); - const signature = await sign(alg, key, data); - const jws = { - signature: base64url(signature), - payload: '', - }; - if (b64) { - jws.payload = decoder.decode(payload); - } - if (this._unprotectedHeader) { - jws.header = this._unprotectedHeader; - } - if (this._protectedHeader) { - jws.protected = decoder.decode(protectedHeader); - } - return jws; - } -} diff --git a/dist/browser/jws/flattened/verify.js b/dist/browser/jws/flattened/verify.js deleted file mode 100644 index a55287ed8e..0000000000 --- a/dist/browser/jws/flattened/verify.js +++ /dev/null @@ -1,104 +0,0 @@ -import { decode as base64url } from '../../runtime/base64url.js'; -import verify from '../../runtime/verify.js'; -import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; -import { concat, encoder, decoder } from '../../lib/buffer_utils.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import isObject from '../../lib/is_object.js'; -import checkKeyType from '../../lib/check_key_type.js'; -import validateCrit from '../../lib/validate_crit.js'; -import validateAlgorithms from '../../lib/validate_algorithms.js'; -export async function flattenedVerify(jws, key, options) { - var _a; - if (!isObject(jws)) { - throw new JWSInvalid('Flattened JWS must be an object'); - } - if (jws.protected === undefined && jws.header === undefined) { - throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); - } - if (jws.protected !== undefined && typeof jws.protected !== 'string') { - throw new JWSInvalid('JWS Protected Header incorrect type'); - } - if (jws.payload === undefined) { - throw new JWSInvalid('JWS Payload missing'); - } - if (typeof jws.signature !== 'string') { - throw new JWSInvalid('JWS Signature missing or incorrect type'); - } - if (jws.header !== undefined && !isObject(jws.header)) { - throw new JWSInvalid('JWS Unprotected Header incorrect type'); - } - let parsedProt = {}; - if (jws.protected) { - try { - const protectedHeader = base64url(jws.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader)); - } - catch (_b) { - throw new JWSInvalid('JWS Protected Header is invalid'); - } - } - if (!isDisjoint(parsedProt, jws.header)) { - throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...parsedProt, - ...jws.header, - }; - const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - let b64 = true; - if (extensions.has('b64')) { - b64 = parsedProt.b64; - if (typeof b64 !== 'boolean') { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - const algorithms = options && validateAlgorithms('algorithms', options.algorithms); - if (algorithms && !algorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (b64) { - if (typeof jws.payload !== 'string') { - throw new JWSInvalid('JWS Payload must be a string'); - } - } - else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { - throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance'); - } - let resolvedKey = false; - if (typeof key === 'function') { - key = await key(parsedProt, jws); - resolvedKey = true; - } - checkKeyType(alg, key, 'verify'); - const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload); - const signature = base64url(jws.signature); - const verified = await verify(alg, key, signature, data); - if (!verified) { - throw new JWSSignatureVerificationFailed(); - } - let payload; - if (b64) { - payload = base64url(jws.payload); - } - else if (typeof jws.payload === 'string') { - payload = encoder.encode(jws.payload); - } - else { - payload = jws.payload; - } - const result = { payload }; - if (jws.protected !== undefined) { - result.protectedHeader = parsedProt; - } - if (jws.header !== undefined) { - result.unprotectedHeader = jws.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} diff --git a/dist/browser/jws/general/sign.js b/dist/browser/jws/general/sign.js deleted file mode 100644 index 38d5a6d766..0000000000 --- a/dist/browser/jws/general/sign.js +++ /dev/null @@ -1,67 +0,0 @@ -import { FlattenedSign } from '../flattened/sign.js'; -import { JWSInvalid } from '../../util/errors.js'; -class IndividualSignature { - constructor(sig, key, options) { - this.parent = sig; - this.key = key; - this.options = options; - } - setProtectedHeader(protectedHeader) { - if (this.protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this.protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addSignature(...args) { - return this.parent.addSignature(...args); - } - sign(...args) { - return this.parent.sign(...args); - } - done() { - return this.parent; - } -} -export class GeneralSign { - constructor(payload) { - this._signatures = []; - this._payload = payload; - } - addSignature(key, options) { - const signature = new IndividualSignature(this, key, options); - this._signatures.push(signature); - return signature; - } - async sign() { - if (!this._signatures.length) { - throw new JWSInvalid('at least one signature must be added'); - } - const jws = { - signatures: [], - payload: '', - }; - for (let i = 0; i < this._signatures.length; i++) { - const signature = this._signatures[i]; - const flattened = new FlattenedSign(this._payload); - flattened.setProtectedHeader(signature.protectedHeader); - flattened.setUnprotectedHeader(signature.unprotectedHeader); - const { payload, ...rest } = await flattened.sign(signature.key, signature.options); - if (i === 0) { - jws.payload = payload; - } - else if (jws.payload !== payload) { - throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)'); - } - jws.signatures.push(rest); - } - return jws; - } -} diff --git a/dist/browser/jws/general/verify.js b/dist/browser/jws/general/verify.js deleted file mode 100644 index 459090afee..0000000000 --- a/dist/browser/jws/general/verify.js +++ /dev/null @@ -1,24 +0,0 @@ -import { flattenedVerify } from '../flattened/verify.js'; -import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; -import isObject from '../../lib/is_object.js'; -export async function generalVerify(jws, key, options) { - if (!isObject(jws)) { - throw new JWSInvalid('General JWS must be an object'); - } - if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { - throw new JWSInvalid('JWS Signatures missing or incorrect type'); - } - for (const signature of jws.signatures) { - try { - return await flattenedVerify({ - header: signature.header, - payload: jws.payload, - protected: signature.protected, - signature: signature.signature, - }, key, options); - } - catch (_a) { - } - } - throw new JWSSignatureVerificationFailed(); -} diff --git a/dist/browser/jwt/decrypt.js b/dist/browser/jwt/decrypt.js deleted file mode 100644 index 1ec2be28f2..0000000000 --- a/dist/browser/jwt/decrypt.js +++ /dev/null @@ -1,23 +0,0 @@ -import { compactDecrypt } from '../jwe/compact/decrypt.js'; -import jwtPayload from '../lib/jwt_claims_set.js'; -import { JWTClaimValidationFailed } from '../util/errors.js'; -export async function jwtDecrypt(jwt, key, options) { - const decrypted = await compactDecrypt(jwt, key, options); - const payload = jwtPayload(decrypted.protectedHeader, decrypted.plaintext, options); - const { protectedHeader } = decrypted; - if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { - throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', 'iss', 'mismatch'); - } - if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { - throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', 'sub', 'mismatch'); - } - if (protectedHeader.aud !== undefined && - JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { - throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch'); - } - const result = { payload, protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: decrypted.key }; - } - return result; -} diff --git a/dist/browser/jwt/encrypt.js b/dist/browser/jwt/encrypt.js deleted file mode 100644 index 15252957ae..0000000000 --- a/dist/browser/jwt/encrypt.js +++ /dev/null @@ -1,68 +0,0 @@ -import { CompactEncrypt } from '../jwe/compact/encrypt.js'; -import { encoder } from '../lib/buffer_utils.js'; -import { ProduceJWT } from './produce.js'; -export class EncryptJWT extends ProduceJWT { - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once'); - } - this._keyManagementParameters = parameters; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once'); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once'); - } - this._iv = iv; - return this; - } - replicateIssuerAsHeader() { - this._replicateIssuerAsHeader = true; - return this; - } - replicateSubjectAsHeader() { - this._replicateSubjectAsHeader = true; - return this; - } - replicateAudienceAsHeader() { - this._replicateAudienceAsHeader = true; - return this; - } - async encrypt(key, options) { - const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); - if (this._replicateIssuerAsHeader) { - this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; - } - if (this._replicateSubjectAsHeader) { - this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; - } - if (this._replicateAudienceAsHeader) { - this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; - } - enc.setProtectedHeader(this._protectedHeader); - if (this._iv) { - enc.setInitializationVector(this._iv); - } - if (this._cek) { - enc.setContentEncryptionKey(this._cek); - } - if (this._keyManagementParameters) { - enc.setKeyManagementParameters(this._keyManagementParameters); - } - return enc.encrypt(key, options); - } -} diff --git a/dist/browser/jwt/produce.js b/dist/browser/jwt/produce.js deleted file mode 100644 index 31c929a07c..0000000000 --- a/dist/browser/jwt/produce.js +++ /dev/null @@ -1,54 +0,0 @@ -import epoch from '../lib/epoch.js'; -import isObject from '../lib/is_object.js'; -import secs from '../lib/secs.js'; -export class ProduceJWT { - constructor(payload) { - if (!isObject(payload)) { - throw new TypeError('JWT Claims Set MUST be an object'); - } - this._payload = payload; - } - setIssuer(issuer) { - this._payload = { ...this._payload, iss: issuer }; - return this; - } - setSubject(subject) { - this._payload = { ...this._payload, sub: subject }; - return this; - } - setAudience(audience) { - this._payload = { ...this._payload, aud: audience }; - return this; - } - setJti(jwtId) { - this._payload = { ...this._payload, jti: jwtId }; - return this; - } - setNotBefore(input) { - if (typeof input === 'number') { - this._payload = { ...this._payload, nbf: input }; - } - else { - this._payload = { ...this._payload, nbf: epoch(new Date()) + secs(input) }; - } - return this; - } - setExpirationTime(input) { - if (typeof input === 'number') { - this._payload = { ...this._payload, exp: input }; - } - else { - this._payload = { ...this._payload, exp: epoch(new Date()) + secs(input) }; - } - return this; - } - setIssuedAt(input) { - if (typeof input === 'undefined') { - this._payload = { ...this._payload, iat: epoch(new Date()) }; - } - else { - this._payload = { ...this._payload, iat: input }; - } - return this; - } -} diff --git a/dist/browser/jwt/sign.js b/dist/browser/jwt/sign.js deleted file mode 100644 index 62352fbfa2..0000000000 --- a/dist/browser/jwt/sign.js +++ /dev/null @@ -1,21 +0,0 @@ -import { CompactSign } from '../jws/compact/sign.js'; -import { JWTInvalid } from '../util/errors.js'; -import { encoder } from '../lib/buffer_utils.js'; -import { ProduceJWT } from './produce.js'; -export class SignJWT extends ProduceJWT { - setProtectedHeader(protectedHeader) { - this._protectedHeader = protectedHeader; - return this; - } - async sign(key, options) { - var _a; - const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); - sig.setProtectedHeader(this._protectedHeader); - if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && - this._protectedHeader.crit.includes('b64') && - this._protectedHeader.b64 === false) { - throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); - } - return sig.sign(key, options); - } -} diff --git a/dist/browser/jwt/unsecured.js b/dist/browser/jwt/unsecured.js deleted file mode 100644 index b0276512fb..0000000000 --- a/dist/browser/jwt/unsecured.js +++ /dev/null @@ -1,32 +0,0 @@ -import * as base64url from '../runtime/base64url.js'; -import { decoder } from '../lib/buffer_utils.js'; -import { JWTInvalid } from '../util/errors.js'; -import jwtPayload from '../lib/jwt_claims_set.js'; -import { ProduceJWT } from './produce.js'; -export class UnsecuredJWT extends ProduceJWT { - encode() { - const header = base64url.encode(JSON.stringify({ alg: 'none' })); - const payload = base64url.encode(JSON.stringify(this._payload)); - return `${header}.${payload}.`; - } - static decode(jwt, options) { - if (typeof jwt !== 'string') { - throw new JWTInvalid('Unsecured JWT must be a string'); - } - const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.'); - if (length !== 3 || signature !== '') { - throw new JWTInvalid('Invalid Unsecured JWT'); - } - let header; - try { - header = JSON.parse(decoder.decode(base64url.decode(encodedHeader))); - if (header.alg !== 'none') - throw new Error(); - } - catch (_a) { - throw new JWTInvalid('Invalid Unsecured JWT'); - } - const payload = jwtPayload(header, base64url.decode(encodedPayload), options); - return { payload, header }; - } -} diff --git a/dist/browser/jwt/verify.js b/dist/browser/jwt/verify.js deleted file mode 100644 index 89571c1847..0000000000 --- a/dist/browser/jwt/verify.js +++ /dev/null @@ -1,16 +0,0 @@ -import { compactVerify } from '../jws/compact/verify.js'; -import jwtPayload from '../lib/jwt_claims_set.js'; -import { JWTInvalid } from '../util/errors.js'; -export async function jwtVerify(jwt, key, options) { - var _a; - const verified = await compactVerify(jwt, key, options); - if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { - throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); - } - const payload = jwtPayload(verified.protectedHeader, verified.payload, options); - const result = { payload, protectedHeader: verified.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: verified.key }; - } - return result; -} diff --git a/dist/browser/key/export.js b/dist/browser/key/export.js deleted file mode 100644 index e4017047cd..0000000000 --- a/dist/browser/key/export.js +++ /dev/null @@ -1,12 +0,0 @@ -import { toSPKI as exportPublic } from '../runtime/asn1.js'; -import { toPKCS8 as exportPrivate } from '../runtime/asn1.js'; -import keyToJWK from '../runtime/key_to_jwk.js'; -export async function exportSPKI(key) { - return exportPublic(key); -} -export async function exportPKCS8(key) { - return exportPrivate(key); -} -export async function exportJWK(key) { - return keyToJWK(key); -} diff --git a/dist/browser/key/generate_key_pair.js b/dist/browser/key/generate_key_pair.js deleted file mode 100644 index 03b9ee54cd..0000000000 --- a/dist/browser/key/generate_key_pair.js +++ /dev/null @@ -1,4 +0,0 @@ -import { generateKeyPair as generate } from '../runtime/generate.js'; -export async function generateKeyPair(alg, options) { - return generate(alg, options); -} diff --git a/dist/browser/key/generate_secret.js b/dist/browser/key/generate_secret.js deleted file mode 100644 index 58f308a543..0000000000 --- a/dist/browser/key/generate_secret.js +++ /dev/null @@ -1,4 +0,0 @@ -import { generateSecret as generate } from '../runtime/generate.js'; -export async function generateSecret(alg, options) { - return generate(alg, options); -} diff --git a/dist/browser/key/import.js b/dist/browser/key/import.js deleted file mode 100644 index 25bb0e1659..0000000000 --- a/dist/browser/key/import.js +++ /dev/null @@ -1,50 +0,0 @@ -import { decode as decodeBase64URL } from '../runtime/base64url.js'; -import { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.js'; -import asKeyObject from '../runtime/jwk_to_key.js'; -import { JOSENotSupported } from '../util/errors.js'; -import isObject from '../lib/is_object.js'; -export async function importSPKI(spki, alg, options) { - if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { - throw new TypeError('"spki" must be SPKI formatted string'); - } - return fromSPKI(spki, alg, options); -} -export async function importX509(x509, alg, options) { - if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { - throw new TypeError('"x509" must be X.509 formatted string'); - } - return fromX509(x509, alg, options); -} -export async function importPKCS8(pkcs8, alg, options) { - if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { - throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); - } - return fromPKCS8(pkcs8, alg, options); -} -export async function importJWK(jwk, alg, octAsKeyObject) { - var _a; - if (!isObject(jwk)) { - throw new TypeError('JWK must be an object'); - } - alg || (alg = jwk.alg); - switch (jwk.kty) { - case 'oct': - if (typeof jwk.k !== 'string' || !jwk.k) { - throw new TypeError('missing "k" (Key Value) Parameter value'); - } - octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true); - if (octAsKeyObject) { - return asKeyObject({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); - } - return decodeBase64URL(jwk.k); - case 'RSA': - if (jwk.oth !== undefined) { - throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); - } - case 'EC': - case 'OKP': - return asKeyObject({ ...jwk, alg }); - default: - throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); - } -} diff --git a/dist/browser/lib/aesgcmkw.js b/dist/browser/lib/aesgcmkw.js deleted file mode 100644 index de3f4f91df..0000000000 --- a/dist/browser/lib/aesgcmkw.js +++ /dev/null @@ -1,14 +0,0 @@ -import encrypt from '../runtime/encrypt.js'; -import decrypt from '../runtime/decrypt.js'; -import generateIv from './iv.js'; -import { encode as base64url } from '../runtime/base64url.js'; -export async function wrap(alg, key, cek, iv) { - const jweAlgorithm = alg.slice(0, 7); - iv || (iv = generateIv(jweAlgorithm)); - const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0)); - return { encryptedKey, iv: base64url(iv), tag: base64url(tag) }; -} -export async function unwrap(alg, key, encryptedKey, iv, tag) { - const jweAlgorithm = alg.slice(0, 7); - return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); -} diff --git a/dist/browser/lib/buffer_utils.js b/dist/browser/lib/buffer_utils.js deleted file mode 100644 index 5a1a7b334d..0000000000 --- a/dist/browser/lib/buffer_utils.js +++ /dev/null @@ -1,51 +0,0 @@ -import digest from '../runtime/digest.js'; -export const encoder = new TextEncoder(); -export const decoder = new TextDecoder(); -const MAX_INT32 = 2 ** 32; -export function concat(...buffers) { - const size = buffers.reduce((acc, { length }) => acc + length, 0); - const buf = new Uint8Array(size); - let i = 0; - buffers.forEach((buffer) => { - buf.set(buffer, i); - i += buffer.length; - }); - return buf; -} -export function p2s(alg, p2sInput) { - return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); -} -function writeUInt32BE(buf, value, offset) { - if (value < 0 || value >= MAX_INT32) { - throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); - } - buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset); -} -export function uint64be(value) { - const high = Math.floor(value / MAX_INT32); - const low = value % MAX_INT32; - const buf = new Uint8Array(8); - writeUInt32BE(buf, high, 0); - writeUInt32BE(buf, low, 4); - return buf; -} -export function uint32be(value) { - const buf = new Uint8Array(4); - writeUInt32BE(buf, value); - return buf; -} -export function lengthAndInput(input) { - return concat(uint32be(input.length), input); -} -export async function concatKdf(secret, bits, value) { - const iterations = Math.ceil((bits >> 3) / 32); - const res = new Uint8Array(iterations * 32); - for (let iter = 0; iter < iterations; iter++) { - const buf = new Uint8Array(4 + secret.length + value.length); - buf.set(uint32be(iter + 1)); - buf.set(secret, 4); - buf.set(value, 4 + secret.length); - res.set(await digest('sha256', buf), iter * 32); - } - return res.slice(0, bits >> 3); -} diff --git a/dist/browser/lib/cek.js b/dist/browser/lib/cek.js deleted file mode 100644 index 34697d3ac2..0000000000 --- a/dist/browser/lib/cek.js +++ /dev/null @@ -1,20 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -import random from '../runtime/random.js'; -export function bitLength(alg) { - switch (alg) { - case 'A128GCM': - return 128; - case 'A192GCM': - return 192; - case 'A256GCM': - case 'A128CBC-HS256': - return 256; - case 'A192CBC-HS384': - return 384; - case 'A256CBC-HS512': - return 512; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/browser/lib/check_iv_length.js b/dist/browser/lib/check_iv_length.js deleted file mode 100644 index dcd28d3a9d..0000000000 --- a/dist/browser/lib/check_iv_length.js +++ /dev/null @@ -1,8 +0,0 @@ -import { JWEInvalid } from '../util/errors.js'; -import { bitLength } from './iv.js'; -const checkIvLength = (enc, iv) => { - if (iv.length << 3 !== bitLength(enc)) { - throw new JWEInvalid('Invalid Initialization Vector length'); - } -}; -export default checkIvLength; diff --git a/dist/browser/lib/check_key_type.js b/dist/browser/lib/check_key_type.js deleted file mode 100644 index 43f3dcbf14..0000000000 --- a/dist/browser/lib/check_key_type.js +++ /dev/null @@ -1,45 +0,0 @@ -import { withAlg as invalidKeyInput } from './invalid_key_input.js'; -import isKeyLike, { types } from '../runtime/is_key_like.js'; -const symmetricTypeCheck = (alg, key) => { - if (key instanceof Uint8Array) - return; - if (!isKeyLike(key)) { - throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array')); - } - if (key.type !== 'secret') { - throw new TypeError(`${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`); - } -}; -const asymmetricTypeCheck = (alg, key, usage) => { - if (!isKeyLike(key)) { - throw new TypeError(invalidKeyInput(alg, key, ...types)); - } - if (key.type === 'secret') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`); - } - if (usage === 'sign' && key.type === 'public') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`); - } - if (usage === 'decrypt' && key.type === 'public') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`); - } - if (key.algorithm && usage === 'verify' && key.type === 'private') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`); - } - if (key.algorithm && usage === 'encrypt' && key.type === 'private') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`); - } -}; -const checkKeyType = (alg, key, usage) => { - const symmetric = alg.startsWith('HS') || - alg === 'dir' || - alg.startsWith('PBES2') || - /^A\d{3}(?:GCM)?KW$/.test(alg); - if (symmetric) { - symmetricTypeCheck(alg, key); - } - else { - asymmetricTypeCheck(alg, key, usage); - } -}; -export default checkKeyType; diff --git a/dist/browser/lib/check_p2s.js b/dist/browser/lib/check_p2s.js deleted file mode 100644 index a65289fa7a..0000000000 --- a/dist/browser/lib/check_p2s.js +++ /dev/null @@ -1,6 +0,0 @@ -import { JWEInvalid } from '../util/errors.js'; -export default function checkP2s(p2s) { - if (!(p2s instanceof Uint8Array) || p2s.length < 8) { - throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets'); - } -} diff --git a/dist/browser/lib/crypto_key.js b/dist/browser/lib/crypto_key.js deleted file mode 100644 index 4405b1915c..0000000000 --- a/dist/browser/lib/crypto_key.js +++ /dev/null @@ -1,158 +0,0 @@ -import { isCloudflareWorkers } from '../runtime/env.js'; -function unusable(name, prop = 'algorithm.name') { - return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); -} -function isAlgorithm(algorithm, name) { - return algorithm.name === name; -} -function getHashLength(hash) { - return parseInt(hash.name.slice(4), 10); -} -function getNamedCurve(alg) { - switch (alg) { - case 'ES256': - return 'P-256'; - case 'ES384': - return 'P-384'; - case 'ES512': - return 'P-521'; - default: - throw new Error('unreachable'); - } -} -function checkUsage(key, usages) { - if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { - let msg = 'CryptoKey does not support this operation, its usages must include '; - if (usages.length > 2) { - const last = usages.pop(); - msg += `one of ${usages.join(', ')}, or ${last}.`; - } - else if (usages.length === 2) { - msg += `one of ${usages[0]} or ${usages[1]}.`; - } - else { - msg += `${usages[0]}.`; - } - throw new TypeError(msg); - } -} -export function checkSigCryptoKey(key, alg, ...usages) { - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': { - if (!isAlgorithm(key.algorithm, 'HMAC')) - throw unusable('HMAC'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'RS256': - case 'RS384': - case 'RS512': { - if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) - throw unusable('RSASSA-PKCS1-v1_5'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'PS256': - case 'PS384': - case 'PS512': { - if (!isAlgorithm(key.algorithm, 'RSA-PSS')) - throw unusable('RSA-PSS'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'EdDSA': { - if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { - if (isCloudflareWorkers()) { - if (isAlgorithm(key.algorithm, 'NODE-ED25519')) - break; - throw unusable('Ed25519, Ed448, or NODE-ED25519'); - } - throw unusable('Ed25519 or Ed448'); - } - break; - } - case 'ES256': - case 'ES384': - case 'ES512': { - if (!isAlgorithm(key.algorithm, 'ECDSA')) - throw unusable('ECDSA'); - const expected = getNamedCurve(alg); - const actual = key.algorithm.namedCurve; - if (actual !== expected) - throw unusable(expected, 'algorithm.namedCurve'); - break; - } - default: - throw new TypeError('CryptoKey does not support this operation'); - } - checkUsage(key, usages); -} -export function checkEncCryptoKey(key, alg, ...usages) { - switch (alg) { - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': { - if (!isAlgorithm(key.algorithm, 'AES-GCM')) - throw unusable('AES-GCM'); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, 'algorithm.length'); - break; - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - if (!isAlgorithm(key.algorithm, 'AES-KW')) - throw unusable('AES-KW'); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, 'algorithm.length'); - break; - } - case 'ECDH': { - switch (key.algorithm.name) { - case 'ECDH': - case 'X25519': - case 'X448': - break; - default: - throw unusable('ECDH, X25519, or X448'); - } - break; - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': - if (!isAlgorithm(key.algorithm, 'PBKDF2')) - throw unusable('PBKDF2'); - break; - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) - throw unusable('RSA-OAEP'); - const expected = parseInt(alg.slice(9), 10) || 1; - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - default: - throw new TypeError('CryptoKey does not support this operation'); - } - checkUsage(key, usages); -} diff --git a/dist/browser/lib/decrypt_key_management.js b/dist/browser/lib/decrypt_key_management.js deleted file mode 100644 index 87890a4fa0..0000000000 --- a/dist/browser/lib/decrypt_key_management.js +++ /dev/null @@ -1,98 +0,0 @@ -import { unwrap as aesKw } from '../runtime/aeskw.js'; -import * as ECDH from '../runtime/ecdhes.js'; -import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js'; -import { decrypt as rsaEs } from '../runtime/rsaes.js'; -import { decode as base64url } from '../runtime/base64url.js'; -import { JOSENotSupported, JWEInvalid } from '../util/errors.js'; -import { bitLength as cekLength } from '../lib/cek.js'; -import { importJWK } from '../key/import.js'; -import checkKeyType from './check_key_type.js'; -import isObject from './is_object.js'; -import { unwrap as aesGcmKw } from './aesgcmkw.js'; -async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { - checkKeyType(alg, key, 'decrypt'); - switch (alg) { - case 'dir': { - if (encryptedKey !== undefined) - throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); - return key; - } - case 'ECDH-ES': - if (encryptedKey !== undefined) - throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - if (!isObject(joseHeader.epk)) - throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); - if (!ECDH.ecdhAllowed(key)) - throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); - const epk = await importJWK(joseHeader.epk, alg); - let partyUInfo; - let partyVInfo; - if (joseHeader.apu !== undefined) { - if (typeof joseHeader.apu !== 'string') - throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); - partyUInfo = base64url(joseHeader.apu); - } - if (joseHeader.apv !== undefined) { - if (typeof joseHeader.apv !== 'string') - throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); - partyVInfo = base64url(joseHeader.apv); - } - const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); - if (alg === 'ECDH-ES') - return sharedSecret; - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - return aesKw(alg.slice(-6), sharedSecret, encryptedKey); - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - return rsaEs(alg, key, encryptedKey); - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - if (typeof joseHeader.p2c !== 'number') - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); - const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 10000; - if (joseHeader.p2c > p2cLimit) - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); - if (typeof joseHeader.p2s !== 'string') - throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); - return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s)); - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - return aesKw(alg, key, encryptedKey); - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - if (typeof joseHeader.iv !== 'string') - throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); - if (typeof joseHeader.tag !== 'string') - throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); - const iv = base64url(joseHeader.iv); - const tag = base64url(joseHeader.tag); - return aesGcmKw(alg, key, encryptedKey, iv, tag); - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } -} -export default decryptKeyManagement; diff --git a/dist/browser/lib/encrypt_key_management.js b/dist/browser/lib/encrypt_key_management.js deleted file mode 100644 index eb9022c63e..0000000000 --- a/dist/browser/lib/encrypt_key_management.js +++ /dev/null @@ -1,87 +0,0 @@ -import { wrap as aesKw } from '../runtime/aeskw.js'; -import * as ECDH from '../runtime/ecdhes.js'; -import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js'; -import { encrypt as rsaEs } from '../runtime/rsaes.js'; -import { encode as base64url } from '../runtime/base64url.js'; -import generateCek, { bitLength as cekLength } from '../lib/cek.js'; -import { JOSENotSupported } from '../util/errors.js'; -import { exportJWK } from '../key/export.js'; -import checkKeyType from './check_key_type.js'; -import { wrap as aesGcmKw } from './aesgcmkw.js'; -async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { - let encryptedKey; - let parameters; - let cek; - checkKeyType(alg, key, 'encrypt'); - switch (alg) { - case 'dir': { - cek = key; - break; - } - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - if (!ECDH.ecdhAllowed(key)) { - throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); - } - const { apu, apv } = providedParameters; - let { epk: ephemeralKey } = providedParameters; - ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey); - const { x, y, crv, kty } = await exportJWK(ephemeralKey); - const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); - parameters = { epk: { x, crv, kty } }; - if (kty === 'EC') - parameters.epk.y = y; - if (apu) - parameters.apu = base64url(apu); - if (apv) - parameters.apv = base64url(apv); - if (alg === 'ECDH-ES') { - cek = sharedSecret; - break; - } - cek = providedCek || generateCek(enc); - const kwAlg = alg.slice(-6); - encryptedKey = await aesKw(kwAlg, sharedSecret, cek); - break; - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - cek = providedCek || generateCek(enc); - encryptedKey = await rsaEs(alg, key, cek); - break; - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - cek = providedCek || generateCek(enc); - const { p2c, p2s } = providedParameters; - ({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s)); - break; - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - cek = providedCek || generateCek(enc); - encryptedKey = await aesKw(alg, key, cek); - break; - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - cek = providedCek || generateCek(enc); - const { iv } = providedParameters; - ({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv)); - break; - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } - return { cek, encryptedKey, parameters }; -} -export default encryptKeyManagement; diff --git a/dist/browser/lib/epoch.js b/dist/browser/lib/epoch.js deleted file mode 100644 index e405e4b2df..0000000000 --- a/dist/browser/lib/epoch.js +++ /dev/null @@ -1 +0,0 @@ -export default (date) => Math.floor(date.getTime() / 1000); diff --git a/dist/browser/lib/format_pem.js b/dist/browser/lib/format_pem.js deleted file mode 100644 index 81673f256f..0000000000 --- a/dist/browser/lib/format_pem.js +++ /dev/null @@ -1,4 +0,0 @@ -export default (b64, descriptor) => { - const newlined = (b64.match(/.{1,64}/g) || []).join('\n'); - return `-----BEGIN ${descriptor}-----\n${newlined}\n-----END ${descriptor}-----`; -}; diff --git a/dist/browser/lib/invalid_key_input.js b/dist/browser/lib/invalid_key_input.js deleted file mode 100644 index 049e66ece0..0000000000 --- a/dist/browser/lib/invalid_key_input.js +++ /dev/null @@ -1,30 +0,0 @@ -function message(msg, actual, ...types) { - if (types.length > 2) { - const last = types.pop(); - msg += `one of type ${types.join(', ')}, or ${last}.`; - } - else if (types.length === 2) { - msg += `one of type ${types[0]} or ${types[1]}.`; - } - else { - msg += `of type ${types[0]}.`; - } - if (actual == null) { - msg += ` Received ${actual}`; - } - else if (typeof actual === 'function' && actual.name) { - msg += ` Received function ${actual.name}`; - } - else if (typeof actual === 'object' && actual != null) { - if (actual.constructor && actual.constructor.name) { - msg += ` Received an instance of ${actual.constructor.name}`; - } - } - return msg; -} -export default (actual, ...types) => { - return message('Key must be ', actual, ...types); -}; -export function withAlg(alg, actual, ...types) { - return message(`Key for the ${alg} algorithm must be `, actual, ...types); -} diff --git a/dist/browser/lib/is_disjoint.js b/dist/browser/lib/is_disjoint.js deleted file mode 100644 index 6f643502dc..0000000000 --- a/dist/browser/lib/is_disjoint.js +++ /dev/null @@ -1,22 +0,0 @@ -const isDisjoint = (...headers) => { - const sources = headers.filter(Boolean); - if (sources.length === 0 || sources.length === 1) { - return true; - } - let acc; - for (const header of sources) { - const parameters = Object.keys(header); - if (!acc || acc.size === 0) { - acc = new Set(parameters); - continue; - } - for (const parameter of parameters) { - if (acc.has(parameter)) { - return false; - } - acc.add(parameter); - } - } - return true; -}; -export default isDisjoint; diff --git a/dist/browser/lib/is_object.js b/dist/browser/lib/is_object.js deleted file mode 100644 index 4955e93225..0000000000 --- a/dist/browser/lib/is_object.js +++ /dev/null @@ -1,16 +0,0 @@ -function isObjectLike(value) { - return typeof value === 'object' && value !== null; -} -export default function isObject(input) { - if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { - return false; - } - if (Object.getPrototypeOf(input) === null) { - return true; - } - let proto = input; - while (Object.getPrototypeOf(proto) !== null) { - proto = Object.getPrototypeOf(proto); - } - return Object.getPrototypeOf(input) === proto; -} diff --git a/dist/browser/lib/iv.js b/dist/browser/lib/iv.js deleted file mode 100644 index cab2a12729..0000000000 --- a/dist/browser/lib/iv.js +++ /dev/null @@ -1,20 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -import random from '../runtime/random.js'; -export function bitLength(alg) { - switch (alg) { - case 'A128GCM': - case 'A128GCMKW': - case 'A192GCM': - case 'A192GCMKW': - case 'A256GCM': - case 'A256GCMKW': - return 96; - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return 128; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/browser/lib/jwt_claims_set.js b/dist/browser/lib/jwt_claims_set.js deleted file mode 100644 index e9e2f1944f..0000000000 --- a/dist/browser/lib/jwt_claims_set.js +++ /dev/null @@ -1,91 +0,0 @@ -import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js'; -import { decoder } from './buffer_utils.js'; -import epoch from './epoch.js'; -import secs from './secs.js'; -import isObject from './is_object.js'; -const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ''); -const checkAudiencePresence = (audPayload, audOption) => { - if (typeof audPayload === 'string') { - return audOption.includes(audPayload); - } - if (Array.isArray(audPayload)) { - return audOption.some(Set.prototype.has.bind(new Set(audPayload))); - } - return false; -}; -export default (protectedHeader, encodedPayload, options = {}) => { - const { typ } = options; - if (typ && - (typeof protectedHeader.typ !== 'string' || - normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { - throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed'); - } - let payload; - try { - payload = JSON.parse(decoder.decode(encodedPayload)); - } - catch (_a) { - } - if (!isObject(payload)) { - throw new JWTInvalid('JWT Claims Set must be a top-level JSON object'); - } - const { issuer } = options; - if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { - throw new JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed'); - } - const { subject } = options; - if (subject && payload.sub !== subject) { - throw new JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed'); - } - const { audience } = options; - if (audience && - !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) { - throw new JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed'); - } - let tolerance; - switch (typeof options.clockTolerance) { - case 'string': - tolerance = secs(options.clockTolerance); - break; - case 'number': - tolerance = options.clockTolerance; - break; - case 'undefined': - tolerance = 0; - break; - default: - throw new TypeError('Invalid clockTolerance option type'); - } - const { currentDate } = options; - const now = epoch(currentDate || new Date()); - if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { - throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid'); - } - if (payload.nbf !== undefined) { - if (typeof payload.nbf !== 'number') { - throw new JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid'); - } - if (payload.nbf > now + tolerance) { - throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', 'nbf', 'check_failed'); - } - } - if (payload.exp !== undefined) { - if (typeof payload.exp !== 'number') { - throw new JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid'); - } - if (payload.exp <= now - tolerance) { - throw new JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed'); - } - } - if (options.maxTokenAge) { - const age = now - payload.iat; - const max = typeof options.maxTokenAge === 'number' ? options.maxTokenAge : secs(options.maxTokenAge); - if (age - tolerance > max) { - throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', 'iat', 'check_failed'); - } - if (age < 0 - tolerance) { - throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed'); - } - } - return payload; -}; diff --git a/dist/browser/lib/secs.js b/dist/browser/lib/secs.js deleted file mode 100644 index cf470ed8ad..0000000000 --- a/dist/browser/lib/secs.js +++ /dev/null @@ -1,44 +0,0 @@ -const minute = 60; -const hour = minute * 60; -const day = hour * 24; -const week = day * 7; -const year = day * 365.25; -const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; -export default (str) => { - const matched = REGEX.exec(str); - if (!matched) { - throw new TypeError('Invalid time period format'); - } - const value = parseFloat(matched[1]); - const unit = matched[2].toLowerCase(); - switch (unit) { - case 'sec': - case 'secs': - case 'second': - case 'seconds': - case 's': - return Math.round(value); - case 'minute': - case 'minutes': - case 'min': - case 'mins': - case 'm': - return Math.round(value * minute); - case 'hour': - case 'hours': - case 'hr': - case 'hrs': - case 'h': - return Math.round(value * hour); - case 'day': - case 'days': - case 'd': - return Math.round(value * day); - case 'week': - case 'weeks': - case 'w': - return Math.round(value * week); - default: - return Math.round(value * year); - } -}; diff --git a/dist/browser/lib/validate_algorithms.js b/dist/browser/lib/validate_algorithms.js deleted file mode 100644 index a6a7918571..0000000000 --- a/dist/browser/lib/validate_algorithms.js +++ /dev/null @@ -1,11 +0,0 @@ -const validateAlgorithms = (option, algorithms) => { - if (algorithms !== undefined && - (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) { - throw new TypeError(`"${option}" option must be an array of strings`); - } - if (!algorithms) { - return undefined; - } - return new Set(algorithms); -}; -export default validateAlgorithms; diff --git a/dist/browser/lib/validate_crit.js b/dist/browser/lib/validate_crit.js deleted file mode 100644 index 68c69f18f5..0000000000 --- a/dist/browser/lib/validate_crit.js +++ /dev/null @@ -1,34 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { - if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { - throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); - } - if (!protectedHeader || protectedHeader.crit === undefined) { - return new Set(); - } - if (!Array.isArray(protectedHeader.crit) || - protectedHeader.crit.length === 0 || - protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) { - throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); - } - let recognized; - if (recognizedOption !== undefined) { - recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); - } - else { - recognized = recognizedDefault; - } - for (const parameter of protectedHeader.crit) { - if (!recognized.has(parameter)) { - throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); - } - if (joseHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" is missing`); - } - else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); - } - } - return new Set(protectedHeader.crit); -} -export default validateCrit; diff --git a/dist/browser/package.json b/dist/browser/package.json deleted file mode 100644 index 6990891ff3..0000000000 --- a/dist/browser/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "module"} diff --git a/dist/browser/runtime/aeskw.js b/dist/browser/runtime/aeskw.js deleted file mode 100644 index bb7dff8a5b..0000000000 --- a/dist/browser/runtime/aeskw.js +++ /dev/null @@ -1,32 +0,0 @@ -import bogusWebCrypto from './bogus.js'; -import crypto, { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -function checkKeySize(key, alg) { - if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) { - throw new TypeError(`Invalid key size for alg: ${alg}`); - } -} -function getCryptoKey(key, alg, usage) { - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, usage); - return key; - } - if (key instanceof Uint8Array) { - return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]); - } - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); -} -export const wrap = async (alg, key, cek) => { - const cryptoKey = await getCryptoKey(key, alg, 'wrapKey'); - checkKeySize(cryptoKey, alg); - const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto); - return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, cryptoKey, 'AES-KW')); -}; -export const unwrap = async (alg, key, encryptedKey) => { - const cryptoKey = await getCryptoKey(key, alg, 'unwrapKey'); - checkKeySize(cryptoKey, alg); - const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, cryptoKey, 'AES-KW', ...bogusWebCrypto); - return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)); -}; diff --git a/dist/browser/runtime/asn1.js b/dist/browser/runtime/asn1.js deleted file mode 100644 index ba617f649a..0000000000 --- a/dist/browser/runtime/asn1.js +++ /dev/null @@ -1,214 +0,0 @@ -import { isCloudflareWorkers } from './env.js'; -import crypto, { isCryptoKey } from './webcrypto.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { encodeBase64, decodeBase64 } from './base64url.js'; -import formatPEM from '../lib/format_pem.js'; -import { JOSENotSupported } from '../util/errors.js'; -import { types } from './is_key_like.js'; -const genericExport = async (keyType, keyFormat, key) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)); - } - if (!key.extractable) { - throw new TypeError('CryptoKey is not extractable'); - } - if (key.type !== keyType) { - throw new TypeError(`key is not a ${keyType} key`); - } - return formatPEM(encodeBase64(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`); -}; -export const toSPKI = (key) => { - return genericExport('public', 'spki', key); -}; -export const toPKCS8 = (key) => { - return genericExport('private', 'pkcs8', key); -}; -const findOid = (keyData, oid, from = 0) => { - if (from === 0) { - oid.unshift(oid.length); - oid.unshift(0x06); - } - let i = keyData.indexOf(oid[0], from); - if (i === -1) - return false; - const sub = keyData.subarray(i, i + oid.length); - if (sub.length !== oid.length) - return false; - return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1); -}; -const getNamedCurve = (keyData) => { - switch (true) { - case findOid(keyData, [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]): - return 'P-256'; - case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x22]): - return 'P-384'; - case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]): - return 'P-521'; - case findOid(keyData, [0x2b, 0x65, 0x6e]): - return 'X25519'; - case findOid(keyData, [0x2b, 0x65, 0x6f]): - return 'X448'; - case findOid(keyData, [0x2b, 0x65, 0x70]): - return 'Ed25519'; - case findOid(keyData, [0x2b, 0x65, 0x71]): - return 'Ed448'; - default: - throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type'); - } -}; -const genericImport = async (replace, keyFormat, pem, alg, options) => { - var _a, _b; - let algorithm; - let keyUsages; - const keyData = new Uint8Array(atob(pem.replace(replace, '')) - .split('') - .map((c) => c.charCodeAt(0))); - const isPublic = keyFormat === 'spki'; - switch (alg) { - case 'PS256': - case 'PS384': - case 'PS512': - algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` }; - keyUsages = isPublic ? ['verify'] : ['sign']; - break; - case 'RS256': - case 'RS384': - case 'RS512': - algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` }; - keyUsages = isPublic ? ['verify'] : ['sign']; - break; - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - algorithm = { - name: 'RSA-OAEP', - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, - }; - keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey']; - break; - case 'ES256': - algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; - keyUsages = isPublic ? ['verify'] : ['sign']; - break; - case 'ES384': - algorithm = { name: 'ECDSA', namedCurve: 'P-384' }; - keyUsages = isPublic ? ['verify'] : ['sign']; - break; - case 'ES512': - algorithm = { name: 'ECDSA', namedCurve: 'P-521' }; - keyUsages = isPublic ? ['verify'] : ['sign']; - break; - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - const namedCurve = getNamedCurve(keyData); - algorithm = namedCurve.startsWith('P-') ? { name: 'ECDH', namedCurve } : { name: namedCurve }; - keyUsages = isPublic ? [] : ['deriveBits']; - break; - } - case 'EdDSA': - algorithm = { name: getNamedCurve(keyData) }; - keyUsages = isPublic ? ['verify'] : ['sign']; - break; - default: - throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value'); - } - try { - return await crypto.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); - } - catch (err) { - if (algorithm.name === 'Ed25519' && - (err === null || err === void 0 ? void 0 : err.name) === 'NotSupportedError' && - isCloudflareWorkers()) { - algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; - return await crypto.subtle.importKey(keyFormat, keyData, algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages); - } - throw err; - } -}; -export const fromPKCS8 = (pem, alg, options) => { - return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options); -}; -export const fromSPKI = (pem, alg, options) => { - return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, 'spki', pem, alg, options); -}; -function getElement(seq) { - let result = []; - let next = 0; - while (next < seq.length) { - let nextPart = parseElement(seq.subarray(next)); - result.push(nextPart); - next += nextPart.byteLength; - } - return result; -} -function parseElement(bytes) { - let position = 0; - let tag = bytes[0] & 0x1f; - position++; - if (tag === 0x1f) { - tag = 0; - while (bytes[position] >= 0x80) { - tag = tag * 128 + bytes[position] - 0x80; - position++; - } - tag = tag * 128 + bytes[position] - 0x80; - position++; - } - let length = 0; - if (bytes[position] < 0x80) { - length = bytes[position]; - position++; - } - else if (length === 0x80) { - length = 0; - while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { - if (length > bytes.byteLength) { - throw new TypeError('invalid indefinite form length'); - } - length++; - } - const byteLength = position + length + 2; - return { - byteLength, - contents: bytes.subarray(position, position + length), - raw: bytes.subarray(0, byteLength), - }; - } - else { - let numberOfDigits = bytes[position] & 0x7f; - position++; - length = 0; - for (let i = 0; i < numberOfDigits; i++) { - length = length * 256 + bytes[position]; - position++; - } - } - const byteLength = position + length; - return { - byteLength, - contents: bytes.subarray(position, byteLength), - raw: bytes.subarray(0, byteLength), - }; -} -function spkiFromX509(buf) { - const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents); - return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 0xa0 ? 6 : 5].raw); -} -function getSPKI(x509) { - const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ''); - const raw = decodeBase64(pem); - return formatPEM(spkiFromX509(raw), 'PUBLIC KEY'); -} -export const fromX509 = (pem, alg, options) => { - let spki; - try { - spki = getSPKI(pem); - } - catch (cause) { - throw new TypeError('failed to parse the X.509 certificate', { cause }); - } - return fromSPKI(spki, alg, options); -}; diff --git a/dist/browser/runtime/base64url.js b/dist/browser/runtime/base64url.js deleted file mode 100644 index 32df82bfe0..0000000000 --- a/dist/browser/runtime/base64url.js +++ /dev/null @@ -1,37 +0,0 @@ -import { encoder, decoder } from '../lib/buffer_utils.js'; -export const encodeBase64 = (input) => { - let unencoded = input; - if (typeof unencoded === 'string') { - unencoded = encoder.encode(unencoded); - } - const CHUNK_SIZE = 0x8000; - const arr = []; - for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { - arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))); - } - return btoa(arr.join('')); -}; -export const encode = (input) => { - return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); -}; -export const decodeBase64 = (encoded) => { - const binary = atob(encoded); - const bytes = new Uint8Array(binary.length); - for (let i = 0; i < binary.length; i++) { - bytes[i] = binary.charCodeAt(i); - } - return bytes; -}; -export const decode = (input) => { - let encoded = input; - if (encoded instanceof Uint8Array) { - encoded = decoder.decode(encoded); - } - encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, ''); - try { - return decodeBase64(encoded); - } - catch (_a) { - throw new TypeError('The input to be decoded is not correctly encoded.'); - } -}; diff --git a/dist/browser/runtime/bogus.js b/dist/browser/runtime/bogus.js deleted file mode 100644 index 8fde604ebf..0000000000 --- a/dist/browser/runtime/bogus.js +++ /dev/null @@ -1,6 +0,0 @@ -const bogusWebCrypto = [ - { hash: 'SHA-256', name: 'HMAC' }, - true, - ['sign'], -]; -export default bogusWebCrypto; diff --git a/dist/browser/runtime/check_cek_length.js b/dist/browser/runtime/check_cek_length.js deleted file mode 100644 index ae89001215..0000000000 --- a/dist/browser/runtime/check_cek_length.js +++ /dev/null @@ -1,8 +0,0 @@ -import { JWEInvalid } from '../util/errors.js'; -const checkCekLength = (cek, expected) => { - const actual = cek.byteLength << 3; - if (actual !== expected) { - throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); - } -}; -export default checkCekLength; diff --git a/dist/browser/runtime/check_key_length.js b/dist/browser/runtime/check_key_length.js deleted file mode 100644 index 33970068fe..0000000000 --- a/dist/browser/runtime/check_key_length.js +++ /dev/null @@ -1,8 +0,0 @@ -export default (alg, key) => { - if (alg.startsWith('RS') || alg.startsWith('PS')) { - const { modulusLength } = key.algorithm; - if (typeof modulusLength !== 'number' || modulusLength < 2048) { - throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); - } - } -}; diff --git a/dist/browser/runtime/decrypt.js b/dist/browser/runtime/decrypt.js deleted file mode 100644 index 68f9f7c3fe..0000000000 --- a/dist/browser/runtime/decrypt.js +++ /dev/null @@ -1,85 +0,0 @@ -import { concat, uint64be } from '../lib/buffer_utils.js'; -import checkIvLength from '../lib/check_iv_length.js'; -import checkCekLength from './check_cek_length.js'; -import timingSafeEqual from './timing_safe_equal.js'; -import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js'; -import crypto, { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, 'Uint8Array')); - } - const keySize = parseInt(enc.slice(1, 4), 10); - const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['decrypt']); - const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), { - hash: `SHA-${keySize << 1}`, - name: 'HMAC', - }, false, ['sign']); - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); - const expectedTag = new Uint8Array((await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3)); - let macCheckPassed; - try { - macCheckPassed = timingSafeEqual(tag, expectedTag); - } - catch (_a) { - } - if (!macCheckPassed) { - throw new JWEDecryptionFailed(); - } - let plaintext; - try { - plaintext = new Uint8Array(await crypto.subtle.decrypt({ iv, name: 'AES-CBC' }, encKey, ciphertext)); - } - catch (_b) { - } - if (!plaintext) { - throw new JWEDecryptionFailed(); - } - return plaintext; -} -async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { - let encKey; - if (cek instanceof Uint8Array) { - encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']); - } - else { - checkEncCryptoKey(cek, enc, 'decrypt'); - encKey = cek; - } - try { - return new Uint8Array(await crypto.subtle.decrypt({ - additionalData: aad, - iv, - name: 'AES-GCM', - tagLength: 128, - }, encKey, concat(ciphertext, tag))); - } - catch (_a) { - throw new JWEDecryptionFailed(); - } -} -const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); - } - checkIvLength(enc, iv); - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - if (cek instanceof Uint8Array) - checkCekLength(cek, parseInt(enc.slice(-3), 10)); - return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad); - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - if (cek instanceof Uint8Array) - checkCekLength(cek, parseInt(enc.slice(1, 4), 10)); - return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); - default: - throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); - } -}; -export default decrypt; diff --git a/dist/browser/runtime/digest.js b/dist/browser/runtime/digest.js deleted file mode 100644 index 39099d3b1d..0000000000 --- a/dist/browser/runtime/digest.js +++ /dev/null @@ -1,6 +0,0 @@ -import crypto from './webcrypto.js'; -const digest = async (algorithm, data) => { - const subtleDigest = `SHA-${algorithm.slice(-3)}`; - return new Uint8Array(await crypto.subtle.digest(subtleDigest, data)); -}; -export default digest; diff --git a/dist/browser/runtime/ecdhes.js b/dist/browser/runtime/ecdhes.js deleted file mode 100644 index b4f515e312..0000000000 --- a/dist/browser/runtime/ecdhes.js +++ /dev/null @@ -1,46 +0,0 @@ -import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.js'; -import crypto, { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { - if (!isCryptoKey(publicKey)) { - throw new TypeError(invalidKeyInput(publicKey, ...types)); - } - checkEncCryptoKey(publicKey, 'ECDH'); - if (!isCryptoKey(privateKey)) { - throw new TypeError(invalidKeyInput(privateKey, ...types)); - } - checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits'); - const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); - let length; - if (publicKey.algorithm.name === 'X25519') { - length = 256; - } - else if (publicKey.algorithm.name === 'X448') { - length = 448; - } - else { - length = - Math.ceil(parseInt(publicKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3; - } - const sharedSecret = new Uint8Array(await crypto.subtle.deriveBits({ - name: publicKey.algorithm.name, - public: publicKey, - }, privateKey, length)); - return concatKdf(sharedSecret, keyLength, value); -} -export async function generateEpk(key) { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)); - } - return crypto.subtle.generateKey(key.algorithm, true, ['deriveBits']); -} -export function ecdhAllowed(key) { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)); - } - return (['P-256', 'P-384', 'P-521'].includes(key.algorithm.namedCurve) || - key.algorithm.name === 'X25519' || - key.algorithm.name === 'X448'); -} diff --git a/dist/browser/runtime/encrypt.js b/dist/browser/runtime/encrypt.js deleted file mode 100644 index c2ec0ef91d..0000000000 --- a/dist/browser/runtime/encrypt.js +++ /dev/null @@ -1,68 +0,0 @@ -import { concat, uint64be } from '../lib/buffer_utils.js'; -import checkIvLength from '../lib/check_iv_length.js'; -import checkCekLength from './check_cek_length.js'; -import crypto, { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { JOSENotSupported } from '../util/errors.js'; -import { types } from './is_key_like.js'; -async function cbcEncrypt(enc, plaintext, cek, iv, aad) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, 'Uint8Array')); - } - const keySize = parseInt(enc.slice(1, 4), 10); - const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['encrypt']); - const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), { - hash: `SHA-${keySize << 1}`, - name: 'HMAC', - }, false, ['sign']); - const ciphertext = new Uint8Array(await crypto.subtle.encrypt({ - iv, - name: 'AES-CBC', - }, encKey, plaintext)); - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); - const tag = new Uint8Array((await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3)); - return { ciphertext, tag }; -} -async function gcmEncrypt(enc, plaintext, cek, iv, aad) { - let encKey; - if (cek instanceof Uint8Array) { - encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']); - } - else { - checkEncCryptoKey(cek, enc, 'encrypt'); - encKey = cek; - } - const encrypted = new Uint8Array(await crypto.subtle.encrypt({ - additionalData: aad, - iv, - name: 'AES-GCM', - tagLength: 128, - }, encKey, plaintext)); - const tag = encrypted.slice(-16); - const ciphertext = encrypted.slice(0, -16); - return { ciphertext, tag }; -} -const encrypt = async (enc, plaintext, cek, iv, aad) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); - } - checkIvLength(enc, iv); - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - if (cek instanceof Uint8Array) - checkCekLength(cek, parseInt(enc.slice(-3), 10)); - return cbcEncrypt(enc, plaintext, cek, iv, aad); - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - if (cek instanceof Uint8Array) - checkCekLength(cek, parseInt(enc.slice(1, 4), 10)); - return gcmEncrypt(enc, plaintext, cek, iv, aad); - default: - throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); - } -}; -export default encrypt; diff --git a/dist/browser/runtime/env.js b/dist/browser/runtime/env.js deleted file mode 100644 index 740a197ec0..0000000000 --- a/dist/browser/runtime/env.js +++ /dev/null @@ -1,5 +0,0 @@ -export function isCloudflareWorkers() { - return (typeof WebSocketPair !== 'undefined' || - (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') || - (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel')); -} diff --git a/dist/browser/runtime/fetch_jwks.js b/dist/browser/runtime/fetch_jwks.js deleted file mode 100644 index 85d58b675d..0000000000 --- a/dist/browser/runtime/fetch_jwks.js +++ /dev/null @@ -1,34 +0,0 @@ -import { JOSEError, JWKSTimeout } from '../util/errors.js'; -const fetchJwks = async (url, timeout, options) => { - let controller; - let id; - let timedOut = false; - if (typeof AbortController === 'function') { - controller = new AbortController(); - id = setTimeout(() => { - timedOut = true; - controller.abort(); - }, timeout); - } - const response = await fetch(url.href, { - signal: controller ? controller.signal : undefined, - redirect: 'manual', - headers: options.headers, - }).catch((err) => { - if (timedOut) - throw new JWKSTimeout(); - throw err; - }); - if (id !== undefined) - clearTimeout(id); - if (response.status !== 200) { - throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response'); - } - try { - return await response.json(); - } - catch (_a) { - throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON'); - } -}; -export default fetchJwks; diff --git a/dist/browser/runtime/generate.js b/dist/browser/runtime/generate.js deleted file mode 100644 index 8af84fa141..0000000000 --- a/dist/browser/runtime/generate.js +++ /dev/null @@ -1,153 +0,0 @@ -import { isCloudflareWorkers } from './env.js'; -import crypto from './webcrypto.js'; -import { JOSENotSupported } from '../util/errors.js'; -import random from './random.js'; -export async function generateSecret(alg, options) { - var _a; - let length; - let algorithm; - let keyUsages; - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': - length = parseInt(alg.slice(-3), 10); - algorithm = { name: 'HMAC', hash: `SHA-${length}`, length }; - keyUsages = ['sign', 'verify']; - break; - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - length = parseInt(alg.slice(-3), 10); - return random(new Uint8Array(length >> 3)); - case 'A128KW': - case 'A192KW': - case 'A256KW': - length = parseInt(alg.slice(1, 4), 10); - algorithm = { name: 'AES-KW', length }; - keyUsages = ['wrapKey', 'unwrapKey']; - break; - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - length = parseInt(alg.slice(1, 4), 10); - algorithm = { name: 'AES-GCM', length }; - keyUsages = ['encrypt', 'decrypt']; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - return crypto.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); -} -function getModulusLengthOption(options) { - var _a; - const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; - if (typeof modulusLength !== 'number' || modulusLength < 2048) { - throw new JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used'); - } - return modulusLength; -} -export async function generateKeyPair(alg, options) { - var _a, _b, _c, _d; - let algorithm; - let keyUsages; - switch (alg) { - case 'PS256': - case 'PS384': - case 'PS512': - algorithm = { - name: 'RSA-PSS', - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([0x01, 0x00, 0x01]), - modulusLength: getModulusLengthOption(options), - }; - keyUsages = ['sign', 'verify']; - break; - case 'RS256': - case 'RS384': - case 'RS512': - algorithm = { - name: 'RSASSA-PKCS1-v1_5', - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([0x01, 0x00, 0x01]), - modulusLength: getModulusLengthOption(options), - }; - keyUsages = ['sign', 'verify']; - break; - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - algorithm = { - name: 'RSA-OAEP', - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, - publicExponent: new Uint8Array([0x01, 0x00, 0x01]), - modulusLength: getModulusLengthOption(options), - }; - keyUsages = ['decrypt', 'unwrapKey', 'encrypt', 'wrapKey']; - break; - case 'ES256': - algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; - keyUsages = ['sign', 'verify']; - break; - case 'ES384': - algorithm = { name: 'ECDSA', namedCurve: 'P-384' }; - keyUsages = ['sign', 'verify']; - break; - case 'ES512': - algorithm = { name: 'ECDSA', namedCurve: 'P-521' }; - keyUsages = ['sign', 'verify']; - break; - case 'EdDSA': - keyUsages = ['sign', 'verify']; - const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : 'Ed25519'; - switch (crv) { - case 'Ed25519': - case 'Ed448': - algorithm = { name: crv }; - break; - default: - throw new JOSENotSupported('Invalid or unsupported crv option provided'); - } - break; - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - keyUsages = ['deriveKey', 'deriveBits']; - const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256'; - switch (crv) { - case 'P-256': - case 'P-384': - case 'P-521': { - algorithm = { name: 'ECDH', namedCurve: crv }; - break; - } - case 'X25519': - case 'X448': - algorithm = { name: crv }; - break; - default: - throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448'); - } - break; - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - try { - return (await crypto.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages)); - } - catch (err) { - if (algorithm.name === 'Ed25519' && - (err === null || err === void 0 ? void 0 : err.name) === 'NotSupportedError' && - isCloudflareWorkers()) { - algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; - return (await crypto.subtle.generateKey(algorithm, (_d = options === null || options === void 0 ? void 0 : options.extractable) !== null && _d !== void 0 ? _d : false, keyUsages)); - } - throw err; - } -} diff --git a/dist/browser/runtime/get_sign_verify_key.js b/dist/browser/runtime/get_sign_verify_key.js deleted file mode 100644 index db34ae8bbe..0000000000 --- a/dist/browser/runtime/get_sign_verify_key.js +++ /dev/null @@ -1,17 +0,0 @@ -import crypto, { isCryptoKey } from './webcrypto.js'; -import { checkSigCryptoKey } from '../lib/crypto_key.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -export default function getCryptoKey(alg, key, usage) { - if (isCryptoKey(key)) { - checkSigCryptoKey(key, alg, usage); - return key; - } - if (key instanceof Uint8Array) { - if (!alg.startsWith('HS')) { - throw new TypeError(invalidKeyInput(key, ...types)); - } - return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, false, [usage]); - } - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); -} diff --git a/dist/browser/runtime/is_key_like.js b/dist/browser/runtime/is_key_like.js deleted file mode 100644 index 8d35fdc84c..0000000000 --- a/dist/browser/runtime/is_key_like.js +++ /dev/null @@ -1,5 +0,0 @@ -import { isCryptoKey } from './webcrypto.js'; -export default (key) => { - return isCryptoKey(key); -}; -export const types = ['CryptoKey']; diff --git a/dist/browser/runtime/jwk_to_key.js b/dist/browser/runtime/jwk_to_key.js deleted file mode 100644 index d3e693d2de..0000000000 --- a/dist/browser/runtime/jwk_to_key.js +++ /dev/null @@ -1,155 +0,0 @@ -import { isCloudflareWorkers } from './env.js'; -import crypto from './webcrypto.js'; -import { JOSENotSupported } from '../util/errors.js'; -import { decode as base64url } from './base64url.js'; -function subtleMapping(jwk) { - let algorithm; - let keyUsages; - switch (jwk.kty) { - case 'oct': { - switch (jwk.alg) { - case 'HS256': - case 'HS384': - case 'HS512': - algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = ['sign', 'verify']; - break; - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`); - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': - algorithm = { name: 'AES-GCM' }; - keyUsages = ['encrypt', 'decrypt']; - break; - case 'A128KW': - case 'A192KW': - case 'A256KW': - algorithm = { name: 'AES-KW' }; - keyUsages = ['wrapKey', 'unwrapKey']; - break; - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': - algorithm = { name: 'PBKDF2' }; - keyUsages = ['deriveBits']; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case 'RSA': { - switch (jwk.alg) { - case 'PS256': - case 'PS384': - case 'PS512': - algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = jwk.d ? ['sign'] : ['verify']; - break; - case 'RS256': - case 'RS384': - case 'RS512': - algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` }; - keyUsages = jwk.d ? ['sign'] : ['verify']; - break; - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - algorithm = { - name: 'RSA-OAEP', - hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`, - }; - keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey']; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case 'EC': { - switch (jwk.alg) { - case 'ES256': - algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; - keyUsages = jwk.d ? ['sign'] : ['verify']; - break; - case 'ES384': - algorithm = { name: 'ECDSA', namedCurve: 'P-384' }; - keyUsages = jwk.d ? ['sign'] : ['verify']; - break; - case 'ES512': - algorithm = { name: 'ECDSA', namedCurve: 'P-521' }; - keyUsages = jwk.d ? ['sign'] : ['verify']; - break; - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': - algorithm = { name: 'ECDH', namedCurve: jwk.crv }; - keyUsages = jwk.d ? ['deriveBits'] : []; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - case 'OKP': { - switch (jwk.alg) { - case 'EdDSA': - algorithm = { name: jwk.crv }; - keyUsages = jwk.d ? ['sign'] : ['verify']; - break; - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': - algorithm = { name: jwk.crv }; - keyUsages = jwk.d ? ['deriveBits'] : []; - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - break; - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); - } - return { algorithm, keyUsages }; -} -const parse = async (jwk) => { - var _a, _b; - if (!jwk.alg) { - throw new TypeError('"alg" argument is required when "jwk.alg" is not present'); - } - const { algorithm, keyUsages } = subtleMapping(jwk); - const rest = [ - algorithm, - (_a = jwk.ext) !== null && _a !== void 0 ? _a : false, - (_b = jwk.key_ops) !== null && _b !== void 0 ? _b : keyUsages, - ]; - if (algorithm.name === 'PBKDF2') { - return crypto.subtle.importKey('raw', base64url(jwk.k), ...rest); - } - const keyData = { ...jwk }; - delete keyData.alg; - delete keyData.use; - try { - return await crypto.subtle.importKey('jwk', keyData, ...rest); - } - catch (err) { - if (algorithm.name === 'Ed25519' && - (err === null || err === void 0 ? void 0 : err.name) === 'NotSupportedError' && - isCloudflareWorkers()) { - rest[0] = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; - return await crypto.subtle.importKey('jwk', keyData, ...rest); - } - throw err; - } -}; -export default parse; diff --git a/dist/browser/runtime/key_to_jwk.js b/dist/browser/runtime/key_to_jwk.js deleted file mode 100644 index 438edfedc3..0000000000 --- a/dist/browser/runtime/key_to_jwk.js +++ /dev/null @@ -1,21 +0,0 @@ -import crypto, { isCryptoKey } from './webcrypto.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { encode as base64url } from './base64url.js'; -import { types } from './is_key_like.js'; -const keyToJWK = async (key) => { - if (key instanceof Uint8Array) { - return { - kty: 'oct', - k: base64url(key), - }; - } - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); - } - if (!key.extractable) { - throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK'); - } - const { ext, key_ops, alg, use, ...jwk } = await crypto.subtle.exportKey('jwk', key); - return jwk; -}; -export default keyToJWK; diff --git a/dist/browser/runtime/pbes2kw.js b/dist/browser/runtime/pbes2kw.js deleted file mode 100644 index 575304aa6b..0000000000 --- a/dist/browser/runtime/pbes2kw.js +++ /dev/null @@ -1,51 +0,0 @@ -import random from './random.js'; -import { p2s as concatSalt } from '../lib/buffer_utils.js'; -import { encode as base64url } from './base64url.js'; -import { wrap, unwrap } from './aeskw.js'; -import checkP2s from '../lib/check_p2s.js'; -import crypto, { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -function getCryptoKey(key, alg) { - if (key instanceof Uint8Array) { - return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']); - } - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey'); - return key; - } - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); -} -async function deriveKey(p2s, alg, p2c, key) { - checkP2s(p2s); - const salt = concatSalt(alg, p2s); - const keylen = parseInt(alg.slice(13, 16), 10); - const subtleAlg = { - hash: `SHA-${alg.slice(8, 11)}`, - iterations: p2c, - name: 'PBKDF2', - salt, - }; - const wrapAlg = { - length: keylen, - name: 'AES-KW', - }; - const cryptoKey = await getCryptoKey(key, alg); - if (cryptoKey.usages.includes('deriveBits')) { - return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen)); - } - if (cryptoKey.usages.includes('deriveKey')) { - return crypto.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ['wrapKey', 'unwrapKey']); - } - throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"'); -} -export const encrypt = async (alg, key, cek, p2c = 2048, p2s = random(new Uint8Array(16))) => { - const derived = await deriveKey(p2s, alg, p2c, key); - const encryptedKey = await wrap(alg.slice(-6), derived, cek); - return { encryptedKey, p2c, p2s: base64url(p2s) }; -}; -export const decrypt = async (alg, key, encryptedKey, p2c, p2s) => { - const derived = await deriveKey(p2s, alg, p2c, key); - return unwrap(alg.slice(-6), derived, encryptedKey); -}; diff --git a/dist/browser/runtime/random.js b/dist/browser/runtime/random.js deleted file mode 100644 index e8e461124a..0000000000 --- a/dist/browser/runtime/random.js +++ /dev/null @@ -1,2 +0,0 @@ -import crypto from './webcrypto.js'; -export default crypto.getRandomValues.bind(crypto); diff --git a/dist/browser/runtime/rsaes.js b/dist/browser/runtime/rsaes.js deleted file mode 100644 index a1733769ec..0000000000 --- a/dist/browser/runtime/rsaes.js +++ /dev/null @@ -1,37 +0,0 @@ -import subtleAlgorithm from './subtle_rsaes.js'; -import bogusWebCrypto from './bogus.js'; -import crypto, { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import checkKeyLength from './check_key_length.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -export const encrypt = async (alg, key, cek) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)); - } - checkEncCryptoKey(key, alg, 'encrypt', 'wrapKey'); - checkKeyLength(alg, key); - if (key.usages.includes('encrypt')) { - return new Uint8Array(await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek)); - } - if (key.usages.includes('wrapKey')) { - const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto); - return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, key, subtleAlgorithm(alg))); - } - throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation'); -}; -export const decrypt = async (alg, key, encryptedKey) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)); - } - checkEncCryptoKey(key, alg, 'decrypt', 'unwrapKey'); - checkKeyLength(alg, key); - if (key.usages.includes('decrypt')) { - return new Uint8Array(await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey)); - } - if (key.usages.includes('unwrapKey')) { - const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, key, subtleAlgorithm(alg), ...bogusWebCrypto); - return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)); - } - throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation'); -}; diff --git a/dist/browser/runtime/sign.js b/dist/browser/runtime/sign.js deleted file mode 100644 index 3ccb9e16c3..0000000000 --- a/dist/browser/runtime/sign.js +++ /dev/null @@ -1,11 +0,0 @@ -import subtleAlgorithm from './subtle_dsa.js'; -import crypto from './webcrypto.js'; -import checkKeyLength from './check_key_length.js'; -import getSignKey from './get_sign_verify_key.js'; -const sign = async (alg, key, data) => { - const cryptoKey = await getSignKey(alg, key, 'sign'); - checkKeyLength(alg, cryptoKey); - const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data); - return new Uint8Array(signature); -}; -export default sign; diff --git a/dist/browser/runtime/subtle_dsa.js b/dist/browser/runtime/subtle_dsa.js deleted file mode 100644 index 3df4514adf..0000000000 --- a/dist/browser/runtime/subtle_dsa.js +++ /dev/null @@ -1,30 +0,0 @@ -import { isCloudflareWorkers } from './env.js'; -import { JOSENotSupported } from '../util/errors.js'; -export default function subtleDsa(alg, algorithm) { - const hash = `SHA-${alg.slice(-3)}`; - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': - return { hash, name: 'HMAC' }; - case 'PS256': - case 'PS384': - case 'PS512': - return { hash, name: 'RSA-PSS', saltLength: alg.slice(-3) >> 3 }; - case 'RS256': - case 'RS384': - case 'RS512': - return { hash, name: 'RSASSA-PKCS1-v1_5' }; - case 'ES256': - case 'ES384': - case 'ES512': - return { hash, name: 'ECDSA', namedCurve: algorithm.namedCurve }; - case 'EdDSA': - if (isCloudflareWorkers() && algorithm.name === 'NODE-ED25519') { - return { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; - } - return { name: algorithm.name }; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} diff --git a/dist/browser/runtime/subtle_rsaes.js b/dist/browser/runtime/subtle_rsaes.js deleted file mode 100644 index 3a399bcfa7..0000000000 --- a/dist/browser/runtime/subtle_rsaes.js +++ /dev/null @@ -1,12 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -export default function subtleRsaEs(alg) { - switch (alg) { - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - return 'RSA-OAEP'; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} diff --git a/dist/browser/runtime/timing_safe_equal.js b/dist/browser/runtime/timing_safe_equal.js deleted file mode 100644 index 442cdccd20..0000000000 --- a/dist/browser/runtime/timing_safe_equal.js +++ /dev/null @@ -1,19 +0,0 @@ -const timingSafeEqual = (a, b) => { - if (!(a instanceof Uint8Array)) { - throw new TypeError('First argument must be a buffer'); - } - if (!(b instanceof Uint8Array)) { - throw new TypeError('Second argument must be a buffer'); - } - if (a.length !== b.length) { - throw new TypeError('Input buffers must have the same length'); - } - const len = a.length; - let out = 0; - let i = -1; - while (++i < len) { - out |= a[i] ^ b[i]; - } - return out === 0; -}; -export default timingSafeEqual; diff --git a/dist/browser/runtime/verify.js b/dist/browser/runtime/verify.js deleted file mode 100644 index 2ad4c7ffe2..0000000000 --- a/dist/browser/runtime/verify.js +++ /dev/null @@ -1,16 +0,0 @@ -import subtleAlgorithm from './subtle_dsa.js'; -import crypto from './webcrypto.js'; -import checkKeyLength from './check_key_length.js'; -import getVerifyKey from './get_sign_verify_key.js'; -const verify = async (alg, key, signature, data) => { - const cryptoKey = await getVerifyKey(alg, key, 'verify'); - checkKeyLength(alg, cryptoKey); - const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm); - try { - return await crypto.subtle.verify(algorithm, cryptoKey, signature, data); - } - catch (_a) { - return false; - } -}; -export default verify; diff --git a/dist/browser/runtime/webcrypto.js b/dist/browser/runtime/webcrypto.js deleted file mode 100644 index f9e1e91539..0000000000 --- a/dist/browser/runtime/webcrypto.js +++ /dev/null @@ -1,2 +0,0 @@ -export default crypto; -export const isCryptoKey = (key) => key instanceof CryptoKey; diff --git a/dist/browser/runtime/zlib.js b/dist/browser/runtime/zlib.js deleted file mode 100644 index e47cb532dc..0000000000 --- a/dist/browser/runtime/zlib.js +++ /dev/null @@ -1,7 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -export const inflate = async () => { - throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.'); -}; -export const deflate = async () => { - throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.'); -}; diff --git a/dist/browser/util/base64url.js b/dist/browser/util/base64url.js deleted file mode 100644 index 88ce7556d6..0000000000 --- a/dist/browser/util/base64url.js +++ /dev/null @@ -1,3 +0,0 @@ -import * as base64url from '../runtime/base64url.js'; -export const encode = base64url.encode; -export const decode = base64url.decode; diff --git a/dist/browser/util/decode_jwt.js b/dist/browser/util/decode_jwt.js deleted file mode 100644 index bea0ea9018..0000000000 --- a/dist/browser/util/decode_jwt.js +++ /dev/null @@ -1,32 +0,0 @@ -import { decode as base64url } from './base64url.js'; -import { decoder } from '../lib/buffer_utils.js'; -import isObject from '../lib/is_object.js'; -import { JWTInvalid } from './errors.js'; -export function decodeJwt(jwt) { - if (typeof jwt !== 'string') - throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string'); - const { 1: payload, length } = jwt.split('.'); - if (length === 5) - throw new JWTInvalid('Only JWTs using Compact JWS serialization can be decoded'); - if (length !== 3) - throw new JWTInvalid('Invalid JWT'); - if (!payload) - throw new JWTInvalid('JWTs must contain a payload'); - let decoded; - try { - decoded = base64url(payload); - } - catch (_a) { - throw new JWTInvalid('Failed to parse the base64url encoded payload'); - } - let result; - try { - result = JSON.parse(decoder.decode(decoded)); - } - catch (_b) { - throw new JWTInvalid('Failed to parse the decoded payload as JSON'); - } - if (!isObject(result)) - throw new JWTInvalid('Invalid JWT Claims Set'); - return result; -} diff --git a/dist/browser/util/decode_protected_header.js b/dist/browser/util/decode_protected_header.js deleted file mode 100644 index aecbfe2390..0000000000 --- a/dist/browser/util/decode_protected_header.js +++ /dev/null @@ -1,34 +0,0 @@ -import { decode as base64url } from './base64url.js'; -import { decoder } from '../lib/buffer_utils.js'; -import isObject from '../lib/is_object.js'; -export function decodeProtectedHeader(token) { - let protectedB64u; - if (typeof token === 'string') { - const parts = token.split('.'); - if (parts.length === 3 || parts.length === 5) { - ; - [protectedB64u] = parts; - } - } - else if (typeof token === 'object' && token) { - if ('protected' in token) { - protectedB64u = token.protected; - } - else { - throw new TypeError('Token does not contain a Protected Header'); - } - } - try { - if (typeof protectedB64u !== 'string' || !protectedB64u) { - throw new Error(); - } - const result = JSON.parse(decoder.decode(base64url(protectedB64u))); - if (!isObject(result)) { - throw new Error(); - } - return result; - } - catch (_a) { - throw new TypeError('Invalid Token or Protected Header formatting'); - } -} diff --git a/dist/browser/util/errors.js b/dist/browser/util/errors.js deleted file mode 100644 index 13a36f58fa..0000000000 --- a/dist/browser/util/errors.js +++ /dev/null @@ -1,148 +0,0 @@ -export class JOSEError extends Error { - static get code() { - return 'ERR_JOSE_GENERIC'; - } - constructor(message) { - var _a; - super(message); - this.code = 'ERR_JOSE_GENERIC'; - this.name = this.constructor.name; - (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); - } -} -export class JWTClaimValidationFailed extends JOSEError { - static get code() { - return 'ERR_JWT_CLAIM_VALIDATION_FAILED'; - } - constructor(message, claim = 'unspecified', reason = 'unspecified') { - super(message); - this.code = 'ERR_JWT_CLAIM_VALIDATION_FAILED'; - this.claim = claim; - this.reason = reason; - } -} -export class JWTExpired extends JOSEError { - static get code() { - return 'ERR_JWT_EXPIRED'; - } - constructor(message, claim = 'unspecified', reason = 'unspecified') { - super(message); - this.code = 'ERR_JWT_EXPIRED'; - this.claim = claim; - this.reason = reason; - } -} -export class JOSEAlgNotAllowed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JOSE_ALG_NOT_ALLOWED'; - } - static get code() { - return 'ERR_JOSE_ALG_NOT_ALLOWED'; - } -} -export class JOSENotSupported extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JOSE_NOT_SUPPORTED'; - } - static get code() { - return 'ERR_JOSE_NOT_SUPPORTED'; - } -} -export class JWEDecryptionFailed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWE_DECRYPTION_FAILED'; - this.message = 'decryption operation failed'; - } - static get code() { - return 'ERR_JWE_DECRYPTION_FAILED'; - } -} -export class JWEInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWE_INVALID'; - } - static get code() { - return 'ERR_JWE_INVALID'; - } -} -export class JWSInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWS_INVALID'; - } - static get code() { - return 'ERR_JWS_INVALID'; - } -} -export class JWTInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWT_INVALID'; - } - static get code() { - return 'ERR_JWT_INVALID'; - } -} -export class JWKInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWK_INVALID'; - } - static get code() { - return 'ERR_JWK_INVALID'; - } -} -export class JWKSInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_INVALID'; - } - static get code() { - return 'ERR_JWKS_INVALID'; - } -} -export class JWKSNoMatchingKey extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_NO_MATCHING_KEY'; - this.message = 'no applicable key found in the JSON Web Key Set'; - } - static get code() { - return 'ERR_JWKS_NO_MATCHING_KEY'; - } -} -export class JWKSMultipleMatchingKeys extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; - this.message = 'multiple matching keys found in the JSON Web Key Set'; - } - static get code() { - return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; - } -} -Symbol.asyncIterator; -export class JWKSTimeout extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_TIMEOUT'; - this.message = 'request timed out'; - } - static get code() { - return 'ERR_JWKS_TIMEOUT'; - } -} -export class JWSSignatureVerificationFailed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; - this.message = 'signature verification failed'; - } - static get code() { - return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; - } -} diff --git a/dist/deno/README.md b/dist/deno/README.md deleted file mode 100644 index 173a302ad6..0000000000 --- a/dist/deno/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# `jose` Modules API Documentation - -> "JSON Web Almost Everything" - JWA, JWS, JWE, JWT, JWK, JWKS with no dependencies using runtime's native crypto. - -## [đŸ’— Help the project](https://github.com/panva/jose/blob/v4.12.1/docs/https://github.com/sponsors/panva) - -## Available modules - -**`example`** Deno import -```js -import * as jose from 'https://deno.land/x/jose@v4.12.1/index.ts' -``` - -- JSON Web Tokens (JWT) - - [Signing](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jwt_sign.SignJWT.md#readme) - - [Verification & JWT Claims Set Validation](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwt_verify.jwtVerify.md#readme) - - Encrypted JSON Web Tokens - - [Encryption](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jwt_encrypt.EncryptJWT.md#readme) - - [Decryption & JWT Claims Set Validation](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwt_decrypt.jwtDecrypt.md#readme) -- Key Import - - [JWK Import](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_import.importJWK.md#readme) - - [Public Key Import (SPKI)](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_import.importSPKI.md#readme) - - [Public Key Import (X.509 Certificate)](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_import.importX509.md#readme) - - [Private Key Import (PKCS #8)](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_import.importPKCS8.md#readme) -- JSON Web Encryption (JWE) - - Encryption - [Compact](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jwe_compact_encrypt.CompactEncrypt.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jwe_flattened_encrypt.FlattenedEncrypt.md#readme), [General](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jwe_general_encrypt.GeneralEncrypt.md#readme) - - Decryption - [Compact](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwe_compact_decrypt.compactDecrypt.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwe_flattened_decrypt.flattenedDecrypt.md#readme), [General](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwe_general_decrypt.generalDecrypt.md#readme) -- JSON Web Signature (JWS) - - Signing - [Compact](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jws_compact_sign.CompactSign.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jws_flattened_sign.FlattenedSign.md#readme), [General](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jws_general_sign.GeneralSign.md#readme) - - Verification - [Compact](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jws_compact_verify.compactVerify.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jws_flattened_verify.flattenedVerify.md#readme), [General](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jws_general_verify.generalVerify.md#readme) -- JSON Web Key (JWK) - - [Calculating JWK Thumbprint](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwk_thumbprint.calculateJwkThumbprint.md#readme) - - [Calculating JWK Thumbprint URI](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwk_thumbprint.calculateJwkThumbprintUri.md#readme) - - [Verification using a JWK Embedded in a JWS Header](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwk_embedded.EmbeddedJWK.md#readme) -- JSON Web Key Set (JWKS) - - [Verify using a local JWKSet](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwks_local.createLocalJWKSet.md#readme) - - [Verify using a remote JWKSet](https://github.com/panva/jose/blob/v4.12.1/docs/functions/jwks_remote.createRemoteJWKSet.md#readme) -- Key Pair or Secret Generation - - [Asymmetric Key Pair Generation](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_generate_key_pair.generateKeyPair.md#readme) - - [Symmetric Secret Generation](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_generate_secret.generateSecret.md#readme) -- Key Export - - [JWK Export](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_export.exportJWK.md#readme) - - [Private Key Export](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_export.exportPKCS8.md#readme) - - [Public Key Export](https://github.com/panva/jose/blob/v4.12.1/docs/functions/key_export.exportSPKI.md#readme) -- Utilities - - [Decoding Token's Protected Header](https://github.com/panva/jose/blob/v4.12.1/docs/functions/util_decode_protected_header.decodeProtectedHeader.md#readme) - - [Decoding JWT Claims Set](https://github.com/panva/jose/blob/v4.12.1/docs/functions/util_decode_jwt.decodeJwt.md#readme) -- [Unsecured JWT](https://github.com/panva/jose/blob/v4.12.1/docs/classes/jwt_unsecured.UnsecuredJWT.md#readme) -- [JOSE Errors](https://github.com/panva/jose/blob/v4.12.1/docs/modules/util_errors.md#readme) - -[support-sponsor]: https://github.com/sponsors/panva diff --git a/dist/deno/index.ts b/dist/deno/index.ts deleted file mode 100644 index 611b8e0d4c..0000000000 --- a/dist/deno/index.ts +++ /dev/null @@ -1,98 +0,0 @@ -export { compactDecrypt } from './jwe/compact/decrypt.ts' -export type { CompactDecryptGetKey } from './jwe/compact/decrypt.ts' -export { flattenedDecrypt } from './jwe/flattened/decrypt.ts' -export type { FlattenedDecryptGetKey } from './jwe/flattened/decrypt.ts' -export { generalDecrypt } from './jwe/general/decrypt.ts' -export type { GeneralDecryptGetKey } from './jwe/general/decrypt.ts' -export { GeneralEncrypt } from './jwe/general/encrypt.ts' -export type { Recipient } from './jwe/general/encrypt.ts' - -export { compactVerify } from './jws/compact/verify.ts' -export type { CompactVerifyGetKey } from './jws/compact/verify.ts' -export { flattenedVerify } from './jws/flattened/verify.ts' -export type { FlattenedVerifyGetKey } from './jws/flattened/verify.ts' -export { generalVerify } from './jws/general/verify.ts' -export type { GeneralVerifyGetKey } from './jws/general/verify.ts' - -export { jwtVerify } from './jwt/verify.ts' -export type { JWTVerifyOptions, JWTVerifyGetKey } from './jwt/verify.ts' -export { jwtDecrypt } from './jwt/decrypt.ts' -export type { JWTDecryptOptions, JWTDecryptGetKey } from './jwt/decrypt.ts' -export type { ProduceJWT } from './jwt/produce.ts' - -export { CompactEncrypt } from './jwe/compact/encrypt.ts' -export { FlattenedEncrypt } from './jwe/flattened/encrypt.ts' - -export { CompactSign } from './jws/compact/sign.ts' -export { FlattenedSign } from './jws/flattened/sign.ts' -export { GeneralSign } from './jws/general/sign.ts' -export type { Signature } from './jws/general/sign.ts' - -export { SignJWT } from './jwt/sign.ts' -export { EncryptJWT } from './jwt/encrypt.ts' - -export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.ts' -export { EmbeddedJWK } from './jwk/embedded.ts' - -export { createLocalJWKSet } from './jwks/local.ts' -export { createRemoteJWKSet } from './jwks/remote.ts' -export type { RemoteJWKSetOptions } from './jwks/remote.ts' - -export { UnsecuredJWT } from './jwt/unsecured.ts' -export type { UnsecuredResult } from './jwt/unsecured.ts' - -export { exportPKCS8, exportSPKI, exportJWK } from './key/export.ts' - -export { importSPKI, importPKCS8, importX509, importJWK } from './key/import.ts' -export type { PEMImportOptions } from './key/import.ts' - -export { decodeProtectedHeader } from './util/decode_protected_header.ts' -export { decodeJwt } from './util/decode_jwt.ts' -export type { ProtectedHeaderParameters } from './util/decode_protected_header.ts' - -export * as errors from './util/errors.ts' - -export { generateKeyPair } from './key/generate_key_pair.ts' -export type { GenerateKeyPairResult, GenerateKeyPairOptions } from './key/generate_key_pair.ts' -export { generateSecret } from './key/generate_secret.ts' -export type { GenerateSecretOptions } from './key/generate_secret.ts' - -export * as base64url from './util/base64url.ts' - -export type { - KeyLike, - JWK, - FlattenedJWSInput, - GeneralJWSInput, - FlattenedJWS, - GeneralJWS, - JoseHeaderParameters, - JWSHeaderParameters, - JWEKeyManagementHeaderParameters, - FlattenedJWE, - GeneralJWE, - JWEHeaderParameters, - CritOption, - DeflateOption, - DecryptOptions, - EncryptOptions, - JWTClaimVerificationOptions, - VerifyOptions, - SignOptions, - JWTPayload, - DeflateFunction, - InflateFunction, - FlattenedDecryptResult, - GeneralDecryptResult, - CompactDecryptResult, - FlattenedVerifyResult, - GeneralVerifyResult, - CompactVerifyResult, - JWTVerifyResult, - JWTDecryptResult, - ResolvedKey, - CompactJWEHeaderParameters, - CompactJWSHeaderParameters, - JWTHeaderParameters, - JSONWebKeySet, -} from './types.d.ts' diff --git a/dist/deno/jwe/compact/decrypt.ts b/dist/deno/jwe/compact/decrypt.ts deleted file mode 100644 index f3bec8eca6..0000000000 --- a/dist/deno/jwe/compact/decrypt.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { flattenedDecrypt } from '../flattened/decrypt.ts' -import { JWEInvalid } from '../../util/errors.ts' -import { decoder } from '../../lib/buffer_utils.ts' -import type { - KeyLike, - DecryptOptions, - CompactJWEHeaderParameters, - GetKeyFunction, - FlattenedJWE, - CompactDecryptResult, - ResolvedKey, -} from '../../types.d.ts' - -/** - * Interface for Compact JWE Decryption dynamic key resolution. No token components have been - * verified at the time of this function call. - */ -export interface CompactDecryptGetKey - extends GetKeyFunction {} - -/** - * Decrypts a Compact JWE. - * - * @example Usage - * - * ```js - * const jwe = - * 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.nyQ19eq9ogh9wA7fFtnI2oouzy5_8b5DeLkoRMfi2yijgfTs2zEnayCEofz_qhnL-nwszabd9qUeHv0-IwvhhJJS7GUJOU3ikiIe42qcIAFme1A_Fo9CTxw4XTOy-I5qanl8So91u6hwfyN1VxAqVLsSE7_23EC-gfGEg_5znew9PyXXsOIE-K_HH7IQowRrlZ1X_bM_Liu53RzDpLDvRz59mp3S8L56YqpM8FexFGTGpEaoTcEIst375qncYt3-79IVR7gZN1RWsWgjPatfvVbnh74PglQcATSf3UUhaW0OAKn6q7r3PDx6DIKQ35bgHQg5QopuN00eIfLQL2trGw.W3grIVj5HVuAb76X.6PcuDe5D6ttWFYyv0oqqdDXfI2R8wBg1F2Q80UUA_Gv8eEimNWfxIWdLxrjzgQGSvIhxmFKuLM0.a93_Ug3uZHuczj70Zavx8Q' - * - * const { plaintext, protectedHeader } = await jose.compactDecrypt(jwe, privateKey) - * - * console.log(protectedHeader) - * console.log(new TextDecoder().decode(plaintext)) - * ``` - * - * @param jwe Compact JWE. - * @param key Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export async function compactDecrypt( - jwe: string | Uint8Array, - key: KeyLike | Uint8Array, - options?: DecryptOptions, -): Promise -/** - * @param jwe Compact JWE. - * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export async function compactDecrypt( - jwe: string | Uint8Array, - getKey: CompactDecryptGetKey, - options?: DecryptOptions, -): Promise -export async function compactDecrypt( - jwe: string | Uint8Array, - key: KeyLike | Uint8Array | CompactDecryptGetKey, - options?: DecryptOptions, -) { - if (jwe instanceof Uint8Array) { - jwe = decoder.decode(jwe) - } - - if (typeof jwe !== 'string') { - throw new JWEInvalid('Compact JWE must be a string or Uint8Array') - } - const { - 0: protectedHeader, - 1: encryptedKey, - 2: iv, - 3: ciphertext, - 4: tag, - length, - } = jwe.split('.') - - if (length !== 5) { - throw new JWEInvalid('Invalid Compact JWE') - } - - const decrypted = await flattenedDecrypt( - { - ciphertext, - iv: (iv || undefined), - protected: protectedHeader || undefined, - tag: (tag || undefined), - encrypted_key: encryptedKey || undefined, - }, - [1]>key, - options, - ) - - const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader! } - - if (typeof key === 'function') { - return { ...result, key: decrypted.key } - } - - return result -} diff --git a/dist/deno/jwe/compact/encrypt.ts b/dist/deno/jwe/compact/encrypt.ts deleted file mode 100644 index bc704a7f0b..0000000000 --- a/dist/deno/jwe/compact/encrypt.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { FlattenedEncrypt } from '../flattened/encrypt.ts' -import type { - KeyLike, - JWEKeyManagementHeaderParameters, - CompactJWEHeaderParameters, - EncryptOptions, -} from '../../types.d.ts' - -/** - * The CompactEncrypt class is a utility for creating Compact JWE strings. - * - * @example Usage - * - * ```js - * const jwe = await new jose.CompactEncrypt( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) - * .encrypt(publicKey) - * - * console.log(jwe) - * ``` - */ -export class CompactEncrypt { - private _flattened: FlattenedEncrypt - - /** @param plaintext Binary representation of the plaintext to encrypt. */ - constructor(plaintext: Uint8Array) { - this._flattened = new FlattenedEncrypt(plaintext) - } - - /** - * Sets a content encryption key to use, by default a random suitable one is generated for the JWE - * enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param cek JWE Content Encryption Key. - */ - setContentEncryptionKey(cek: Uint8Array) { - this._flattened.setContentEncryptionKey(cek) - return this - } - - /** - * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable - * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param iv JWE Initialization Vector. - */ - setInitializationVector(iv: Uint8Array) { - this._flattened.setInitializationVector(iv) - return this - } - - /** - * Sets the JWE Protected Header on the CompactEncrypt object. - * - * @param protectedHeader JWE Protected Header object. - */ - setProtectedHeader(protectedHeader: CompactJWEHeaderParameters) { - this._flattened.setProtectedHeader(protectedHeader) - return this - } - - /** - * Sets the JWE Key Management parameters to be used when encrypting the Content Encryption Key. - * You do not need to invoke this method, it is only really intended for test and vector - * validation purposes. - * - * @param parameters JWE Key Management parameters. - */ - setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters) { - this._flattened.setKeyManagementParameters(parameters) - return this - } - - /** - * Encrypts and resolves the value of the Compact JWE string. - * - * @param key Public Key or Secret to encrypt the JWE with. - * @param options JWE Encryption options. - */ - async encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise { - const jwe = await this._flattened.encrypt(key, options) - - return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.') - } -} diff --git a/dist/deno/jwe/flattened/decrypt.ts b/dist/deno/jwe/flattened/decrypt.ts deleted file mode 100644 index 6b5e4fd0eb..0000000000 --- a/dist/deno/jwe/flattened/decrypt.ts +++ /dev/null @@ -1,247 +0,0 @@ -import { decode as base64url } from '../../runtime/base64url.ts' -import decrypt from '../../runtime/decrypt.ts' -import { inflate } from '../../runtime/zlib.ts' - -import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.ts' -import isDisjoint from '../../lib/is_disjoint.ts' -import isObject from '../../lib/is_object.ts' -import decryptKeyManagement from '../../lib/decrypt_key_management.ts' -import type { - FlattenedDecryptResult, - KeyLike, - FlattenedJWE, - JWEHeaderParameters, - DecryptOptions, - GetKeyFunction, - ResolvedKey, -} from '../../types.d.ts' -import { encoder, decoder, concat } from '../../lib/buffer_utils.ts' -import generateCek from '../../lib/cek.ts' -import validateCrit from '../../lib/validate_crit.ts' -import validateAlgorithms from '../../lib/validate_algorithms.ts' - -/** - * Interface for Flattened JWE Decryption dynamic key resolution. No token components have been - * verified at the time of this function call. - */ -export interface FlattenedDecryptGetKey - extends GetKeyFunction {} - -/** - * Decrypts a Flattened JWE. - * - * @example Usage - * - * ```js - * const jwe = { - * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', - * iv: '8Fy7A_IuoX5VXG9s', - * tag: 'W76IYV6arGRuDSaSyWrQNg', - * encrypted_key: - * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', - * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', - * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', - * } - * - * const { plaintext, protectedHeader, additionalAuthenticatedData } = - * await jose.flattenedDecrypt(jwe, privateKey) - * - * console.log(protectedHeader) - * const decoder = new TextDecoder() - * console.log(decoder.decode(plaintext)) - * console.log(decoder.decode(additionalAuthenticatedData)) - * ``` - * - * @param jwe Flattened JWE. - * @param key Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export function flattenedDecrypt( - jwe: FlattenedJWE, - key: KeyLike | Uint8Array, - options?: DecryptOptions, -): Promise -/** - * @param jwe Flattened JWE. - * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export function flattenedDecrypt( - jwe: FlattenedJWE, - getKey: FlattenedDecryptGetKey, - options?: DecryptOptions, -): Promise -export async function flattenedDecrypt( - jwe: FlattenedJWE, - key: KeyLike | Uint8Array | FlattenedDecryptGetKey, - options?: DecryptOptions, -) { - if (!isObject(jwe)) { - throw new JWEInvalid('Flattened JWE must be an object') - } - - if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { - throw new JWEInvalid('JOSE Header missing') - } - - if (typeof jwe.iv !== 'string') { - throw new JWEInvalid('JWE Initialization Vector missing or incorrect type') - } - - if (typeof jwe.ciphertext !== 'string') { - throw new JWEInvalid('JWE Ciphertext missing or incorrect type') - } - - if (typeof jwe.tag !== 'string') { - throw new JWEInvalid('JWE Authentication Tag missing or incorrect type') - } - - if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { - throw new JWEInvalid('JWE Protected Header incorrect type') - } - - if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { - throw new JWEInvalid('JWE Encrypted Key incorrect type') - } - - if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { - throw new JWEInvalid('JWE AAD incorrect type') - } - - if (jwe.header !== undefined && !isObject(jwe.header)) { - throw new JWEInvalid('JWE Shared Unprotected Header incorrect type') - } - - if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) { - throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type') - } - - let parsedProt!: JWEHeaderParameters - if (jwe.protected) { - try { - const protectedHeader = base64url(jwe.protected) - parsedProt = JSON.parse(decoder.decode(protectedHeader)) - } catch { - throw new JWEInvalid('JWE Protected Header is invalid') - } - } - if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) { - throw new JWEInvalid( - 'JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint', - ) - } - - const joseHeader: JWEHeaderParameters = { - ...parsedProt, - ...jwe.header, - ...jwe.unprotected, - } - - validateCrit(JWEInvalid, new Map(), options?.crit, parsedProt, joseHeader) - - if (joseHeader.zip !== undefined) { - if (!parsedProt || !parsedProt.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected') - } - - if (joseHeader.zip !== 'DEF') { - throw new JOSENotSupported( - 'Unsupported JWE "zip" (Compression Algorithm) Header Parameter value', - ) - } - } - - const { alg, enc } = joseHeader - - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header') - } - - if (typeof enc !== 'string' || !enc) { - throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header') - } - - const keyManagementAlgorithms = - options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms) - const contentEncryptionAlgorithms = - options && - validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms) - - if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed') - } - - if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { - throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed') - } - - let encryptedKey!: Uint8Array - if (jwe.encrypted_key !== undefined) { - encryptedKey = base64url(jwe.encrypted_key!) - } - - let resolvedKey = false - if (typeof key === 'function') { - key = await key(parsedProt, jwe) - resolvedKey = true - } - - let cek: KeyLike | Uint8Array - try { - cek = await decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) - } catch (err) { - if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { - throw err - } - // https://www.rfc-editor.org/rfc/rfc7516#section-11.5 - // To mitigate the attacks described in RFC 3218, the - // recipient MUST NOT distinguish between format, padding, and length - // errors of encrypted keys. It is strongly recommended, in the event - // of receiving an improperly formatted key, that the recipient - // substitute a randomly generated CEK and proceed to the next step, to - // mitigate timing attacks. - cek = generateCek(enc) - } - - const iv = base64url(jwe.iv) - const tag = base64url(jwe.tag) - - const protectedHeader: Uint8Array = encoder.encode(jwe.protected ?? '') - let additionalData: Uint8Array - - if (jwe.aad !== undefined) { - additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(jwe.aad)) - } else { - additionalData = protectedHeader - } - - let plaintext = await decrypt(enc, cek, base64url(jwe.ciphertext), iv, tag, additionalData) - - if (joseHeader.zip === 'DEF') { - plaintext = await (options?.inflateRaw || inflate)(plaintext) - } - - const result: FlattenedDecryptResult = { plaintext } - - if (jwe.protected !== undefined) { - result.protectedHeader = parsedProt - } - - if (jwe.aad !== undefined) { - result.additionalAuthenticatedData = base64url(jwe.aad!) - } - - if (jwe.unprotected !== undefined) { - result.sharedUnprotectedHeader = jwe.unprotected - } - - if (jwe.header !== undefined) { - result.unprotectedHeader = jwe.header - } - - if (resolvedKey) { - return { ...result, key } - } - - return result -} diff --git a/dist/deno/jwe/flattened/encrypt.ts b/dist/deno/jwe/flattened/encrypt.ts deleted file mode 100644 index 966af35b25..0000000000 --- a/dist/deno/jwe/flattened/encrypt.ts +++ /dev/null @@ -1,309 +0,0 @@ -import { encode as base64url } from '../../runtime/base64url.ts' -import encrypt from '../../runtime/encrypt.ts' -import { deflate } from '../../runtime/zlib.ts' - -import type { - KeyLike, - FlattenedJWE, - JWEHeaderParameters, - JWEKeyManagementHeaderParameters, - EncryptOptions, -} from '../../types.d.ts' -import generateIv from '../../lib/iv.ts' -import encryptKeyManagement from '../../lib/encrypt_key_management.ts' -import { JOSENotSupported, JWEInvalid } from '../../util/errors.ts' -import isDisjoint from '../../lib/is_disjoint.ts' -import { encoder, decoder, concat } from '../../lib/buffer_utils.ts' -import validateCrit from '../../lib/validate_crit.ts' - -/** @private */ -export const unprotected = Symbol() - -/** - * The FlattenedEncrypt class is a utility for creating Flattened JWE objects. - * - * @example Usage - * - * ```js - * const jwe = await new jose.FlattenedEncrypt( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) - * .setAdditionalAuthenticatedData(encoder.encode('The Fellowship of the Ring')) - * .encrypt(publicKey) - * - * console.log(jwe) - * ``` - */ -export class FlattenedEncrypt { - private _plaintext: Uint8Array - - private _protectedHeader!: JWEHeaderParameters - - private _sharedUnprotectedHeader!: JWEHeaderParameters - - private _unprotectedHeader!: JWEHeaderParameters - - private _aad!: Uint8Array - - private _cek!: Uint8Array - - private _iv!: Uint8Array - - private _keyManagementParameters!: JWEKeyManagementHeaderParameters - - /** @param plaintext Binary representation of the plaintext to encrypt. */ - constructor(plaintext: Uint8Array) { - if (!(plaintext instanceof Uint8Array)) { - throw new TypeError('plaintext must be an instance of Uint8Array') - } - this._plaintext = plaintext - } - - /** - * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is - * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or - * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed - * and missing. - * - * @param parameters JWE Key Management parameters. - */ - setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once') - } - this._keyManagementParameters = parameters - return this - } - - /** - * Sets the JWE Protected Header on the FlattenedEncrypt object. - * - * @param protectedHeader JWE Protected Header. - */ - setProtectedHeader(protectedHeader: JWEHeaderParameters) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once') - } - this._protectedHeader = protectedHeader - return this - } - - /** - * Sets the JWE Shared Unprotected Header on the FlattenedEncrypt object. - * - * @param sharedUnprotectedHeader JWE Shared Unprotected Header. - */ - setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters) { - if (this._sharedUnprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once') - } - this._sharedUnprotectedHeader = sharedUnprotectedHeader - return this - } - - /** - * Sets the JWE Per-Recipient Unprotected Header on the FlattenedEncrypt object. - * - * @param unprotectedHeader JWE Per-Recipient Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once') - } - this._unprotectedHeader = unprotectedHeader - return this - } - - /** - * Sets the Additional Authenticated Data on the FlattenedEncrypt object. - * - * @param aad Additional Authenticated Data. - */ - setAdditionalAuthenticatedData(aad: Uint8Array) { - this._aad = aad - return this - } - - /** - * Sets a content encryption key to use, by default a random suitable one is generated for the JWE - * enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param cek JWE Content Encryption Key. - */ - setContentEncryptionKey(cek: Uint8Array) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once') - } - this._cek = cek - return this - } - - /** - * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable - * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param iv JWE Initialization Vector. - */ - setInitializationVector(iv: Uint8Array) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once') - } - this._iv = iv - return this - } - - /** - * Encrypts and resolves the value of the Flattened JWE object. - * - * @param key Public Key or Secret to encrypt the JWE with. - * @param options JWE Encryption options. - */ - async encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions) { - if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { - throw new JWEInvalid( - 'either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()', - ) - } - - if ( - !isDisjoint(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader) - ) { - throw new JWEInvalid( - 'JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint', - ) - } - - const joseHeader: JWEHeaderParameters = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...this._sharedUnprotectedHeader, - } - - validateCrit(JWEInvalid, new Map(), options?.crit, this._protectedHeader, joseHeader) - - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected') - } - - if (joseHeader.zip !== 'DEF') { - throw new JOSENotSupported( - 'Unsupported JWE "zip" (Compression Algorithm) Header Parameter value', - ) - } - } - - const { alg, enc } = joseHeader - - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid') - } - - if (typeof enc !== 'string' || !enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid') - } - - let encryptedKey: Uint8Array | undefined - - if (alg === 'dir') { - if (this._cek) { - throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption') - } - } else if (alg === 'ECDH-ES') { - if (this._cek) { - throw new TypeError( - 'setContentEncryptionKey cannot be called when using Direct Key Agreement', - ) - } - } - - let cek: KeyLike | Uint8Array - { - let parameters: { [propName: string]: unknown } | undefined - ;({ cek, encryptedKey, parameters } = await encryptKeyManagement( - alg, - enc, - key, - this._cek, - this._keyManagementParameters, - )) - - if (parameters) { - if (options && unprotected in options) { - if (!this._unprotectedHeader) { - this.setUnprotectedHeader(parameters) - } else { - this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters } - } - } else { - if (!this._protectedHeader) { - this.setProtectedHeader(parameters) - } else { - this._protectedHeader = { ...this._protectedHeader, ...parameters } - } - } - } - } - - this._iv ||= generateIv(enc) - - let additionalData: Uint8Array - let protectedHeader: Uint8Array - let aadMember: string | undefined - if (this._protectedHeader) { - protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))) - } else { - protectedHeader = encoder.encode('') - } - - if (this._aad) { - aadMember = base64url(this._aad) - additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember)) - } else { - additionalData = protectedHeader - } - - let ciphertext: Uint8Array - let tag: Uint8Array - - if (joseHeader.zip === 'DEF') { - const deflated = await (options?.deflateRaw || deflate)(this._plaintext) - ;({ ciphertext, tag } = await encrypt(enc, deflated, cek, this._iv, additionalData)) - } else { - ;({ ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData)) - } - - const jwe: FlattenedJWE = { - ciphertext: base64url(ciphertext), - iv: base64url(this._iv), - tag: base64url(tag), - } - - if (encryptedKey) { - jwe.encrypted_key = base64url(encryptedKey) - } - - if (aadMember) { - jwe.aad = aadMember - } - - if (this._protectedHeader) { - jwe.protected = decoder.decode(protectedHeader) - } - - if (this._sharedUnprotectedHeader) { - jwe.unprotected = this._sharedUnprotectedHeader - } - - if (this._unprotectedHeader) { - jwe.header = this._unprotectedHeader - } - - return jwe - } -} diff --git a/dist/deno/jwe/general/decrypt.ts b/dist/deno/jwe/general/decrypt.ts deleted file mode 100644 index c674f3b99b..0000000000 --- a/dist/deno/jwe/general/decrypt.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { flattenedDecrypt } from '../flattened/decrypt.ts' -import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.ts' -import type { - KeyLike, - DecryptOptions, - JWEHeaderParameters, - GetKeyFunction, - FlattenedJWE, - GeneralJWE, - GeneralDecryptResult, - ResolvedKey, -} from '../../types.d.ts' -import isObject from '../../lib/is_object.ts' - -/** - * Interface for General JWE Decryption dynamic key resolution. No token components have been - * verified at the time of this function call. - */ -export interface GeneralDecryptGetKey extends GetKeyFunction {} - -/** - * Decrypts a General JWE. - * - * @example Usage - * - * ```js - * const jwe = { - * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', - * iv: '8Fy7A_IuoX5VXG9s', - * tag: 'W76IYV6arGRuDSaSyWrQNg', - * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', - * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', - * recipients: [ - * { - * encrypted_key: - * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', - * }, - * ], - * } - * - * const { plaintext, protectedHeader, additionalAuthenticatedData } = - * await jose.generalDecrypt(jwe, privateKey) - * - * console.log(protectedHeader) - * const decoder = new TextDecoder() - * console.log(decoder.decode(plaintext)) - * console.log(decoder.decode(additionalAuthenticatedData)) - * ``` - * - * @param jwe General JWE. - * @param key Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export function generalDecrypt( - jwe: GeneralJWE, - key: KeyLike | Uint8Array, - options?: DecryptOptions, -): Promise -/** - * @param jwe General JWE. - * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export function generalDecrypt( - jwe: GeneralJWE, - getKey: GeneralDecryptGetKey, - options?: DecryptOptions, -): Promise -export async function generalDecrypt( - jwe: GeneralJWE, - key: KeyLike | Uint8Array | GeneralDecryptGetKey, - options?: DecryptOptions, -) { - if (!isObject(jwe)) { - throw new JWEInvalid('General JWE must be an object') - } - - if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { - throw new JWEInvalid('JWE Recipients missing or incorrect type') - } - - if (!jwe.recipients.length) { - throw new JWEInvalid('JWE Recipients has no members') - } - - for (const recipient of jwe.recipients) { - try { - return await flattenedDecrypt( - { - aad: jwe.aad, - ciphertext: jwe.ciphertext, - encrypted_key: recipient.encrypted_key, - header: recipient.header, - iv: jwe.iv, - protected: jwe.protected, - tag: jwe.tag, - unprotected: jwe.unprotected, - }, - [1]>key, - options, - ) - } catch { - // - } - } - throw new JWEDecryptionFailed() -} diff --git a/dist/deno/jwe/general/encrypt.ts b/dist/deno/jwe/general/encrypt.ts deleted file mode 100644 index e97d976f29..0000000000 --- a/dist/deno/jwe/general/encrypt.ts +++ /dev/null @@ -1,306 +0,0 @@ -import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.ts' -import { JWEInvalid } from '../../util/errors.ts' -import generateCek from '../../lib/cek.ts' -import isDisjoint from '../../lib/is_disjoint.ts' -import encryptKeyManagement from '../../lib/encrypt_key_management.ts' -import { encode as base64url } from '../../runtime/base64url.ts' -import validateCrit from '../../lib/validate_crit.ts' - -import type { - KeyLike, - GeneralJWE, - JWEHeaderParameters, - CritOption, - DeflateOption, -} from '../../types.d.ts' - -export interface Recipient { - /** - * Sets the JWE Per-Recipient Unprotected Header on the Recipient object. - * - * @param unprotectedHeader JWE Per-Recipient Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters): Recipient - - /** A shorthand for calling addRecipient() on the enclosing GeneralEncrypt instance */ - addRecipient(...args: Parameters): Recipient - - /** A shorthand for calling encrypt() on the enclosing GeneralEncrypt instance */ - encrypt(...args: Parameters): Promise - - /** Returns the enclosing GeneralEncrypt */ - done(): GeneralEncrypt -} - -class IndividualRecipient implements Recipient { - private parent: GeneralEncrypt - unprotectedHeader?: JWEHeaderParameters - key: KeyLike | Uint8Array - options: CritOption - - constructor(enc: GeneralEncrypt, key: KeyLike | Uint8Array, options: CritOption) { - this.parent = enc - this.key = key - this.options = options - } - - setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once') - } - this.unprotectedHeader = unprotectedHeader - return this - } - - addRecipient(...args: Parameters) { - return this.parent.addRecipient(...args) - } - - encrypt(...args: Parameters) { - return this.parent.encrypt(...args) - } - - done() { - return this.parent - } -} - -/** - * The GeneralEncrypt class is a utility for creating General JWE objects. - * - * @example Usage - * - * ```js - * const jwe = await new jose.GeneralEncrypt( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ enc: 'A256GCM' }) - * .addRecipient(ecPublicKey) - * .setUnprotectedHeader({ alg: 'ECDH-ES+A256KW' }) - * .addRecipient(rsaPublicKey) - * .setUnprotectedHeader({ alg: 'RSA-OAEP-384' }) - * .encrypt() - * - * console.log(jwe) - * ``` - */ -export class GeneralEncrypt { - private _plaintext: Uint8Array - - private _recipients: IndividualRecipient[] = [] - - private _protectedHeader!: JWEHeaderParameters - - private _unprotectedHeader!: JWEHeaderParameters - - private _aad!: Uint8Array - - /** @param plaintext Binary representation of the plaintext to encrypt. */ - constructor(plaintext: Uint8Array) { - this._plaintext = plaintext - } - - /** - * Adds an additional recipient for the General JWE object. - * - * @param key Public Key or Secret to encrypt the Content Encryption Key for the recipient with. - * @param options JWE Encryption options. - */ - addRecipient(key: KeyLike | Uint8Array, options?: CritOption): Recipient { - const recipient = new IndividualRecipient(this, key, { crit: options?.crit }) - this._recipients.push(recipient) - return recipient - } - - /** - * Sets the JWE Protected Header on the GeneralEncrypt object. - * - * @param protectedHeader JWE Protected Header object. - */ - setProtectedHeader(protectedHeader: JWEHeaderParameters): this { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once') - } - this._protectedHeader = protectedHeader - return this - } - - /** - * Sets the JWE Shared Unprotected Header on the GeneralEncrypt object. - * - * @param sharedUnprotectedHeader JWE Shared Unprotected Header object. - */ - setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters): this { - if (this._unprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once') - } - this._unprotectedHeader = sharedUnprotectedHeader - return this - } - - /** - * Sets the Additional Authenticated Data on the GeneralEncrypt object. - * - * @param aad Additional Authenticated Data. - */ - setAdditionalAuthenticatedData(aad: Uint8Array) { - this._aad = aad - return this - } - - /** - * Encrypts and resolves the value of the General JWE object. - * - * @param options JWE Encryption options. - */ - async encrypt(options?: DeflateOption): Promise { - if (!this._recipients.length) { - throw new JWEInvalid('at least one recipient must be added') - } - - options = { deflateRaw: options?.deflateRaw } - - if (this._recipients.length === 1) { - const [recipient] = this._recipients - - const flattened = await new FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader!) - .encrypt(recipient.key, { ...recipient.options, ...options }) - - let jwe: GeneralJWE = { - ciphertext: flattened.ciphertext, - iv: flattened.iv, - recipients: [{}], - tag: flattened.tag, - } - - if (flattened.aad) jwe.aad = flattened.aad - if (flattened.protected) jwe.protected = flattened.protected - if (flattened.unprotected) jwe.unprotected = flattened.unprotected - if (flattened.encrypted_key) jwe.recipients![0].encrypted_key = flattened.encrypted_key - if (flattened.header) jwe.recipients![0].header = flattened.header - - return jwe - } - - let enc!: string - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i] - if ( - !isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader) - ) { - throw new JWEInvalid( - 'JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint', - ) - } - - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - } - - const { alg } = joseHeader - - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid') - } - - if (alg === 'dir' || alg === 'ECDH-ES') { - throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient') - } - - if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid') - } - - if (!enc) { - enc = joseHeader.enc - } else if (enc !== joseHeader.enc) { - throw new JWEInvalid( - 'JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients', - ) - } - - validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader) - - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid( - 'JWE "zip" (Compression Algorithm) Header MUST be integrity protected', - ) - } - } - } - - const cek = generateCek(enc) - - let jwe: GeneralJWE = { - ciphertext: '', - iv: '', - recipients: [], - tag: '', - } - - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i] - const target: Record = {} - jwe.recipients!.push(target) - - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - } - - const p2c = joseHeader.alg!.startsWith('PBES2') ? 2048 + i : undefined - - if (i === 0) { - const flattened = await new FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setContentEncryptionKey(cek) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader!) - .setKeyManagementParameters({ p2c }) - .encrypt(recipient.key, { - ...recipient.options, - ...options, - // @ts-expect-error - [unprotected]: true, - }) - - jwe.ciphertext = flattened.ciphertext - jwe.iv = flattened.iv - jwe.tag = flattened.tag - - if (flattened.aad) jwe.aad = flattened.aad - if (flattened.protected) jwe.protected = flattened.protected - if (flattened.unprotected) jwe.unprotected = flattened.unprotected - - target.encrypted_key = flattened.encrypted_key! - if (flattened.header) target.header = flattened.header - - continue - } - - const { encryptedKey, parameters } = await encryptKeyManagement( - recipient.unprotectedHeader?.alg! || - this._protectedHeader?.alg! || - this._unprotectedHeader?.alg!, - enc, - recipient.key, - cek, - { p2c }, - ) - target.encrypted_key = base64url(encryptedKey!) - if (recipient.unprotectedHeader || parameters) - target.header = { ...recipient.unprotectedHeader, ...parameters } - } - - return jwe - } -} diff --git a/dist/deno/jwk/embedded.ts b/dist/deno/jwk/embedded.ts deleted file mode 100644 index f56e12fc52..0000000000 --- a/dist/deno/jwk/embedded.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { FlattenedJWSInput, JWSHeaderParameters } from '../types.d.ts' -import { importJWK } from '../key/import.ts' -import isObject from '../lib/is_object.ts' -import { JWSInvalid } from '../util/errors.ts' - -/** - * EmbeddedJWK is an implementation of a GetKeyFunction intended to be used with the JWS/JWT verify - * operations whenever you need to opt-in to verify signatures with a public key embedded in the - * token's "jwk" (JSON Web Key) Header Parameter. It is recommended to combine this with the verify - * function's `algorithms` option to define accepted JWS "alg" (Algorithm) Header Parameter values. - * - * @example Usage - * - * ```js - * const jwt = - * 'eyJqd2siOnsiY3J2IjoiUC0yNTYiLCJ4IjoiVU05ZzVuS25aWFlvdldBbE03NmNMejl2VG96UmpfX0NIVV9kT2wtZ09vRSIsInkiOiJkczhhZVF3MWwyY0RDQTdiQ2tPTnZ3REtwWEFidFhqdnFDbGVZSDhXc19VIiwia3R5IjoiRUMifSwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSIsImlhdCI6MTYwNDU4MDc5NH0.60boak3_dErnW47ZPty1C0nrjeVq86EN_eK0GOq6K8w2OA0thKoBxFK4j-NuU9yZ_A9UKGxPT_G87DladBaV9g' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, jose.EmbeddedJWK, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - */ -export async function EmbeddedJWK(protectedHeader: JWSHeaderParameters, token: FlattenedJWSInput) { - const joseHeader = { - ...protectedHeader, - ...token.header, - } - if (!isObject(joseHeader.jwk)) { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object') - } - - const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg!, true) - - if (key instanceof Uint8Array || key.type !== 'public') { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key') - } - - return key -} diff --git a/dist/deno/jwk/thumbprint.ts b/dist/deno/jwk/thumbprint.ts deleted file mode 100644 index 2e5f410b1f..0000000000 --- a/dist/deno/jwk/thumbprint.ts +++ /dev/null @@ -1,114 +0,0 @@ -import digest from '../runtime/digest.ts' -import { encode as base64url } from '../runtime/base64url.ts' - -import { JOSENotSupported, JWKInvalid } from '../util/errors.ts' -import { encoder } from '../lib/buffer_utils.ts' -import type { JWK } from '../types.d.ts' -import isObject from '../lib/is_object.ts' - -const check = (value: unknown, description: string) => { - if (typeof value !== 'string' || !value) { - throw new JWKInvalid(`${description} missing or invalid`) - } -} - -/** - * Calculates a base64url-encoded JSON Web Key (JWK) Thumbprint - * - * @example Usage - * - * ```js - * const thumbprint = await jose.calculateJwkThumbprint({ - * kty: 'EC', - * crv: 'P-256', - * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', - * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', - * }) - * - * console.log(thumbprint) - * // 'w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' - * ``` - * - * @param jwk JSON Web Key. - * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is - * "sha256". - * @see [RFC7638](https://www.rfc-editor.org/rfc/rfc7638) - */ -export async function calculateJwkThumbprint( - jwk: JWK, - digestAlgorithm?: 'sha256' | 'sha384' | 'sha512', -): Promise { - if (!isObject(jwk)) { - throw new TypeError('JWK must be an object') - } - - digestAlgorithm ??= 'sha256' - - if ( - digestAlgorithm !== 'sha256' && - digestAlgorithm !== 'sha384' && - digestAlgorithm !== 'sha512' - ) { - throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"') - } - - let components: JWK - switch (jwk.kty) { - case 'EC': - check(jwk.crv, '"crv" (Curve) Parameter') - check(jwk.x, '"x" (X Coordinate) Parameter') - check(jwk.y, '"y" (Y Coordinate) Parameter') - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y } - break - case 'OKP': - check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter') - check(jwk.x, '"x" (Public Key) Parameter') - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x } - break - case 'RSA': - check(jwk.e, '"e" (Exponent) Parameter') - check(jwk.n, '"n" (Modulus) Parameter') - components = { e: jwk.e, kty: jwk.kty, n: jwk.n } - break - case 'oct': - check(jwk.k, '"k" (Key Value) Parameter') - components = { k: jwk.k, kty: jwk.kty } - break - default: - throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported') - } - - const data = encoder.encode(JSON.stringify(components)) - return base64url(await digest(digestAlgorithm, data)) -} - -/** - * Calculates a JSON Web Key (JWK) Thumbprint URI - * - * @example Usage - * - * ```js - * const thumbprintUri = await jose.calculateJwkThumbprintUri({ - * kty: 'EC', - * crv: 'P-256', - * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', - * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', - * }) - * - * console.log(thumbprint) - * // 'urn:ietf:params:oauth:jwk-thumbprint:sha-256:w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' - * ``` - * - * @param jwk JSON Web Key. - * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is - * "sha256". - * @see [RFC9278](https://www.rfc-editor.org/rfc/rfc9278) - */ -export async function calculateJwkThumbprintUri( - jwk: JWK, - digestAlgorithm?: 'sha256' | 'sha384' | 'sha512', -): Promise { - digestAlgorithm ??= 'sha256' - const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm) - return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}` -} diff --git a/dist/deno/jwks/local.ts b/dist/deno/jwks/local.ts deleted file mode 100644 index b9693be1bf..0000000000 --- a/dist/deno/jwks/local.ts +++ /dev/null @@ -1,245 +0,0 @@ -import type { - KeyLike, - JWSHeaderParameters, - JWK, - JSONWebKeySet, - FlattenedJWSInput, -} from '../types.d.ts' -import { importJWK } from '../key/import.ts' -import { - JWKSInvalid, - JOSENotSupported, - JWKSNoMatchingKey, - JWKSMultipleMatchingKeys, -} from '../util/errors.ts' -import isObject from '../lib/is_object.ts' - -function getKtyFromAlg(alg: unknown) { - switch (typeof alg === 'string' && alg.slice(0, 2)) { - case 'RS': - case 'PS': - return 'RSA' - case 'ES': - return 'EC' - case 'Ed': - return 'OKP' - default: - throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set') - } -} - -interface Cache { - [alg: string]: KeyLike -} - -/** @private */ -export function isJWKSLike(jwks: unknown): jwks is JSONWebKeySet { - return ( - jwks && - typeof jwks === 'object' && - // @ts-expect-error - Array.isArray(jwks.keys) && - // @ts-expect-error - jwks.keys.every(isJWKLike) - ) -} - -function isJWKLike(key: unknown) { - return isObject(key) -} - -function clone(obj: T): T { - // @ts-ignore - if (typeof structuredClone === 'function') { - // @ts-ignore - return structuredClone(obj) - } - - return JSON.parse(JSON.stringify(obj)) -} - -/** @private */ -export class LocalJWKSet { - protected _jwks?: JSONWebKeySet - - private _cached: WeakMap = new WeakMap() - - constructor(jwks: unknown) { - if (!isJWKSLike(jwks)) { - throw new JWKSInvalid('JSON Web Key Set malformed') - } - - this._jwks = clone(jwks) - } - - async getKey(protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise { - const { alg, kid } = { ...protectedHeader, ...token?.header } - const kty = getKtyFromAlg(alg) - - const candidates = this._jwks!.keys.filter((jwk) => { - // filter keys based on the mapping of signature algorithms to Key Type - let candidate = kty === jwk.kty - - // filter keys based on the JWK Key ID in the header - if (candidate && typeof kid === 'string') { - candidate = kid === jwk.kid - } - - // filter keys based on the key's declared Algorithm - if (candidate && typeof jwk.alg === 'string') { - candidate = alg === jwk.alg - } - - // filter keys based on the key's declared Public Key Use - if (candidate && typeof jwk.use === 'string') { - candidate = jwk.use === 'sig' - } - - // filter keys based on the key's declared Key Operations - if (candidate && Array.isArray(jwk.key_ops)) { - candidate = jwk.key_ops.includes('verify') - } - - // filter out non-applicable OKP Sub Types - if (candidate && alg === 'EdDSA') { - candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448' - } - - // filter out non-applicable EC curves - if (candidate) { - switch (alg) { - case 'ES256': - candidate = jwk.crv === 'P-256' - break - case 'ES256K': - candidate = jwk.crv === 'secp256k1' - break - case 'ES384': - candidate = jwk.crv === 'P-384' - break - case 'ES512': - candidate = jwk.crv === 'P-521' - break - } - } - - return candidate - }) - - const { 0: jwk, length } = candidates - - if (length === 0) { - throw new JWKSNoMatchingKey() - } else if (length !== 1) { - const error = new JWKSMultipleMatchingKeys() - - const { _cached } = this - error[Symbol.asyncIterator] = async function* () { - for (const jwk of candidates) { - try { - yield await importWithAlgCache(_cached, jwk, alg!) - } catch { - continue - } - } - } - - throw error - } - - return importWithAlgCache(this._cached, jwk, alg!) - } -} - -async function importWithAlgCache(cache: WeakMap, jwk: JWK, alg: string) { - const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk)! - if (cached[alg] === undefined) { - const keyObject = await importJWK({ ...jwk, ext: true }, alg) - - if (keyObject.type !== 'public') { - throw new JWKSInvalid('JSON Web Key Set members must be public keys') - } - - cached[alg] = keyObject - } - - return cached[alg] -} - -/** - * Returns a function that resolves to a key object from a locally stored, or otherwise available, - * JSON Web Key Set. - * - * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), - * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if - * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key - * Operations) Parameters (if they are present on the JWK). - * - * Only a single public key must match the selection process. As shown in the example below when - * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt - * verification in an iterative manner. - * - * @example Usage - * - * ```js - * const JWKS = jose.createLocalJWKSet({ - * keys: [ - * { - * kty: 'RSA', - * e: 'AQAB', - * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', - * alg: 'PS256', - * }, - * { - * crv: 'P-256', - * kty: 'EC', - * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', - * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', - * alg: 'ES256', - * }, - * ], - * }) - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Opting-in to multiple JWKS matches using `createLocalJWKSet` - * - * ```js - * const options = { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * } - * const { payload, protectedHeader } = await jose - * .jwtVerify(jwt, JWKS, options) - * .catch(async (error) => { - * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { - * for await (const publicKey of error) { - * try { - * return await jose.jwtVerify(jwt, publicKey, options) - * } catch (innerError) { - * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { - * continue - * } - * throw innerError - * } - * } - * throw new jose.errors.JWSSignatureVerificationFailed() - * } - * - * throw error - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwks JSON Web Key Set formatted object. - */ -export function createLocalJWKSet(jwks: JSONWebKeySet) { - return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)) -} diff --git a/dist/deno/jwks/remote.ts b/dist/deno/jwks/remote.ts deleted file mode 100644 index 1a67595572..0000000000 --- a/dist/deno/jwks/remote.ts +++ /dev/null @@ -1,204 +0,0 @@ -import fetchJwks from '../runtime/fetch_jwks.ts' -import { isCloudflareWorkers } from '../runtime/env.ts' - -import type { KeyLike, JWSHeaderParameters, FlattenedJWSInput } from '../types.d.ts' -import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.ts' - -import { isJWKSLike, LocalJWKSet } from './local.ts' - -/** Options for the remote JSON Web Key Set. */ -export interface RemoteJWKSetOptions { - /** - * Timeout (in milliseconds) for the HTTP request. When reached the request will be aborted and - * the verification will fail. Default is 5000 (5 seconds). - */ - timeoutDuration?: number - - /** - * Duration (in milliseconds) for which no more HTTP requests will be triggered after a previous - * successful fetch. Default is 30000 (30 seconds). - */ - cooldownDuration?: number - - /** - * Maximum time (in milliseconds) between successful HTTP requests. Default is 600000 (10 - * minutes). - */ - cacheMaxAge?: number | typeof Infinity - - /** - * An instance of [http.Agent](https://nodejs.org/api/http.html#class-httpagent) or - * [https.Agent](https://nodejs.org/api/https.html#class-httpsagent) to pass to the - * [http.get](https://nodejs.org/api/http.html#httpgetoptions-callback) or - * [https.get](https://nodejs.org/api/https.html#httpsgetoptions-callback) method's options. Use - * when behind an http(s) proxy. This is a Node.js runtime specific option, it is ignored when - * used outside of Node.js runtime. - */ - agent?: any - - /** Optional headers to be sent with the HTTP request. */ - headers?: Record -} - -class RemoteJWKSet extends LocalJWKSet { - private _url: URL - - private _timeoutDuration: number - - private _cooldownDuration: number - - private _cacheMaxAge: number - - private _jwksTimestamp?: number - - private _pendingFetch?: Promise - - private _options: Pick - - constructor(url: unknown, options?: RemoteJWKSetOptions) { - super({ keys: [] }) - - this._jwks = undefined - - if (!(url instanceof URL)) { - throw new TypeError('url must be an instance of URL') - } - this._url = new URL(url.href) - this._options = { agent: options?.agent, headers: options?.headers } - this._timeoutDuration = - typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000 - this._cooldownDuration = - typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000 - this._cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000 - } - - coolingDown() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cooldownDuration - : false - } - - fresh() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cacheMaxAge - : false - } - - async getKey(protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise { - if (!this._jwks || !this.fresh()) { - await this.reload() - } - - try { - return await super.getKey(protectedHeader, token) - } catch (err) { - if (err instanceof JWKSNoMatchingKey) { - if (this.coolingDown() === false) { - await this.reload() - return super.getKey(protectedHeader, token) - } - } - throw err - } - } - - async reload() { - // see https://github.com/panva/jose/issues/355 - if (this._pendingFetch && isCloudflareWorkers()) { - return new Promise((resolve) => { - const isDone = () => { - if (this._pendingFetch === undefined) { - resolve() - } else { - setTimeout(isDone, 5) - } - } - isDone() - }) - } - - if (!this._pendingFetch) { - this._pendingFetch = fetchJwks(this._url, this._timeoutDuration, this._options) - .then((json) => { - if (!isJWKSLike(json)) { - throw new JWKSInvalid('JSON Web Key Set malformed') - } - - this._jwks = { keys: json.keys } - this._jwksTimestamp = Date.now() - this._pendingFetch = undefined - }) - .catch((err: Error) => { - this._pendingFetch = undefined - throw err - }) - } - - await this._pendingFetch - } -} - -/** - * Returns a function that resolves to a key object downloaded from a remote endpoint returning a - * JSON Web Key Set, that is, for example, an OAuth 2.0 or OIDC jwks_uri. The JSON Web Key Set is - * fetched when no key matches the selection process but only as frequently as the - * `cooldownDuration` option allows to prevent abuse. - * - * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), - * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if - * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key - * Operations) Parameters (if they are present on the JWK). - * - * Only a single public key must match the selection process. As shown in the example below when - * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt - * verification in an iterative manner. - * - * @example Usage - * - * ```js - * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Opting-in to multiple JWKS matches using `createRemoteJWKSet` - * - * ```js - * const options = { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * } - * const { payload, protectedHeader } = await jose - * .jwtVerify(jwt, JWKS, options) - * .catch(async (error) => { - * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { - * for await (const publicKey of error) { - * try { - * return await jose.jwtVerify(jwt, publicKey, options) - * } catch (innerError) { - * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { - * continue - * } - * throw innerError - * } - * } - * throw new jose.errors.JWSSignatureVerificationFailed() - * } - * - * throw error - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param url URL to fetch the JSON Web Key Set from. - * @param options Options for the remote JSON Web Key Set. - */ -export function createRemoteJWKSet(url: URL, options?: RemoteJWKSetOptions) { - return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)) -} diff --git a/dist/deno/jws/compact/sign.ts b/dist/deno/jws/compact/sign.ts deleted file mode 100644 index 339858f58b..0000000000 --- a/dist/deno/jws/compact/sign.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { FlattenedSign } from '../flattened/sign.ts' -import type { CompactJWSHeaderParameters, KeyLike, SignOptions } from '../../types.d.ts' - -/** - * The CompactSign class is a utility for creating Compact JWS strings. - * - * @example Usage - * - * ```js - * const jws = await new jose.CompactSign( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'ES256' }) - * .sign(privateKey) - * - * console.log(jws) - * ``` - */ -export class CompactSign { - private _flattened: FlattenedSign - - /** @param payload Binary representation of the payload to sign. */ - constructor(payload: Uint8Array) { - this._flattened = new FlattenedSign(payload) - } - - /** - * Sets the JWS Protected Header on the Sign object. - * - * @param protectedHeader JWS Protected Header. - */ - setProtectedHeader(protectedHeader: CompactJWSHeaderParameters) { - this._flattened.setProtectedHeader(protectedHeader) - return this - } - - /** - * Signs and resolves the value of the Compact JWS string. - * - * @param key Private Key or Secret to sign the JWS with. - * @param options JWS Sign options. - */ - async sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise { - const jws = await this._flattened.sign(key, options) - - if (jws.payload === undefined) { - throw new TypeError('use the flattened module for creating JWS with b64: false') - } - - return `${jws.protected}.${jws.payload}.${jws.signature}` - } -} diff --git a/dist/deno/jws/compact/verify.ts b/dist/deno/jws/compact/verify.ts deleted file mode 100644 index 026de73ff0..0000000000 --- a/dist/deno/jws/compact/verify.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { flattenedVerify } from '../flattened/verify.ts' -import { JWSInvalid } from '../../util/errors.ts' -import { decoder } from '../../lib/buffer_utils.ts' -import type { - CompactVerifyResult, - FlattenedJWSInput, - GetKeyFunction, - CompactJWSHeaderParameters, - KeyLike, - VerifyOptions, - ResolvedKey, -} from '../../types.d.ts' - -/** - * Interface for Compact JWS Verification dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface CompactVerifyGetKey - extends GetKeyFunction {} - -/** - * Verifies the signature and format of and afterwards decodes the Compact JWS. - * - * @example Usage - * - * ```js - * const jws = - * 'eyJhbGciOiJFUzI1NiJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4.kkAs_gPPxWMI3rHuVlxHaTPfDWDoqdI8jSvuSmqV-8IHIWXg9mcAeC9ggV-45ZHRbiRJ3obUIFo1rHphPA5URg' - * - * const { payload, protectedHeader } = await jose.compactVerify(jws, publicKey) - * - * console.log(protectedHeader) - * console.log(new TextDecoder().decode(payload)) - * ``` - * - * @param jws Compact JWS. - * @param key Key to verify the JWS with. - * @param options JWS Verify options. - */ -export function compactVerify( - jws: string | Uint8Array, - key: KeyLike | Uint8Array, - options?: VerifyOptions, -): Promise -/** - * @param jws Compact JWS. - * @param getKey Function resolving a key to verify the JWS with. - * @param options JWS Verify options. - */ -export function compactVerify( - jws: string | Uint8Array, - getKey: CompactVerifyGetKey, - options?: VerifyOptions, -): Promise -export async function compactVerify( - jws: string | Uint8Array, - key: KeyLike | Uint8Array | CompactVerifyGetKey, - options?: VerifyOptions, -) { - if (jws instanceof Uint8Array) { - jws = decoder.decode(jws) - } - - if (typeof jws !== 'string') { - throw new JWSInvalid('Compact JWS must be a string or Uint8Array') - } - const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.') - - if (length !== 3) { - throw new JWSInvalid('Invalid Compact JWS') - } - - const verified = await flattenedVerify( - { payload, protected: protectedHeader, signature }, - [1]>key, - options, - ) - - const result = { payload: verified.payload, protectedHeader: verified.protectedHeader! } - - if (typeof key === 'function') { - return { ...result, key: verified.key } - } - - return result -} diff --git a/dist/deno/jws/flattened/sign.ts b/dist/deno/jws/flattened/sign.ts deleted file mode 100644 index 57f2353ce7..0000000000 --- a/dist/deno/jws/flattened/sign.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { encode as base64url } from '../../runtime/base64url.ts' -import sign from '../../runtime/sign.ts' - -import isDisjoint from '../../lib/is_disjoint.ts' -import { JWSInvalid } from '../../util/errors.ts' -import { encoder, decoder, concat } from '../../lib/buffer_utils.ts' -import type { KeyLike, FlattenedJWS, JWSHeaderParameters, SignOptions } from '../../types.d.ts' -import checkKeyType from '../../lib/check_key_type.ts' -import validateCrit from '../../lib/validate_crit.ts' - -/** - * The FlattenedSign class is a utility for creating Flattened JWS objects. - * - * @example Usage - * - * ```js - * const jws = await new jose.FlattenedSign( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'ES256' }) - * .sign(privateKey) - * - * console.log(jws) - * ``` - */ -export class FlattenedSign { - private _payload: Uint8Array - - private _protectedHeader!: JWSHeaderParameters - - private _unprotectedHeader!: JWSHeaderParameters - - /** @param payload Binary representation of the payload to sign. */ - constructor(payload: Uint8Array) { - if (!(payload instanceof Uint8Array)) { - throw new TypeError('payload must be an instance of Uint8Array') - } - this._payload = payload - } - - /** - * Sets the JWS Protected Header on the FlattenedSign object. - * - * @param protectedHeader JWS Protected Header. - */ - setProtectedHeader(protectedHeader: JWSHeaderParameters) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once') - } - this._protectedHeader = protectedHeader - return this - } - - /** - * Sets the JWS Unprotected Header on the FlattenedSign object. - * - * @param unprotectedHeader JWS Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once') - } - this._unprotectedHeader = unprotectedHeader - return this - } - - /** - * Signs and resolves the value of the Flattened JWS object. - * - * @param key Private Key or Secret to sign the JWS with. - * @param options JWS Sign options. - */ - async sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise { - if (!this._protectedHeader && !this._unprotectedHeader) { - throw new JWSInvalid( - 'either setProtectedHeader or setUnprotectedHeader must be called before #sign()', - ) - } - - if (!isDisjoint(this._protectedHeader, this._unprotectedHeader)) { - throw new JWSInvalid( - 'JWS Protected and JWS Unprotected Header Parameter names must be disjoint', - ) - } - - const joseHeader: JWSHeaderParameters = { - ...this._protectedHeader, - ...this._unprotectedHeader, - } - - const extensions = validateCrit( - JWSInvalid, - new Map([['b64', true]]), - options?.crit, - this._protectedHeader, - joseHeader, - ) - - let b64: boolean = true - if (extensions.has('b64')) { - b64 = this._protectedHeader.b64! - if (typeof b64 !== 'boolean') { - throw new JWSInvalid( - 'The "b64" (base64url-encode payload) Header Parameter must be a boolean', - ) - } - } - - const { alg } = joseHeader - - if (typeof alg !== 'string' || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid') - } - - checkKeyType(alg, key, 'sign') - - let payload = this._payload - if (b64) { - payload = encoder.encode(base64url(payload)) - } - - let protectedHeader: Uint8Array - if (this._protectedHeader) { - protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))) - } else { - protectedHeader = encoder.encode('') - } - - const data = concat(protectedHeader, encoder.encode('.'), payload) - - const signature = await sign(alg, key, data) - - const jws: FlattenedJWS = { - signature: base64url(signature), - payload: '', - } - - if (b64) { - jws.payload = decoder.decode(payload) - } - - if (this._unprotectedHeader) { - jws.header = this._unprotectedHeader - } - - if (this._protectedHeader) { - jws.protected = decoder.decode(protectedHeader) - } - - return jws - } -} diff --git a/dist/deno/jws/flattened/verify.ts b/dist/deno/jws/flattened/verify.ts deleted file mode 100644 index 6f9f5eda68..0000000000 --- a/dist/deno/jws/flattened/verify.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { decode as base64url } from '../../runtime/base64url.ts' -import verify from '../../runtime/verify.ts' - -import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.ts' -import { concat, encoder, decoder } from '../../lib/buffer_utils.ts' -import isDisjoint from '../../lib/is_disjoint.ts' -import isObject from '../../lib/is_object.ts' -import checkKeyType from '../../lib/check_key_type.ts' -import validateCrit from '../../lib/validate_crit.ts' -import validateAlgorithms from '../../lib/validate_algorithms.ts' - -import type { - FlattenedVerifyResult, - KeyLike, - FlattenedJWSInput, - JWSHeaderParameters, - VerifyOptions, - GetKeyFunction, - ResolvedKey, -} from '../../types.d.ts' - -/** - * Interface for Flattened JWS Verification dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface FlattenedVerifyGetKey - extends GetKeyFunction {} - -/** - * Verifies the signature and format of and afterwards decodes the Flattened JWS. - * - * @example Usage - * - * ```js - * const decoder = new TextDecoder() - * const jws = { - * signature: - * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', - * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', - * protected: 'eyJhbGciOiJFUzI1NiJ9', - * } - * - * const { payload, protectedHeader } = await jose.flattenedVerify(jws, publicKey) - * - * console.log(protectedHeader) - * console.log(decoder.decode(payload)) - * ``` - * - * @param jws Flattened JWS. - * @param key Key to verify the JWS with. - * @param options JWS Verify options. - */ -export function flattenedVerify( - jws: FlattenedJWSInput, - key: KeyLike | Uint8Array, - options?: VerifyOptions, -): Promise -/** - * @param jws Flattened JWS. - * @param getKey Function resolving a key to verify the JWS with. - * @param options JWS Verify options. - */ -export function flattenedVerify( - jws: FlattenedJWSInput, - getKey: FlattenedVerifyGetKey, - options?: VerifyOptions, -): Promise -export async function flattenedVerify( - jws: FlattenedJWSInput, - key: KeyLike | Uint8Array | FlattenedVerifyGetKey, - options?: VerifyOptions, -) { - if (!isObject(jws)) { - throw new JWSInvalid('Flattened JWS must be an object') - } - - if (jws.protected === undefined && jws.header === undefined) { - throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members') - } - - if (jws.protected !== undefined && typeof jws.protected !== 'string') { - throw new JWSInvalid('JWS Protected Header incorrect type') - } - - if (jws.payload === undefined) { - throw new JWSInvalid('JWS Payload missing') - } - - if (typeof jws.signature !== 'string') { - throw new JWSInvalid('JWS Signature missing or incorrect type') - } - - if (jws.header !== undefined && !isObject(jws.header)) { - throw new JWSInvalid('JWS Unprotected Header incorrect type') - } - - let parsedProt: JWSHeaderParameters = {} - if (jws.protected) { - try { - const protectedHeader = base64url(jws.protected) - parsedProt = JSON.parse(decoder.decode(protectedHeader)) - } catch { - throw new JWSInvalid('JWS Protected Header is invalid') - } - } - if (!isDisjoint(parsedProt, jws.header)) { - throw new JWSInvalid( - 'JWS Protected and JWS Unprotected Header Parameter names must be disjoint', - ) - } - - const joseHeader: JWSHeaderParameters = { - ...parsedProt, - ...jws.header, - } - - const extensions = validateCrit( - JWSInvalid, - new Map([['b64', true]]), - options?.crit, - parsedProt, - joseHeader, - ) - - let b64: boolean = true - if (extensions.has('b64')) { - b64 = parsedProt.b64! - if (typeof b64 !== 'boolean') { - throw new JWSInvalid( - 'The "b64" (base64url-encode payload) Header Parameter must be a boolean', - ) - } - } - - const { alg } = joseHeader - - if (typeof alg !== 'string' || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid') - } - - const algorithms = options && validateAlgorithms('algorithms', options.algorithms) - - if (algorithms && !algorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed') - } - - if (b64) { - if (typeof jws.payload !== 'string') { - throw new JWSInvalid('JWS Payload must be a string') - } - } else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { - throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance') - } - - let resolvedKey = false - if (typeof key === 'function') { - key = await key(parsedProt, jws) - resolvedKey = true - } - - checkKeyType(alg, key, 'verify') - - const data = concat( - encoder.encode(jws.protected ?? ''), - encoder.encode('.'), - typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload, - ) - const signature = base64url(jws.signature) - const verified = await verify(alg, key, signature, data) - - if (!verified) { - throw new JWSSignatureVerificationFailed() - } - - let payload: Uint8Array - if (b64) { - payload = base64url(jws.payload) - } else if (typeof jws.payload === 'string') { - payload = encoder.encode(jws.payload) - } else { - payload = jws.payload - } - - const result: FlattenedVerifyResult = { payload } - - if (jws.protected !== undefined) { - result.protectedHeader = parsedProt - } - - if (jws.header !== undefined) { - result.unprotectedHeader = jws.header - } - - if (resolvedKey) { - return { ...result, key } - } - - return result -} diff --git a/dist/deno/jws/general/sign.ts b/dist/deno/jws/general/sign.ts deleted file mode 100644 index 0b3886e804..0000000000 --- a/dist/deno/jws/general/sign.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { FlattenedSign } from '../flattened/sign.ts' -import { JWSInvalid } from '../../util/errors.ts' - -import type { KeyLike, GeneralJWS, JWSHeaderParameters, SignOptions } from '../../types.d.ts' - -export interface Signature { - /** - * Sets the JWS Protected Header on the Signature object. - * - * @param protectedHeader JWS Protected Header. - */ - setProtectedHeader(protectedHeader: JWSHeaderParameters): Signature - - /** - * Sets the JWS Unprotected Header on the Signature object. - * - * @param unprotectedHeader JWS Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters): Signature - - /** A shorthand for calling addSignature() on the enclosing GeneralSign instance */ - addSignature(...args: Parameters): Signature - - /** A shorthand for calling encrypt() on the enclosing GeneralSign instance */ - sign(...args: Parameters): Promise - - /** Returns the enclosing GeneralSign */ - done(): GeneralSign -} - -class IndividualSignature implements Signature { - private parent: GeneralSign - - protectedHeader?: JWSHeaderParameters - unprotectedHeader?: JWSHeaderParameters - options?: SignOptions - key: KeyLike | Uint8Array - - constructor(sig: GeneralSign, key: KeyLike | Uint8Array, options?: SignOptions) { - this.parent = sig - this.key = key - this.options = options - } - - setProtectedHeader(protectedHeader: JWSHeaderParameters) { - if (this.protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once') - } - this.protectedHeader = protectedHeader - return this - } - - setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once') - } - this.unprotectedHeader = unprotectedHeader - return this - } - - addSignature(...args: Parameters) { - return this.parent.addSignature(...args) - } - - sign(...args: Parameters) { - return this.parent.sign(...args) - } - - done() { - return this.parent - } -} - -/** - * The GeneralSign class is a utility for creating General JWS objects. - * - * @example Usage - * - * ```js - * const jws = await new jose.GeneralSign( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .addSignature(ecPrivateKey) - * .setProtectedHeader({ alg: 'ES256' }) - * .addSignature(rsaPrivateKey) - * .setProtectedHeader({ alg: 'PS256' }) - * .sign() - * - * console.log(jws) - * ``` - */ -export class GeneralSign { - private _payload: Uint8Array - - private _signatures: IndividualSignature[] = [] - - /** @param payload Binary representation of the payload to sign. */ - constructor(payload: Uint8Array) { - this._payload = payload - } - - /** - * Adds an additional signature for the General JWS object. - * - * @param key Private Key or Secret to sign the individual JWS signature with. - * @param options JWS Sign options. - */ - addSignature(key: KeyLike | Uint8Array, options?: SignOptions): Signature { - const signature = new IndividualSignature(this, key, options) - this._signatures.push(signature) - return signature - } - - /** Signs and resolves the value of the General JWS object. */ - async sign(): Promise { - if (!this._signatures.length) { - throw new JWSInvalid('at least one signature must be added') - } - - const jws: GeneralJWS = { - signatures: [], - payload: '', - } - - for (let i = 0; i < this._signatures.length; i++) { - const signature = this._signatures[i] - const flattened = new FlattenedSign(this._payload) - - flattened.setProtectedHeader(signature.protectedHeader!) - flattened.setUnprotectedHeader(signature.unprotectedHeader!) - - const { payload, ...rest } = await flattened.sign(signature.key, signature.options) - if (i === 0) { - jws.payload = payload - } else if (jws.payload !== payload) { - throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)') - } - jws.signatures.push(rest) - } - - return jws - } -} diff --git a/dist/deno/jws/general/verify.ts b/dist/deno/jws/general/verify.ts deleted file mode 100644 index fa31fc7c76..0000000000 --- a/dist/deno/jws/general/verify.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { flattenedVerify } from '../flattened/verify.ts' -import type { - GeneralJWSInput, - GeneralVerifyResult, - FlattenedJWSInput, - GetKeyFunction, - JWSHeaderParameters, - KeyLike, - VerifyOptions, - ResolvedKey, -} from '../../types.d.ts' -import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.ts' -import isObject from '../../lib/is_object.ts' - -/** - * Interface for General JWS Verification dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface GeneralVerifyGetKey - extends GetKeyFunction {} - -/** - * Verifies the signature and format of and afterwards decodes the General JWS. - * - * @example Usage - * - * ```js - * const jws = { - * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', - * signatures: [ - * { - * signature: - * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', - * protected: 'eyJhbGciOiJFUzI1NiJ9', - * }, - * ], - * } - * - * const { payload, protectedHeader } = await jose.generalVerify(jws, publicKey) - * - * console.log(protectedHeader) - * console.log(new TextDecoder().decode(payload)) - * ``` - * - * @param jws General JWS. - * @param key Key to verify the JWS with. - * @param options JWS Verify options. - */ -export function generalVerify( - jws: GeneralJWSInput, - key: KeyLike | Uint8Array, - options?: VerifyOptions, -): Promise -/** - * @param jws General JWS. - * @param getKey Function resolving a key to verify the JWS with. - * @param options JWS Verify options. - */ -export function generalVerify( - jws: GeneralJWSInput, - getKey: GeneralVerifyGetKey, - options?: VerifyOptions, -): Promise -export async function generalVerify( - jws: GeneralJWSInput, - key: KeyLike | Uint8Array | GeneralVerifyGetKey, - options?: VerifyOptions, -) { - if (!isObject(jws)) { - throw new JWSInvalid('General JWS must be an object') - } - - if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { - throw new JWSInvalid('JWS Signatures missing or incorrect type') - } - - for (const signature of jws.signatures) { - try { - return await flattenedVerify( - { - header: signature.header, - payload: jws.payload, - protected: signature.protected, - signature: signature.signature, - }, - [1]>key, - options, - ) - } catch { - // - } - } - throw new JWSSignatureVerificationFailed() -} diff --git a/dist/deno/jwt/decrypt.ts b/dist/deno/jwt/decrypt.ts deleted file mode 100644 index d8aa32a4df..0000000000 --- a/dist/deno/jwt/decrypt.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { compactDecrypt } from '../jwe/compact/decrypt.ts' -import type { - KeyLike, - DecryptOptions, - JWTClaimVerificationOptions, - GetKeyFunction, - CompactJWEHeaderParameters, - FlattenedJWE, - JWTDecryptResult, - ResolvedKey, -} from '../types.d.ts' -import jwtPayload from '../lib/jwt_claims_set.ts' -import { JWTClaimValidationFailed } from '../util/errors.ts' - -/** Combination of JWE Decryption options and JWT Claims Set verification options. */ -export interface JWTDecryptOptions extends DecryptOptions, JWTClaimVerificationOptions {} - -/** - * Interface for JWT Decryption dynamic key resolution. No token components have been verified at - * the time of this function call. - */ -export interface JWTDecryptGetKey - extends GetKeyFunction {} - -/** - * Verifies the JWT format (to be a JWE Compact format), decrypts the ciphertext, validates the JWT - * Claims Set. - * - * @example Usage - * - * ```js - * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') - * const jwt = - * 'eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..MB66qstZBPxAXKdsjet_lA.WHbtJTl4taHp7otOHLq3hBvv0yNPsPEKHYInmCPdDDeyV1kU-f-tGEiU4FxlSqkqAT2hVs8_wMNiQFAzPU1PUgIqWCPsBrPP3TtxYsrtwagpn4SvCsUsx0Mhw9ZhliAO8CLmCBQkqr_T9AcYsz5uZw.7nX9m7BGUu_u1p1qFHzyIg' - * - * const { payload, protectedHeader } = await jose.jwtDecrypt(jwt, secret, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwt JSON Web Token value (encoded as JWE). - * @param key Private Key or Secret to decrypt and verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export async function jwtDecrypt( - jwt: string | Uint8Array, - key: KeyLike | Uint8Array, - options?: JWTDecryptOptions, -): Promise -/** - * @param jwt JSON Web Token value (encoded as JWE). - * @param getKey Function resolving Private Key or Secret to decrypt and verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export async function jwtDecrypt( - jwt: string | Uint8Array, - getKey: JWTDecryptGetKey, - options?: JWTDecryptOptions, -): Promise -export async function jwtDecrypt( - jwt: string | Uint8Array, - key: KeyLike | Uint8Array | JWTDecryptGetKey, - options?: JWTDecryptOptions, -) { - const decrypted = await compactDecrypt(jwt, [1]>key, options) - const payload = jwtPayload(decrypted.protectedHeader, decrypted.plaintext, options) - - const { protectedHeader } = decrypted - - if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { - throw new JWTClaimValidationFailed( - 'replicated "iss" claim header parameter mismatch', - 'iss', - 'mismatch', - ) - } - - if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { - throw new JWTClaimValidationFailed( - 'replicated "sub" claim header parameter mismatch', - 'sub', - 'mismatch', - ) - } - - if ( - protectedHeader.aud !== undefined && - JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud) - ) { - throw new JWTClaimValidationFailed( - 'replicated "aud" claim header parameter mismatch', - 'aud', - 'mismatch', - ) - } - - const result = { payload, protectedHeader } - - if (typeof key === 'function') { - return { ...result, key: decrypted.key } - } - - return result -} diff --git a/dist/deno/jwt/encrypt.ts b/dist/deno/jwt/encrypt.ts deleted file mode 100644 index de3cc6df1e..0000000000 --- a/dist/deno/jwt/encrypt.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { CompactEncrypt } from '../jwe/compact/encrypt.ts' -import type { - EncryptOptions, - CompactJWEHeaderParameters, - JWEKeyManagementHeaderParameters, - KeyLike, -} from '../types.d.ts' -import { encoder } from '../lib/buffer_utils.ts' -import { ProduceJWT } from './produce.ts' - -/** - * The EncryptJWT class is a utility for creating Compact JWE formatted JWT strings. - * - * @example Usage - * - * ```js - * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') - * const jwt = await new jose.EncryptJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg: 'dir', enc: 'A128CBC-HS256' }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .encrypt(secret) - * - * console.log(jwt) - * ``` - */ -export class EncryptJWT extends ProduceJWT { - private _cek!: Uint8Array - - private _iv!: Uint8Array - - private _keyManagementParameters!: JWEKeyManagementHeaderParameters - - private _protectedHeader!: CompactJWEHeaderParameters - - private _replicateIssuerAsHeader!: boolean - - private _replicateSubjectAsHeader!: boolean - - private _replicateAudienceAsHeader!: boolean - - /** - * Sets the JWE Protected Header on the EncryptJWT object. - * - * @param protectedHeader JWE Protected Header. Must contain an "alg" (JWE Algorithm) and "enc" - * (JWE Encryption Algorithm) properties. - */ - setProtectedHeader(protectedHeader: CompactJWEHeaderParameters) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once') - } - this._protectedHeader = protectedHeader - return this - } - - /** - * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is - * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or - * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed - * and missing. - * - * @param parameters JWE Key Management parameters. - */ - setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once') - } - this._keyManagementParameters = parameters - return this - } - - /** - * Sets a content encryption key to use, by default a random suitable one is generated for the JWE - * enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param cek JWE Content Encryption Key. - */ - setContentEncryptionKey(cek: Uint8Array) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once') - } - this._cek = cek - return this - } - - /** - * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable - * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param iv JWE Initialization Vector. - */ - setInitializationVector(iv: Uint8Array) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once') - } - this._iv = iv - return this - } - - /** - * Replicates the "iss" (Issuer) Claim as a JWE Protected Header Parameter as per - * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). - */ - replicateIssuerAsHeader() { - this._replicateIssuerAsHeader = true - return this - } - - /** - * Replicates the "sub" (Subject) Claim as a JWE Protected Header Parameter as per - * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). - */ - replicateSubjectAsHeader() { - this._replicateSubjectAsHeader = true - return this - } - - /** - * Replicates the "aud" (Audience) Claim as a JWE Protected Header Parameter as per - * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). - */ - replicateAudienceAsHeader() { - this._replicateAudienceAsHeader = true - return this - } - - /** - * Encrypts and returns the JWT. - * - * @param key Public Key or Secret to encrypt the JWT with. - * @param options JWE Encryption options. - */ - async encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise { - const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))) - if (this._replicateIssuerAsHeader) { - this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss } - } - if (this._replicateSubjectAsHeader) { - this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub } - } - if (this._replicateAudienceAsHeader) { - this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud } - } - enc.setProtectedHeader(this._protectedHeader) - if (this._iv) { - enc.setInitializationVector(this._iv) - } - if (this._cek) { - enc.setContentEncryptionKey(this._cek) - } - if (this._keyManagementParameters) { - enc.setKeyManagementParameters(this._keyManagementParameters) - } - return enc.encrypt(key, options) - } -} diff --git a/dist/deno/jwt/produce.ts b/dist/deno/jwt/produce.ts deleted file mode 100644 index 5fd7defddf..0000000000 --- a/dist/deno/jwt/produce.ts +++ /dev/null @@ -1,104 +0,0 @@ -import type { JWTPayload } from '../types.d.ts' -import epoch from '../lib/epoch.ts' -import isObject from '../lib/is_object.ts' -import secs from '../lib/secs.ts' - -/** Generic class for JWT producing. */ -export class ProduceJWT { - protected _payload!: JWTPayload - - /** @param payload The JWT Claims Set object. */ - constructor(payload: JWTPayload) { - if (!isObject(payload)) { - throw new TypeError('JWT Claims Set MUST be an object') - } - this._payload = payload - } - - /** - * Set "iss" (Issuer) Claim. - * - * @param issuer "Issuer" Claim value to set on the JWT Claims Set. - */ - setIssuer(issuer: string) { - this._payload = { ...this._payload, iss: issuer } - return this - } - - /** - * Set "sub" (Subject) Claim. - * - * @param subject "sub" (Subject) Claim value to set on the JWT Claims Set. - */ - setSubject(subject: string) { - this._payload = { ...this._payload, sub: subject } - return this - } - - /** - * Set "aud" (Audience) Claim. - * - * @param audience "aud" (Audience) Claim value to set on the JWT Claims Set. - */ - setAudience(audience: string | string[]) { - this._payload = { ...this._payload, aud: audience } - return this - } - - /** - * Set "jti" (JWT ID) Claim. - * - * @param jwtId "jti" (JWT ID) Claim value to set on the JWT Claims Set. - */ - setJti(jwtId: string) { - this._payload = { ...this._payload, jti: jwtId } - return this - } - - /** - * Set "nbf" (Not Before) Claim. - * - * @param input "nbf" (Not Before) Claim value to set on the JWT Claims Set. When number is passed - * that is used as a value, when string is passed it is resolved to a time span and added to the - * current timestamp. - */ - setNotBefore(input: number | string) { - if (typeof input === 'number') { - this._payload = { ...this._payload, nbf: input } - } else { - this._payload = { ...this._payload, nbf: epoch(new Date()) + secs(input) } - } - return this - } - - /** - * Set "exp" (Expiration Time) Claim. - * - * @param input "exp" (Expiration Time) Claim value to set on the JWT Claims Set. When number is - * passed that is used as a value, when string is passed it is resolved to a time span and added - * to the current timestamp. - */ - setExpirationTime(input: number | string) { - if (typeof input === 'number') { - this._payload = { ...this._payload, exp: input } - } else { - this._payload = { ...this._payload, exp: epoch(new Date()) + secs(input) } - } - return this - } - - /** - * Set "iat" (Issued At) Claim. - * - * @param input "iat" (Issued At) Claim value to set on the JWT Claims Set. Default is current - * timestamp. - */ - setIssuedAt(input?: number) { - if (typeof input === 'undefined') { - this._payload = { ...this._payload, iat: epoch(new Date()) } - } else { - this._payload = { ...this._payload, iat: input } - } - return this - } -} diff --git a/dist/deno/jwt/sign.ts b/dist/deno/jwt/sign.ts deleted file mode 100644 index d7f9761a19..0000000000 --- a/dist/deno/jwt/sign.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { CompactSign } from '../jws/compact/sign.ts' -import { JWTInvalid } from '../util/errors.ts' -import type { JWTHeaderParameters, KeyLike, SignOptions } from '../types.d.ts' -import { encoder } from '../lib/buffer_utils.ts' -import { ProduceJWT } from './produce.ts' - -/** - * The SignJWT class is a utility for creating Compact JWS formatted JWT strings. - * - * @example Usage with a symmetric secret - * - * ```js - * const secret = new TextEncoder().encode( - * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', - * ) - * const alg = 'HS256' - * - * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .sign(secret) - * - * console.log(jwt) - * ``` - * - * @example Usage with a private PKCS#8 encoded RSA key - * - * ```js - * const alg = 'RS256' - * const pkcs8 = `-----BEGIN PRIVATE KEY----- - * MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCFg4UrY5xtulv - * /NXKmL1J4qI1SopAfTNMo3X7p+kJO7plqUYjzaztcre1qfh0m33Sm1Q8oPbO/GpP - * MU1/HgcceytgJ/b4UwufVVMl9BrMDYG8moDBylbVupFQS3Ly1L9i/iFG9Z9A9xzY - * Zzf799A45bnvNXL6s2glzvjiRvfQ2NDF0anTcnZLcYtC7ugq1IMM+ihAcPfw8Qw2 - * chN/SmP4qAM+PKaQwagmU7doqmmyN9u38AfoYZ1GCFhEs5TBBT6H6h9YdHeVtiIq - * 1c+fl03biSIfLrV7dUBD39gBmXBcL/30Ya3D82mCEUC4zg/UkOfQOmkmV3Lc8YUL - * QZ8EJkBLAgMBAAECggEAVuVE/KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34ls - * VOPK0XDegZkhAybMZHjRhp+gwVxX5ChC+J3cUpOBH5FNxElgW6HizD2Jcq6t6LoL - * YgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG/qJV1K00/Ly1G1QKoBffEs - * +v4fAMJrCbUdCz1qWto+PU+HLMEo+krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq/ - * aAP4a1SXmo+j0cvRU4W5Fj0RVwNesIpetX2ZFz4p/JmB5sWFEj/fC7h5z2lq+6Bm - * e2T3BHtXkIxoBW0/pYVnASC8P2puO5FnVxDmWuHDYQKBgQDTuuBd3+0tSFVEX+DU - * 5qpFmHm5nyGItZRJTS+71yg5pBxq1KqNCUjAtbxR0q//fwauakh+BwRVCPOrqsUG - * jBSb3NYE70Srp6elqxgkE54PwQx4Mr6exJPnseM9U4K+hULllf5yjM9edreJE1nV - * NVgFjeyafQhrHKwgr7PERJ/ikwKBgQDqqsT1M+EJLmI1HtCspOG6cu7q3gf/wKRh - * E8tu84i3YyBnI8uJkKy92RNVI5fvpBARe3tjSdM25rr2rcrcmF/5g6Q9ImxZPGCt - * 86eOgO9ErNtbc4TEgybsP319UE4O41aKeNiBTAZKoYCxv/dMqG0j4avmWzd+foHq - * gSNUvR2maQKBgQCYeqOsV2B6VPY7KIVFLd0AA9/dwvEmgAYLiA/RShDI+hwQ/5jX - * uxDu37KAhqeC65sHLrmIMUt4Zdr+DRyZK3aIDNEAesPMjw/X6lCXYp1ZISD2yyym - * MFGH8X8CIkstI9Faf9vf6PJKSFrC1/HA7wq17VCwrUzLvrljTMW8meM/CwKBgCpo - * 2leGHLFQFKeM/iF1WuYbR1pi7gcmhY6VyTowARFDdOOu8GXYI5/bz0afvCGvAMho - * DJCREv7lC/zww6zCTPYG+HOj+PjXlJFba3ixjIxYwPvyEJiDK1Ge18sB7Fl8dHNq - * C5ayaqCqN1voWYUdGzxU2IA1E/5kVo5O8FesJeOhAoGBAImJbZFf+D5kA32Xxhac - * 59lLWBCsocvvbd1cvDMNlRywAAyhsCb1SuX4nEAK9mrSBdfmoF2Nm3eilfsOds0f - * K5mX069IKG82CMqh3Mzptd7e7lyb9lsoGO0BAtjho3cWtha/UZ70vfaMzGuZ6JmQ - * ak6k+8+UFd93M4z0Qo74OhXB - * -----END PRIVATE KEY-----` - * const privateKey = await jose.importPKCS8(pkcs8, alg) - * - * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .sign(privateKey) - * - * console.log(jwt) - * ``` - * - * @example Usage with a private JWK encoded RSA key - * - * ```js - * const alg = 'RS256' - * const jwk = { - * kty: 'RSA', - * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', - * e: 'AQAB', - * d: 'VuVE_KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34lsVOPK0XDegZkhAybMZHjRhp-gwVxX5ChC-J3cUpOBH5FNxElgW6HizD2Jcq6t6LoLYgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG_qJV1K00_Ly1G1QKoBffEs-v4fAMJrCbUdCz1qWto-PU-HLMEo-krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq_aAP4a1SXmo-j0cvRU4W5Fj0RVwNesIpetX2ZFz4p_JmB5sWFEj_fC7h5z2lq-6Bme2T3BHtXkIxoBW0_pYVnASC8P2puO5FnVxDmWuHDYQ', - * p: '07rgXd_tLUhVRF_g1OaqRZh5uZ8hiLWUSU0vu9coOaQcatSqjQlIwLW8UdKv_38GrmpIfgcEVQjzq6rFBowUm9zWBO9Eq6enpasYJBOeD8EMeDK-nsST57HjPVOCvoVC5ZX-cozPXna3iRNZ1TVYBY3smn0IaxysIK-zxESf4pM', - * q: '6qrE9TPhCS5iNR7QrKThunLu6t4H_8CkYRPLbvOIt2MgZyPLiZCsvdkTVSOX76QQEXt7Y0nTNua69q3K3Jhf-YOkPSJsWTxgrfOnjoDvRKzbW3OExIMm7D99fVBODuNWinjYgUwGSqGAsb_3TKhtI-Gr5ls3fn6B6oEjVL0dpmk', - * dp: 'mHqjrFdgelT2OyiFRS3dAAPf3cLxJoAGC4gP0UoQyPocEP-Y17sQ7t-ygIanguubBy65iDFLeGXa_g0cmSt2iAzRAHrDzI8P1-pQl2KdWSEg9ssspjBRh_F_AiJLLSPRWn_b3-jySkhawtfxwO8Kte1QsK1My765Y0zFvJnjPws', - * dq: 'KmjaV4YcsVAUp4z-IXVa5htHWmLuByaFjpXJOjABEUN0467wZdgjn9vPRp-8Ia8AyGgMkJES_uUL_PDDrMJM9gb4c6P4-NeUkVtreLGMjFjA-_IQmIMrUZ7XywHsWXx0c2oLlrJqoKo3W-hZhR0bPFTYgDUT_mRWjk7wV6wl46E', - * qi: 'iYltkV_4PmQDfZfGFpzn2UtYEKyhy-9t3Vy8Mw2VHLAADKGwJvVK5ficQAr2atIF1-agXY2bd6KV-w52zR8rmZfTr0gobzYIyqHczOm13t7uXJv2WygY7QEC2OGjdxa2Fr9RnvS99ozMa5nomZBqTqT7z5QV33czjPRCjvg6FcE', - * } - * const privateKey = await jose.importJWK(jwk, alg) - * - * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .sign(privateKey) - * - * console.log(jwt) - * ``` - */ -export class SignJWT extends ProduceJWT { - private _protectedHeader!: JWTHeaderParameters - - /** - * Sets the JWS Protected Header on the SignJWT object. - * - * @param protectedHeader JWS Protected Header. Must contain an "alg" (JWS Algorithm) property. - */ - setProtectedHeader(protectedHeader: JWTHeaderParameters) { - this._protectedHeader = protectedHeader - return this - } - - /** - * Signs and returns the JWT. - * - * @param key Private Key or Secret to sign the JWT with. - * @param options JWT Sign options. - */ - async sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise { - const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))) - sig.setProtectedHeader(this._protectedHeader) - if ( - Array.isArray(this._protectedHeader?.crit) && - this._protectedHeader.crit.includes('b64') && - // @ts-expect-error - this._protectedHeader.b64 === false - ) { - throw new JWTInvalid('JWTs MUST NOT use unencoded payload') - } - return sig.sign(key, options) - } -} diff --git a/dist/deno/jwt/unsecured.ts b/dist/deno/jwt/unsecured.ts deleted file mode 100644 index 771ed2375e..0000000000 --- a/dist/deno/jwt/unsecured.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as base64url from '../runtime/base64url.ts' - -import type { JWSHeaderParameters, JWTClaimVerificationOptions, JWTPayload } from '../types.d.ts' -import { decoder } from '../lib/buffer_utils.ts' -import { JWTInvalid } from '../util/errors.ts' -import jwtPayload from '../lib/jwt_claims_set.ts' -import { ProduceJWT } from './produce.ts' - -export interface UnsecuredResult { - payload: JWTPayload - header: JWSHeaderParameters -} - -/** - * The UnsecuredJWT class is a utility for dealing with `{ "alg": "none" }` Unsecured JWTs. - * - * @example Encoding - * - * ```js - * const unsecuredJwt = new jose.UnsecuredJWT({ 'urn:example:claim': true }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .encode() - * - * console.log(unsecuredJwt) - * ``` - * - * @example Decoding - * - * ```js - * const payload = jose.UnsecuredJWT.decode(jwt, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(payload) - * ``` - */ -export class UnsecuredJWT extends ProduceJWT { - /** Encodes the Unsecured JWT. */ - encode(): string { - const header = base64url.encode(JSON.stringify({ alg: 'none' })) - const payload = base64url.encode(JSON.stringify(this._payload)) - - return `${header}.${payload}.` - } - - /** - * Decodes an unsecured JWT. - * - * @param jwt Unsecured JWT to decode the payload of. - * @param options JWT Claims Set validation options. - */ - static decode(jwt: string, options?: JWTClaimVerificationOptions): UnsecuredResult { - if (typeof jwt !== 'string') { - throw new JWTInvalid('Unsecured JWT must be a string') - } - const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.') - - if (length !== 3 || signature !== '') { - throw new JWTInvalid('Invalid Unsecured JWT') - } - - let header: JWSHeaderParameters - try { - header = JSON.parse(decoder.decode(base64url.decode(encodedHeader))) - if (header.alg !== 'none') throw new Error() - } catch { - throw new JWTInvalid('Invalid Unsecured JWT') - } - - const payload = jwtPayload(header, base64url.decode(encodedPayload), options) - - return { payload, header } - } -} diff --git a/dist/deno/jwt/verify.ts b/dist/deno/jwt/verify.ts deleted file mode 100644 index e546a0f0c4..0000000000 --- a/dist/deno/jwt/verify.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { compactVerify } from '../jws/compact/verify.ts' -import type { - KeyLike, - VerifyOptions, - JWTClaimVerificationOptions, - JWTHeaderParameters, - GetKeyFunction, - FlattenedJWSInput, - JWTVerifyResult, - ResolvedKey, -} from '../types.d.ts' -import jwtPayload from '../lib/jwt_claims_set.ts' -import { JWTInvalid } from '../util/errors.ts' - -/** Combination of JWS Verification options and JWT Claims Set verification options. */ -export interface JWTVerifyOptions extends VerifyOptions, JWTClaimVerificationOptions {} - -/** - * Interface for JWT Verification dynamic key resolution. No token components have been verified at - * the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface JWTVerifyGetKey extends GetKeyFunction {} - -/** - * Verifies the JWT format (to be a JWS Compact format), verifies the JWS signature, validates the - * JWT Claims Set. - * - * @example Usage with a symmetric secret - * - * ```js - * const secret = new TextEncoder().encode( - * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', - * ) - * const jwt = - * 'eyJhbGciOiJIUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2MjMxLCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.C4iSlLfAUMBq--wnC6VqD9gEOhwpRZpoRarE0m7KEnI' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, secret, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Usage with a public SPKI encoded RSA key - * - * ```js - * const alg = 'RS256' - * const spki = `-----BEGIN PUBLIC KEY----- - * MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwhYOFK2Ocbbpb/zVypi9 - * SeKiNUqKQH0zTKN1+6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4H - * HHsrYCf2+FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS/Yv4hRvWfQPcc2Gc3+/fQ - * OOW57zVy+rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj - * +KgDPjymkMGoJlO3aKppsjfbt/AH6GGdRghYRLOUwQU+h+ofWHR3lbYiKtXPn5dN - * 24kiHy61e3VAQ9/YAZlwXC/99GGtw/NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZA - * SwIDAQAB - * -----END PUBLIC KEY-----` - * const publicKey = await jose.importSPKI(spki, alg) - * const jwt = - * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Usage with a public JWK encoded RSA key - * - * ```js - * const alg = 'RS256' - * const jwk = { - * kty: 'RSA', - * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', - * e: 'AQAB', - * } - * const publicKey = await jose.importJWK(jwk, alg) - * const jwt = - * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwt JSON Web Token value (encoded as JWS). - * @param key Key to verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export async function jwtVerify( - jwt: string | Uint8Array, - key: KeyLike | Uint8Array, - options?: JWTVerifyOptions, -): Promise - -/** - * @example Usage with a public JSON Web Key Set hosted on a remote URL - * - * ```js - * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwt JSON Web Token value (encoded as JWS). - * @param getKey Function resolving a key to verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export async function jwtVerify( - jwt: string | Uint8Array, - getKey: JWTVerifyGetKey, - options?: JWTVerifyOptions, -): Promise - -export async function jwtVerify( - jwt: string | Uint8Array, - key: KeyLike | Uint8Array | JWTVerifyGetKey, - options?: JWTVerifyOptions, -) { - const verified = await compactVerify(jwt, [1]>key, options) - if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) { - throw new JWTInvalid('JWTs MUST NOT use unencoded payload') - } - const payload = jwtPayload(verified.protectedHeader, verified.payload, options) - const result = { payload, protectedHeader: verified.protectedHeader } - if (typeof key === 'function') { - return { ...result, key: verified.key } - } - return result -} diff --git a/dist/deno/key/export.ts b/dist/deno/key/export.ts deleted file mode 100644 index 2370835d0f..0000000000 --- a/dist/deno/key/export.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { toSPKI as exportPublic } from '../runtime/asn1.ts' -import { toPKCS8 as exportPrivate } from '../runtime/asn1.ts' -import keyToJWK from '../runtime/key_to_jwk.ts' - -import type { JWK, KeyLike } from '../types.d.ts' - -/** - * Exports a runtime-specific public key representation (KeyObject or CryptoKey) to a PEM-encoded - * SPKI string format. - * - * @example Usage - * - * ```js - * const spkiPem = await jose.exportSPKI(publicKey) - * - * console.log(spkiPem) - * ``` - * - * @param key Key representation to transform to a PEM-encoded SPKI string format. - */ -export async function exportSPKI(key: KeyLike): Promise { - return exportPublic(key) -} - -/** - * Exports a runtime-specific private key representation (KeyObject or CryptoKey) to a PEM-encoded - * PKCS8 string format. - * - * @example Usage - * - * ```js - * const pkcs8Pem = await jose.exportPKCS8(privateKey) - * - * console.log(pkcs8Pem) - * ``` - * - * @param key Key representation to transform to a PEM-encoded PKCS8 string format. - */ -export async function exportPKCS8(key: KeyLike): Promise { - return exportPrivate(key) -} - -/** - * Exports a runtime-specific key representation (KeyLike) to a JWK. - * - * @example Usage - * - * ```js - * const privateJwk = await jose.exportJWK(privateKey) - * const publicJwk = await jose.exportJWK(publicKey) - * - * console.log(privateJwk) - * console.log(publicJwk) - * ``` - * - * @param key Key representation to export as JWK. - */ -export async function exportJWK(key: KeyLike | Uint8Array): Promise { - return keyToJWK(key) -} diff --git a/dist/deno/key/generate_key_pair.ts b/dist/deno/key/generate_key_pair.ts deleted file mode 100644 index a2e699e769..0000000000 --- a/dist/deno/key/generate_key_pair.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { generateKeyPair as generate } from '../runtime/generate.ts' - -import type { KeyLike } from '../types.d.ts' - -export interface GenerateKeyPairResult { - /** The generated Private Key. */ - privateKey: KeyLike - - /** Public Key corresponding to the generated Private Key. */ - publicKey: KeyLike -} - -export interface GenerateKeyPairOptions { - /** - * The EC "crv" (Curve) or OKP "crv" (Subtype of Key Pair) value to generate. The curve must be - * both supported on the runtime as well as applicable for the given JWA algorithm identifier. - */ - crv?: string - - /** - * A hint for RSA algorithms to generate an RSA key of a given `modulusLength` (Key size in bits). - * JOSE requires 2048 bits or larger. Default is 2048. - */ - modulusLength?: number - - /** - * (Only effective in Web Crypto API runtimes) The value to use as - * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) - * `extractable` argument. Default is false. - */ - extractable?: boolean -} - -/** - * Generates a private and a public key for a given JWA algorithm identifier. This can only generate - * asymmetric key pairs. For symmetric secrets use the `generateSecret` function. - * - * Note: Under Web Crypto API runtime the `privateKey` is generated with `extractable` set to - * `false` by default. - * - * @example Usage - * - * ```js - * const { publicKey, privateKey } = await jose.generateKeyPair('PS256') - * console.log(publicKey) - * console.log(privateKey) - * ``` - * - * @param alg JWA Algorithm Identifier to be used with the generated key pair. - * @param options Additional options passed down to the key pair generation. - */ -export async function generateKeyPair( - alg: string, - options?: GenerateKeyPairOptions, -): Promise { - return generate(alg, options) -} diff --git a/dist/deno/key/generate_secret.ts b/dist/deno/key/generate_secret.ts deleted file mode 100644 index ee9de48106..0000000000 --- a/dist/deno/key/generate_secret.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { generateSecret as generate } from '../runtime/generate.ts' - -import type { KeyLike } from '../types.d.ts' - -export interface GenerateSecretOptions { - /** - * (Only effective in Web Crypto API runtimes) The value to use as - * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) - * `extractable` argument. Default is false. - */ - extractable?: boolean -} - -/** - * Generates a symmetric secret key for a given JWA algorithm identifier. - * - * Note: Under Web Crypto API runtime the secret key is generated with `extractable` set to `false` - * by default. - * - * @example Usage - * - * ```js - * const secret = await jose.generateSecret('HS256') - * console.log(secret) - * ``` - * - * @param alg JWA Algorithm Identifier to be used with the generated secret. - * @param options Additional options passed down to the secret generation. - */ -export async function generateSecret( - alg: string, - options?: GenerateSecretOptions, -): Promise { - return generate(alg, options) -} diff --git a/dist/deno/key/import.ts b/dist/deno/key/import.ts deleted file mode 100644 index 15415ff3e8..0000000000 --- a/dist/deno/key/import.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { decode as decodeBase64URL } from '../runtime/base64url.ts' -import { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.ts' -import asKeyObject from '../runtime/jwk_to_key.ts' - -import { JOSENotSupported } from '../util/errors.ts' -import isObject from '../lib/is_object.ts' -import type { JWK, KeyLike } from '../types.d.ts' - -export interface PEMImportOptions { - /** - * (Only effective in Web Crypto API runtimes) The value to use as - * [SubtleCrypto.importKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) - * `extractable` argument. Default is false. - */ - extractable?: boolean -} - -/** - * Imports a PEM-encoded SPKI string as a runtime-specific public key representation (KeyObject or - * CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to learn - * about key to algorithm requirements and mapping. - * - * @example Usage - * - * ```js - * const algorithm = 'ES256' - * const spki = `-----BEGIN PUBLIC KEY----- - * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM - * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== - * -----END PUBLIC KEY-----` - * const ecPublicKey = await jose.importSPKI(spki, algorithm) - * ``` - * - * @param pem PEM-encoded SPKI string - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key, its presence is only enforced in Web Crypto API runtimes. - */ -export async function importSPKI( - spki: string, - alg: string, - options?: PEMImportOptions, -): Promise { - if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { - throw new TypeError('"spki" must be SPKI formatted string') - } - return fromSPKI(spki, alg, options) -} - -/** - * Imports the SPKI from an X.509 string certificate as a runtime-specific public key representation - * (KeyObject or CryptoKey). See [Algorithm Key - * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm - * requirements and mapping. - * - * @example Usage - * - * ```js - * const algorithm = 'ES256' - * const x509 = `-----BEGIN CERTIFICATE----- - * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np - * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw - * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN - * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI - * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 - * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA - * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh - * v+A1QWZMuTWqYt+uh/YSRNDn - * -----END CERTIFICATE-----` - * const ecPublicKey = await jose.importX509(x509, algorithm) - * ``` - * - * @param pem X.509 certificate string - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key, its presence is only enforced in Web Crypto API runtimes. - */ -export async function importX509( - x509: string, - alg: string, - options?: PEMImportOptions, -): Promise { - if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { - throw new TypeError('"x509" must be X.509 formatted string') - } - return fromX509(x509, alg, options) -} - -/** - * Imports a PEM-encoded PKCS#8 string as a runtime-specific private key representation (KeyObject - * or CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to - * learn about key to algorithm requirements and mapping. Encrypted keys are not supported. - * - * @example Usage - * - * ```js - * const algorithm = 'ES256' - * const pkcs8 = `-----BEGIN PRIVATE KEY----- - * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN - * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg - * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa - * -----END PRIVATE KEY-----` - * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) - * ``` - * - * @param pem PEM-encoded PKCS#8 string - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key, its presence is only enforced in Web Crypto API runtimes. - */ -export async function importPKCS8( - pkcs8: string, - alg: string, - options?: PEMImportOptions, -): Promise { - if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { - throw new TypeError('"pkcs8" must be PKCS#8 formatted string') - } - return fromPKCS8(pkcs8, alg, options) -} - -/** - * Imports a JWK to a runtime-specific key representation (KeyLike). Either JWK "alg" (Algorithm) - * Parameter must be present or the optional "alg" argument. When running on a runtime using [Web - * Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) the jwk parameters "use", "key_ops", and - * "ext" are also used in the resulting `CryptoKey`. See [Algorithm Key - * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm - * requirements and mapping. - * - * @example Usage - * - * ```js - * const ecPublicKey = await jose.importJWK( - * { - * crv: 'P-256', - * kty: 'EC', - * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', - * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', - * }, - * 'ES256', - * ) - * - * const rsaPublicKey = await jose.importJWK( - * { - * kty: 'RSA', - * e: 'AQAB', - * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', - * }, - * 'PS256', - * ) - * ``` - * - * @param jwk JSON Web Key. - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key. Default is the "alg" property on the JWK, its presence is only enforced - * in Web Crypto API runtimes. - * @param octAsKeyObject Forces a symmetric key to be imported to a KeyObject or CryptoKey. Default - * is true unless JWK "ext" (Extractable) is true. - */ -export async function importJWK( - jwk: JWK, - alg?: string, - octAsKeyObject?: boolean, -): Promise { - if (!isObject(jwk)) { - throw new TypeError('JWK must be an object') - } - - alg ||= jwk.alg - - switch (jwk.kty) { - case 'oct': - if (typeof jwk.k !== 'string' || !jwk.k) { - throw new TypeError('missing "k" (Key Value) Parameter value') - } - - octAsKeyObject ??= jwk.ext !== true - - if (octAsKeyObject) { - return asKeyObject({ ...jwk, alg, ext: jwk.ext ?? false }) - } - - return decodeBase64URL(jwk.k) - case 'RSA': - if (jwk.oth !== undefined) { - throw new JOSENotSupported( - 'RSA JWK "oth" (Other Primes Info) Parameter value is not supported', - ) - } - case 'EC': - case 'OKP': - return asKeyObject({ ...jwk, alg }) - default: - throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value') - } -} diff --git a/dist/deno/lib/aesgcmkw.ts b/dist/deno/lib/aesgcmkw.ts deleted file mode 100644 index 87d7013728..0000000000 --- a/dist/deno/lib/aesgcmkw.ts +++ /dev/null @@ -1,30 +0,0 @@ -import encrypt from '../runtime/encrypt.ts' -import decrypt from '../runtime/decrypt.ts' -import generateIv from './iv.ts' -import { encode as base64url } from '../runtime/base64url.ts' - -export async function wrap(alg: string, key: unknown, cek: Uint8Array, iv?: Uint8Array) { - const jweAlgorithm = alg.slice(0, 7) - iv ||= generateIv(jweAlgorithm) - - const { ciphertext: encryptedKey, tag } = await encrypt( - jweAlgorithm, - cek, - key, - iv, - new Uint8Array(0), - ) - - return { encryptedKey, iv: base64url(iv), tag: base64url(tag) } -} - -export async function unwrap( - alg: string, - key: unknown, - encryptedKey: Uint8Array, - iv: Uint8Array, - tag: Uint8Array, -) { - const jweAlgorithm = alg.slice(0, 7) - return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)) -} diff --git a/dist/deno/lib/buffer_utils.ts b/dist/deno/lib/buffer_utils.ts deleted file mode 100644 index 2c910c61cb..0000000000 --- a/dist/deno/lib/buffer_utils.ts +++ /dev/null @@ -1,60 +0,0 @@ -import digest from '../runtime/digest.ts' - -export const encoder = new TextEncoder() -export const decoder = new TextDecoder() - -const MAX_INT32 = 2 ** 32 - -export function concat(...buffers: Uint8Array[]): Uint8Array { - const size = buffers.reduce((acc, { length }) => acc + length, 0) - const buf = new Uint8Array(size) - let i = 0 - buffers.forEach((buffer) => { - buf.set(buffer, i) - i += buffer.length - }) - return buf -} - -export function p2s(alg: string, p2sInput: Uint8Array) { - return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput) -} - -function writeUInt32BE(buf: Uint8Array, value: number, offset?: number) { - if (value < 0 || value >= MAX_INT32) { - throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`) - } - buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset) -} - -export function uint64be(value: number) { - const high = Math.floor(value / MAX_INT32) - const low = value % MAX_INT32 - const buf = new Uint8Array(8) - writeUInt32BE(buf, high, 0) - writeUInt32BE(buf, low, 4) - return buf -} - -export function uint32be(value: number) { - const buf = new Uint8Array(4) - writeUInt32BE(buf, value) - return buf -} - -export function lengthAndInput(input: Uint8Array) { - return concat(uint32be(input.length), input) -} - -export async function concatKdf(secret: Uint8Array, bits: number, value: Uint8Array) { - const iterations = Math.ceil((bits >> 3) / 32) - const res = new Uint8Array(iterations * 32) - for (let iter = 0; iter < iterations; iter++) { - const buf = new Uint8Array(4 + secret.length + value.length) - buf.set(uint32be(iter + 1)) - buf.set(secret, 4) - buf.set(value, 4 + secret.length) - res.set(await digest('sha256', buf), iter * 32) - } - return res.slice(0, bits >> 3) -} diff --git a/dist/deno/lib/cek.ts b/dist/deno/lib/cek.ts deleted file mode 100644 index 22cb0bb1a7..0000000000 --- a/dist/deno/lib/cek.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { JOSENotSupported } from '../util/errors.ts' -import random from '../runtime/random.ts' - -export function bitLength(alg: string) { - switch (alg) { - case 'A128GCM': - return 128 - case 'A192GCM': - return 192 - case 'A256GCM': - case 'A128CBC-HS256': - return 256 - case 'A192CBC-HS384': - return 384 - case 'A256CBC-HS512': - return 512 - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`) - } -} -export default (alg: string): Uint8Array => random(new Uint8Array(bitLength(alg) >> 3)) diff --git a/dist/deno/lib/check_iv_length.ts b/dist/deno/lib/check_iv_length.ts deleted file mode 100644 index d63a2b280a..0000000000 --- a/dist/deno/lib/check_iv_length.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { JWEInvalid } from '../util/errors.ts' -import { bitLength } from './iv.ts' - -const checkIvLength = (enc: string, iv: Uint8Array) => { - if (iv.length << 3 !== bitLength(enc)) { - throw new JWEInvalid('Invalid Initialization Vector length') - } -} - -export default checkIvLength diff --git a/dist/deno/lib/check_key_type.ts b/dist/deno/lib/check_key_type.ts deleted file mode 100644 index cc85e608dc..0000000000 --- a/dist/deno/lib/check_key_type.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { withAlg as invalidKeyInput } from './invalid_key_input.ts' -import isKeyLike, { types } from '../runtime/is_key_like.ts' - -const symmetricTypeCheck = (alg: string, key: unknown) => { - if (key instanceof Uint8Array) return - - if (!isKeyLike(key)) { - throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array')) - } - - if (key.type !== 'secret') { - throw new TypeError( - `${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`, - ) - } -} - -const asymmetricTypeCheck = (alg: string, key: unknown, usage: string) => { - if (!isKeyLike(key)) { - throw new TypeError(invalidKeyInput(alg, key, ...types)) - } - - if (key.type === 'secret') { - throw new TypeError( - `${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`, - ) - } - - if (usage === 'sign' && key.type === 'public') { - throw new TypeError( - `${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`, - ) - } - - if (usage === 'decrypt' && key.type === 'public') { - throw new TypeError( - `${types.join( - ' or ', - )} instances for asymmetric algorithm decryption must be of type "private"`, - ) - } - - // KeyObject allows this but CryptoKey does not. - if ((key).algorithm && usage === 'verify' && key.type === 'private') { - throw new TypeError( - `${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`, - ) - } - - // KeyObject allows this but CryptoKey does not. - if ((key).algorithm && usage === 'encrypt' && key.type === 'private') { - throw new TypeError( - `${types.join( - ' or ', - )} instances for asymmetric algorithm encryption must be of type "public"`, - ) - } -} - -const checkKeyType = (alg: string, key: unknown, usage: string): void => { - const symmetric = - alg.startsWith('HS') || - alg === 'dir' || - alg.startsWith('PBES2') || - /^A\d{3}(?:GCM)?KW$/.test(alg) - - if (symmetric) { - symmetricTypeCheck(alg, key) - } else { - asymmetricTypeCheck(alg, key, usage) - } -} - -export default checkKeyType diff --git a/dist/deno/lib/check_p2s.ts b/dist/deno/lib/check_p2s.ts deleted file mode 100644 index 53c6d9c85f..0000000000 --- a/dist/deno/lib/check_p2s.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { JWEInvalid } from '../util/errors.ts' - -export default function checkP2s(p2s: Uint8Array) { - if (!(p2s instanceof Uint8Array) || p2s.length < 8) { - throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets') - } -} diff --git a/dist/deno/lib/crypto_key.ts b/dist/deno/lib/crypto_key.ts deleted file mode 100644 index 2c9eb3fdae..0000000000 --- a/dist/deno/lib/crypto_key.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { isCloudflareWorkers } from '../runtime/env.ts' - -function unusable(name: string | number, prop = 'algorithm.name') { - return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`) -} - -function isAlgorithm(algorithm: any, name: string): algorithm is T { - return algorithm.name === name -} - -function getHashLength(hash: KeyAlgorithm) { - return parseInt(hash.name.slice(4), 10) -} - -function getNamedCurve(alg: string) { - switch (alg) { - case 'ES256': - return 'P-256' - case 'ES384': - return 'P-384' - case 'ES512': - return 'P-521' - default: - throw new Error('unreachable') - } -} - -function checkUsage(key: CryptoKey, usages: KeyUsage[]) { - if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { - let msg = 'CryptoKey does not support this operation, its usages must include ' - if (usages.length > 2) { - const last = usages.pop() - msg += `one of ${usages.join(', ')}, or ${last}.` - } else if (usages.length === 2) { - msg += `one of ${usages[0]} or ${usages[1]}.` - } else { - msg += `${usages[0]}.` - } - - throw new TypeError(msg) - } -} - -export function checkSigCryptoKey(key: CryptoKey, alg: string, ...usages: KeyUsage[]) { - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': { - if (!isAlgorithm(key.algorithm, 'HMAC')) throw unusable('HMAC') - const expected = parseInt(alg.slice(2), 10) - const actual = getHashLength(key.algorithm.hash) - if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') - break - } - case 'RS256': - case 'RS384': - case 'RS512': { - if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) - throw unusable('RSASSA-PKCS1-v1_5') - const expected = parseInt(alg.slice(2), 10) - const actual = getHashLength(key.algorithm.hash) - if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') - break - } - case 'PS256': - case 'PS384': - case 'PS512': { - if (!isAlgorithm(key.algorithm, 'RSA-PSS')) throw unusable('RSA-PSS') - const expected = parseInt(alg.slice(2), 10) - const actual = getHashLength(key.algorithm.hash) - if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') - break - } - case 'EdDSA': { - if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { - if (isCloudflareWorkers()) { - if (isAlgorithm(key.algorithm, 'NODE-ED25519')) break - throw unusable('Ed25519, Ed448, or NODE-ED25519') - } - throw unusable('Ed25519 or Ed448') - } - break - } - case 'ES256': - case 'ES384': - case 'ES512': { - if (!isAlgorithm(key.algorithm, 'ECDSA')) throw unusable('ECDSA') - const expected = getNamedCurve(alg) - const actual = key.algorithm.namedCurve - if (actual !== expected) throw unusable(expected, 'algorithm.namedCurve') - break - } - default: - throw new TypeError('CryptoKey does not support this operation') - } - - checkUsage(key, usages) -} - -export function checkEncCryptoKey(key: CryptoKey, alg: string, ...usages: KeyUsage[]) { - switch (alg) { - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': { - if (!isAlgorithm(key.algorithm, 'AES-GCM')) throw unusable('AES-GCM') - const expected = parseInt(alg.slice(1, 4), 10) - const actual = key.algorithm.length - if (actual !== expected) throw unusable(expected, 'algorithm.length') - break - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - if (!isAlgorithm(key.algorithm, 'AES-KW')) throw unusable('AES-KW') - const expected = parseInt(alg.slice(1, 4), 10) - const actual = key.algorithm.length - if (actual !== expected) throw unusable(expected, 'algorithm.length') - break - } - case 'ECDH': { - switch (key.algorithm.name) { - case 'ECDH': - case 'X25519': - case 'X448': - break - default: - throw unusable('ECDH, X25519, or X448') - } - break - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': - if (!isAlgorithm(key.algorithm, 'PBKDF2')) throw unusable('PBKDF2') - break - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) throw unusable('RSA-OAEP') - const expected = parseInt(alg.slice(9), 10) || 1 - const actual = getHashLength(key.algorithm.hash) - if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') - break - } - default: - throw new TypeError('CryptoKey does not support this operation') - } - - checkUsage(key, usages) -} diff --git a/dist/deno/lib/decrypt_key_management.ts b/dist/deno/lib/decrypt_key_management.ts deleted file mode 100644 index 0960882982..0000000000 --- a/dist/deno/lib/decrypt_key_management.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { unwrap as aesKw } from '../runtime/aeskw.ts' -import * as ECDH from '../runtime/ecdhes.ts' -import { decrypt as pbes2Kw } from '../runtime/pbes2kw.ts' -import { decrypt as rsaEs } from '../runtime/rsaes.ts' -import { decode as base64url } from '../runtime/base64url.ts' - -import type { DecryptOptions, JWEHeaderParameters, KeyLike, JWK } from '../types.d.ts' -import { JOSENotSupported, JWEInvalid } from '../util/errors.ts' -import { bitLength as cekLength } from '../lib/cek.ts' -import { importJWK } from '../key/import.ts' -import checkKeyType from './check_key_type.ts' -import isObject from './is_object.ts' -import { unwrap as aesGcmKw } from './aesgcmkw.ts' - -async function decryptKeyManagement( - alg: string, - key: KeyLike | Uint8Array, - encryptedKey: Uint8Array | undefined, - joseHeader: JWEHeaderParameters, - options?: DecryptOptions, -): Promise { - checkKeyType(alg, key, 'decrypt') - - switch (alg) { - case 'dir': { - // Direct Encryption - if (encryptedKey !== undefined) - throw new JWEInvalid('Encountered unexpected JWE Encrypted Key') - - return key - } - case 'ECDH-ES': - // Direct Key Agreement - if (encryptedKey !== undefined) - throw new JWEInvalid('Encountered unexpected JWE Encrypted Key') - - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - // Direct Key Agreement - if (!isObject(joseHeader.epk)) - throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`) - - if (!ECDH.ecdhAllowed(key)) - throw new JOSENotSupported( - 'ECDH with the provided key is not allowed or not supported by your javascript runtime', - ) - - const epk = await importJWK(joseHeader.epk, alg) - let partyUInfo!: Uint8Array - let partyVInfo!: Uint8Array - - if (joseHeader.apu !== undefined) { - if (typeof joseHeader.apu !== 'string') - throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`) - partyUInfo = base64url(joseHeader.apu) - } - - if (joseHeader.apv !== undefined) { - if (typeof joseHeader.apv !== 'string') - throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`) - partyVInfo = base64url(joseHeader.apv) - } - - const sharedSecret = await ECDH.deriveKey( - epk, - key, - alg === 'ECDH-ES' ? joseHeader.enc! : alg, - alg === 'ECDH-ES' ? cekLength(joseHeader.enc!) : parseInt(alg.slice(-5, -2), 10), - partyUInfo, - partyVInfo, - ) - - if (alg === 'ECDH-ES') return sharedSecret - - // Key Agreement with Key Wrapping - if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') - - return aesKw(alg.slice(-6), sharedSecret, encryptedKey) - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - // Key Encryption (RSA) - if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') - - return rsaEs(alg, key, encryptedKey) - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - // Key Encryption (PBES2) - if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') - - if (typeof joseHeader.p2c !== 'number') - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`) - - const p2cLimit = options?.maxPBES2Count || 10_000 - - if (joseHeader.p2c > p2cLimit) - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`) - - if (typeof joseHeader.p2s !== 'string') - throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`) - - return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s)) - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - // Key Wrapping (AES KW) - if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') - - return aesKw(alg, key, encryptedKey) - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - // Key Wrapping (AES GCM KW) - if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') - - if (typeof joseHeader.iv !== 'string') - throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`) - - if (typeof joseHeader.tag !== 'string') - throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`) - - const iv = base64url(joseHeader.iv) - const tag = base64url(joseHeader.tag) - - return aesGcmKw(alg, key, encryptedKey, iv, tag) - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value') - } - } -} - -export default decryptKeyManagement diff --git a/dist/deno/lib/encrypt_key_management.ts b/dist/deno/lib/encrypt_key_management.ts deleted file mode 100644 index 4ce03a4b8d..0000000000 --- a/dist/deno/lib/encrypt_key_management.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { wrap as aesKw } from '../runtime/aeskw.ts' -import * as ECDH from '../runtime/ecdhes.ts' -import { encrypt as pbes2Kw } from '../runtime/pbes2kw.ts' -import { encrypt as rsaEs } from '../runtime/rsaes.ts' -import { encode as base64url } from '../runtime/base64url.ts' - -import type { - KeyLike, - JWEKeyManagementHeaderParameters, - JWEHeaderParameters, - JWK, -} from '../types.d.ts' -import generateCek, { bitLength as cekLength } from '../lib/cek.ts' -import { JOSENotSupported } from '../util/errors.ts' -import { exportJWK } from '../key/export.ts' -import checkKeyType from './check_key_type.ts' -import { wrap as aesGcmKw } from './aesgcmkw.ts' - -async function encryptKeyManagement( - alg: string, - enc: string, - key: KeyLike | Uint8Array, - providedCek?: Uint8Array, - providedParameters: JWEKeyManagementHeaderParameters = {}, -): Promise<{ - cek: KeyLike | Uint8Array - encryptedKey?: Uint8Array - parameters?: JWEHeaderParameters -}> { - let encryptedKey: Uint8Array | undefined - let parameters: (JWEHeaderParameters & { epk?: JWK }) | undefined - let cek: KeyLike | Uint8Array - - checkKeyType(alg, key, 'encrypt') - - switch (alg) { - case 'dir': { - // Direct Encryption - cek = key - break - } - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - // Direct Key Agreement - if (!ECDH.ecdhAllowed(key)) { - throw new JOSENotSupported( - 'ECDH with the provided key is not allowed or not supported by your javascript runtime', - ) - } - const { apu, apv } = providedParameters - let { epk: ephemeralKey } = providedParameters - ephemeralKey ||= (await ECDH.generateEpk(key)).privateKey - const { x, y, crv, kty } = await exportJWK(ephemeralKey!) - const sharedSecret = await ECDH.deriveKey( - key, - ephemeralKey, - alg === 'ECDH-ES' ? enc : alg, - alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), - apu, - apv, - ) - parameters = { epk: { x, crv, kty } } - if (kty === 'EC') parameters.epk!.y = y - if (apu) parameters.apu = base64url(apu) - if (apv) parameters.apv = base64url(apv) - - if (alg === 'ECDH-ES') { - cek = sharedSecret - break - } - - // Key Agreement with Key Wrapping - cek = providedCek || generateCek(enc) - const kwAlg = alg.slice(-6) - encryptedKey = await aesKw(kwAlg, sharedSecret, cek) - break - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - // Key Encryption (RSA) - cek = providedCek || generateCek(enc) - encryptedKey = await rsaEs(alg, key, cek) - break - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - // Key Encryption (PBES2) - cek = providedCek || generateCek(enc) - const { p2c, p2s } = providedParameters - ;({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s)) - break - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - // Key Wrapping (AES KW) - cek = providedCek || generateCek(enc) - encryptedKey = await aesKw(alg, key, cek) - break - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - // Key Wrapping (AES GCM KW) - cek = providedCek || generateCek(enc) - const { iv } = providedParameters - ;({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv)) - break - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value') - } - } - - return { cek, encryptedKey, parameters } -} - -export default encryptKeyManagement diff --git a/dist/deno/lib/epoch.ts b/dist/deno/lib/epoch.ts deleted file mode 100644 index 616795a52e..0000000000 --- a/dist/deno/lib/epoch.ts +++ /dev/null @@ -1 +0,0 @@ -export default (date: Date) => Math.floor(date.getTime() / 1000) diff --git a/dist/deno/lib/format_pem.ts b/dist/deno/lib/format_pem.ts deleted file mode 100644 index ff54c795dd..0000000000 --- a/dist/deno/lib/format_pem.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default (b64: string, descriptor: string) => { - const newlined = (b64.match(/.{1,64}/g) || []).join('\n') - return `-----BEGIN ${descriptor}-----\n${newlined}\n-----END ${descriptor}-----` -} diff --git a/dist/deno/lib/invalid_key_input.ts b/dist/deno/lib/invalid_key_input.ts deleted file mode 100644 index 2b99dd440c..0000000000 --- a/dist/deno/lib/invalid_key_input.ts +++ /dev/null @@ -1,30 +0,0 @@ -function message(msg: string, actual: unknown, ...types: string[]) { - if (types.length > 2) { - const last = types.pop() - msg += `one of type ${types.join(', ')}, or ${last}.` - } else if (types.length === 2) { - msg += `one of type ${types[0]} or ${types[1]}.` - } else { - msg += `of type ${types[0]}.` - } - - if (actual == null) { - msg += ` Received ${actual}` - } else if (typeof actual === 'function' && actual.name) { - msg += ` Received function ${actual.name}` - } else if (typeof actual === 'object' && actual != null) { - if (actual.constructor && actual.constructor.name) { - msg += ` Received an instance of ${actual.constructor.name}` - } - } - - return msg -} - -export default (actual: unknown, ...types: string[]) => { - return message('Key must be ', actual, ...types) -} - -export function withAlg(alg: string, actual: unknown, ...types: string[]) { - return message(`Key for the ${alg} algorithm must be `, actual, ...types) -} diff --git a/dist/deno/lib/is_disjoint.ts b/dist/deno/lib/is_disjoint.ts deleted file mode 100644 index c260352e76..0000000000 --- a/dist/deno/lib/is_disjoint.ts +++ /dev/null @@ -1,26 +0,0 @@ -const isDisjoint = (...headers: Array) => { - const sources = headers.filter(Boolean) - - if (sources.length === 0 || sources.length === 1) { - return true - } - - let acc!: Set - for (const header of sources) { - const parameters = Object.keys(header) - if (!acc || acc.size === 0) { - acc = new Set(parameters) - continue - } - - for (const parameter of parameters) { - if (acc.has(parameter)) { - return false - } - acc.add(parameter) - } - } - - return true -} -export default isDisjoint diff --git a/dist/deno/lib/is_object.ts b/dist/deno/lib/is_object.ts deleted file mode 100644 index 50aa4f6a5c..0000000000 --- a/dist/deno/lib/is_object.ts +++ /dev/null @@ -1,17 +0,0 @@ -function isObjectLike(value: unknown) { - return typeof value === 'object' && value !== null -} - -export default function isObject(input: unknown): input is T { - if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { - return false - } - if (Object.getPrototypeOf(input) === null) { - return true - } - let proto = input - while (Object.getPrototypeOf(proto) !== null) { - proto = Object.getPrototypeOf(proto) - } - return Object.getPrototypeOf(input) === proto -} diff --git a/dist/deno/lib/iv.ts b/dist/deno/lib/iv.ts deleted file mode 100644 index 93eb2ca8d8..0000000000 --- a/dist/deno/lib/iv.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { JOSENotSupported } from '../util/errors.ts' -import random from '../runtime/random.ts' - -export function bitLength(alg: string) { - switch (alg) { - case 'A128GCM': - case 'A128GCMKW': - case 'A192GCM': - case 'A192GCMKW': - case 'A256GCM': - case 'A256GCMKW': - return 96 - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return 128 - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`) - } -} -export default (alg: string): Uint8Array => random(new Uint8Array(bitLength(alg) >> 3)) diff --git a/dist/deno/lib/jwt_claims_set.ts b/dist/deno/lib/jwt_claims_set.ts deleted file mode 100644 index 5ebb4c0872..0000000000 --- a/dist/deno/lib/jwt_claims_set.ts +++ /dev/null @@ -1,139 +0,0 @@ -import type { - JWTPayload, - JWTClaimVerificationOptions, - JWEHeaderParameters, - JWSHeaderParameters, -} from '../types.d.ts' -import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.ts' -import { decoder } from './buffer_utils.ts' -import epoch from './epoch.ts' -import secs from './secs.ts' -import isObject from './is_object.ts' - -const normalizeTyp = (value: string) => value.toLowerCase().replace(/^application\//, '') - -const checkAudiencePresence = (audPayload: unknown, audOption: unknown[]) => { - if (typeof audPayload === 'string') { - return audOption.includes(audPayload) - } - - if (Array.isArray(audPayload)) { - // Each principal intended to process the JWT MUST - // identify itself with a value in the audience claim - return audOption.some(Set.prototype.has.bind(new Set(audPayload))) - } - - return false -} - -export default ( - protectedHeader: JWEHeaderParameters | JWSHeaderParameters, - encodedPayload: Uint8Array, - options: JWTClaimVerificationOptions = {}, -) => { - const { typ } = options - if ( - typ && - (typeof protectedHeader!.typ !== 'string' || - normalizeTyp(protectedHeader!.typ) !== normalizeTyp(typ)) - ) { - throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed') - } - - let payload!: { [propName: string]: unknown } - try { - payload = JSON.parse(decoder.decode(encodedPayload)) - } catch { - // - } - - if (!isObject(payload)) { - throw new JWTInvalid('JWT Claims Set must be a top-level JSON object') - } - - const { issuer } = options - if (issuer && !((Array.isArray(issuer) ? issuer : [issuer])).includes(payload.iss!)) { - throw new JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed') - } - - const { subject } = options - if (subject && payload.sub !== subject) { - throw new JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed') - } - - const { audience } = options - if ( - audience && - !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience) - ) { - throw new JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed') - } - - let tolerance: number - switch (typeof options.clockTolerance) { - case 'string': - tolerance = secs(options.clockTolerance) - break - case 'number': - tolerance = options.clockTolerance - break - case 'undefined': - tolerance = 0 - break - default: - throw new TypeError('Invalid clockTolerance option type') - } - - const { currentDate } = options - const now = epoch(currentDate || new Date()) - - if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { - throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid') - } - - if (payload.nbf !== undefined) { - if (typeof payload.nbf !== 'number') { - throw new JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid') - } - if (payload.nbf > now + tolerance) { - throw new JWTClaimValidationFailed( - '"nbf" claim timestamp check failed', - 'nbf', - 'check_failed', - ) - } - } - - if (payload.exp !== undefined) { - if (typeof payload.exp !== 'number') { - throw new JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid') - } - if (payload.exp <= now - tolerance) { - throw new JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed') - } - } - - if (options.maxTokenAge) { - const age = now - payload.iat! - const max = - typeof options.maxTokenAge === 'number' ? options.maxTokenAge : secs(options.maxTokenAge) - - if (age - tolerance > max) { - throw new JWTExpired( - '"iat" claim timestamp check failed (too far in the past)', - 'iat', - 'check_failed', - ) - } - - if (age < 0 - tolerance) { - throw new JWTClaimValidationFailed( - '"iat" claim timestamp check failed (it should be in the past)', - 'iat', - 'check_failed', - ) - } - } - - return payload -} diff --git a/dist/deno/lib/secs.ts b/dist/deno/lib/secs.ts deleted file mode 100644 index 8d9f07f7de..0000000000 --- a/dist/deno/lib/secs.ts +++ /dev/null @@ -1,51 +0,0 @@ -const minute = 60 -const hour = minute * 60 -const day = hour * 24 -const week = day * 7 -const year = day * 365.25 - -const REGEX = - /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i - -export default (str: string): number => { - const matched = REGEX.exec(str) - - if (!matched) { - throw new TypeError('Invalid time period format') - } - - const value = parseFloat(matched[1]) - const unit = matched[2].toLowerCase() - - switch (unit) { - case 'sec': - case 'secs': - case 'second': - case 'seconds': - case 's': - return Math.round(value) - case 'minute': - case 'minutes': - case 'min': - case 'mins': - case 'm': - return Math.round(value * minute) - case 'hour': - case 'hours': - case 'hr': - case 'hrs': - case 'h': - return Math.round(value * hour) - case 'day': - case 'days': - case 'd': - return Math.round(value * day) - case 'week': - case 'weeks': - case 'w': - return Math.round(value * week) - // years matched - default: - return Math.round(value * year) - } -} diff --git a/dist/deno/lib/validate_algorithms.ts b/dist/deno/lib/validate_algorithms.ts deleted file mode 100644 index 870efaa6ef..0000000000 --- a/dist/deno/lib/validate_algorithms.ts +++ /dev/null @@ -1,16 +0,0 @@ -const validateAlgorithms = (option: string, algorithms?: string[]) => { - if ( - algorithms !== undefined && - (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string')) - ) { - throw new TypeError(`"${option}" option must be an array of strings`) - } - - if (!algorithms) { - return undefined - } - - return new Set(algorithms) -} - -export default validateAlgorithms diff --git a/dist/deno/lib/validate_crit.ts b/dist/deno/lib/validate_crit.ts deleted file mode 100644 index d5ea76dc55..0000000000 --- a/dist/deno/lib/validate_crit.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.ts' - -interface CritCheckHeader { - b64?: boolean - crit?: string[] - [propName: string]: unknown -} - -function validateCrit( - Err: typeof JWEInvalid | typeof JWSInvalid, - recognizedDefault: Map, - recognizedOption: { [propName: string]: boolean } | undefined, - protectedHeader: CritCheckHeader, - joseHeader: CritCheckHeader, -) { - if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { - throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected') - } - - if (!protectedHeader || protectedHeader.crit === undefined) { - return new Set() - } - - if ( - !Array.isArray(protectedHeader.crit) || - protectedHeader.crit.length === 0 || - protectedHeader.crit.some((input: string) => typeof input !== 'string' || input.length === 0) - ) { - throw new Err( - '"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present', - ) - } - - let recognized: Map - if (recognizedOption !== undefined) { - recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]) - } else { - recognized = recognizedDefault - } - - for (const parameter of protectedHeader.crit) { - if (!recognized.has(parameter)) { - throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`) - } - - if (joseHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" is missing`) - } else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`) - } - } - - return new Set(protectedHeader.crit) -} - -export default validateCrit diff --git a/dist/deno/runtime/aeskw.ts b/dist/deno/runtime/aeskw.ts deleted file mode 100644 index 72da0ef4a7..0000000000 --- a/dist/deno/runtime/aeskw.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { AesKwUnwrapFunction, AesKwWrapFunction } from './interfaces.d.ts' -import bogusWebCrypto from './bogus.ts' -import crypto, { isCryptoKey } from './webcrypto.ts' -import { checkEncCryptoKey } from '../lib/crypto_key.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { types } from './is_key_like.ts' - -function checkKeySize(key: CryptoKey, alg: string) { - if ((key.algorithm).length !== parseInt(alg.slice(1, 4), 10)) { - throw new TypeError(`Invalid key size for alg: ${alg}`) - } -} - -function getCryptoKey(key: unknown, alg: string, usage: KeyUsage) { - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, usage) - return key - } - - if (key instanceof Uint8Array) { - return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]) - } - - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) -} - -export const wrap: AesKwWrapFunction = async (alg: string, key: unknown, cek: Uint8Array) => { - const cryptoKey = await getCryptoKey(key, alg, 'wrapKey') - - checkKeySize(cryptoKey, alg) - - // we're importing the cek to end up with CryptoKey instance that can be wrapped, the algorithm used is irrelevant - const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto) - - return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, cryptoKey, 'AES-KW')) -} - -export const unwrap: AesKwUnwrapFunction = async ( - alg: string, - key: unknown, - encryptedKey: Uint8Array, -) => { - const cryptoKey = await getCryptoKey(key, alg, 'unwrapKey') - - checkKeySize(cryptoKey, alg) - - const cryptoKeyCek = await crypto.subtle.unwrapKey( - 'raw', - encryptedKey, - cryptoKey, - 'AES-KW', - ...bogusWebCrypto, - ) - - return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)) -} diff --git a/dist/deno/runtime/asn1.ts b/dist/deno/runtime/asn1.ts deleted file mode 100644 index 7e4db5886e..0000000000 --- a/dist/deno/runtime/asn1.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { isCloudflareWorkers } from './env.ts' -import crypto, { isCryptoKey } from './webcrypto.ts' -import type { PEMExportFunction, PEMImportFunction } from './interfaces.d.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { encodeBase64, decodeBase64 } from './base64url.ts' -import formatPEM from '../lib/format_pem.ts' -import { JOSENotSupported } from '../util/errors.ts' -import { types } from './is_key_like.ts' - -import type { PEMImportOptions } from '../key/import.ts' - -const genericExport = async ( - keyType: 'private' | 'public', - keyFormat: 'spki' | 'pkcs8', - key: unknown, -) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)) - } - - if (!key.extractable) { - throw new TypeError('CryptoKey is not extractable') - } - - if (key.type !== keyType) { - throw new TypeError(`key is not a ${keyType} key`) - } - - return formatPEM( - encodeBase64(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), - `${keyType.toUpperCase()} KEY`, - ) -} - -export const toSPKI: PEMExportFunction = (key) => { - return genericExport('public', 'spki', key) -} - -export const toPKCS8: PEMExportFunction = (key) => { - return genericExport('private', 'pkcs8', key) -} - -const findOid = (keyData: Uint8Array, oid: number[], from = 0): boolean => { - if (from === 0) { - oid.unshift(oid.length) - oid.unshift(0x06) - } - let i = keyData.indexOf(oid[0], from) - if (i === -1) return false - const sub = keyData.subarray(i, i + oid.length) - if (sub.length !== oid.length) return false - return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1) -} - -const getNamedCurve = (keyData: Uint8Array): string => { - switch (true) { - case findOid(keyData, [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]): - return 'P-256' - case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x22]): - return 'P-384' - case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]): - return 'P-521' - case findOid(keyData, [0x2b, 0x65, 0x6e]): - return 'X25519' - case findOid(keyData, [0x2b, 0x65, 0x6f]): - return 'X448' - case findOid(keyData, [0x2b, 0x65, 0x70]): - return 'Ed25519' - case findOid(keyData, [0x2b, 0x65, 0x71]): - return 'Ed448' - default: - throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type') - } -} - -const genericImport = async ( - replace: RegExp, - keyFormat: 'spki' | 'pkcs8', - pem: string, - alg: string, - options?: PEMImportOptions, -) => { - let algorithm: RsaHashedImportParams | EcKeyAlgorithm | Algorithm - let keyUsages: KeyUsage[] - - const keyData = new Uint8Array( - atob(pem.replace(replace, '')) - .split('') - .map((c) => c.charCodeAt(0)), - ) - - const isPublic = keyFormat === 'spki' - - switch (alg) { - case 'PS256': - case 'PS384': - case 'PS512': - algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` } - keyUsages = isPublic ? ['verify'] : ['sign'] - break - case 'RS256': - case 'RS384': - case 'RS512': - algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` } - keyUsages = isPublic ? ['verify'] : ['sign'] - break - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - algorithm = { - name: 'RSA-OAEP', - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, - } - keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'] - break - case 'ES256': - algorithm = { name: 'ECDSA', namedCurve: 'P-256' } - keyUsages = isPublic ? ['verify'] : ['sign'] - break - case 'ES384': - algorithm = { name: 'ECDSA', namedCurve: 'P-384' } - keyUsages = isPublic ? ['verify'] : ['sign'] - break - case 'ES512': - algorithm = { name: 'ECDSA', namedCurve: 'P-521' } - keyUsages = isPublic ? ['verify'] : ['sign'] - break - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - const namedCurve = getNamedCurve(keyData) - algorithm = namedCurve.startsWith('P-') ? { name: 'ECDH', namedCurve } : { name: namedCurve } - keyUsages = isPublic ? [] : ['deriveBits'] - break - } - case 'EdDSA': - algorithm = { name: getNamedCurve(keyData) } - keyUsages = isPublic ? ['verify'] : ['sign'] - break - default: - throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value') - } - - try { - return await crypto.subtle.importKey( - keyFormat, - keyData, - algorithm, - options?.extractable ?? false, - keyUsages, - ) - } catch (err) { - if ( - algorithm.name === 'Ed25519' && - (err)?.name === 'NotSupportedError' && - isCloudflareWorkers() - ) { - algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } - return await crypto.subtle.importKey( - keyFormat, - keyData, - algorithm, - options?.extractable ?? false, - keyUsages, - ) - } - throw err - } -} - -export const fromPKCS8: PEMImportFunction = (pem, alg, options?) => { - return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options) -} - -export const fromSPKI: PEMImportFunction = (pem, alg, options?) => { - return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, 'spki', pem, alg, options) -} - -function getElement(seq: Uint8Array) { - let result = [] - let next = 0 - - while (next < seq.length) { - let nextPart = parseElement(seq.subarray(next)) - result.push(nextPart) - next += nextPart.byteLength - } - return result -} - -function parseElement(bytes: Uint8Array) { - let position = 0 - - // tag - let tag = bytes[0] & 0x1f - position++ - if (tag === 0x1f) { - tag = 0 - while (bytes[position] >= 0x80) { - tag = tag * 128 + bytes[position] - 0x80 - position++ - } - tag = tag * 128 + bytes[position] - 0x80 - position++ - } - - // length - let length = 0 - if (bytes[position] < 0x80) { - length = bytes[position] - position++ - } else if (length === 0x80) { - length = 0 - - while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { - if (length > bytes.byteLength) { - throw new TypeError('invalid indefinite form length') - } - length++ - } - - const byteLength = position + length + 2 - return { - byteLength, - contents: bytes.subarray(position, position + length), - raw: bytes.subarray(0, byteLength), - } - } else { - let numberOfDigits = bytes[position] & 0x7f - position++ - length = 0 - for (let i = 0; i < numberOfDigits; i++) { - length = length * 256 + bytes[position] - position++ - } - } - - const byteLength = position + length - return { - byteLength, - contents: bytes.subarray(position, byteLength), - raw: bytes.subarray(0, byteLength), - } -} - -function spkiFromX509(buf: Uint8Array) { - const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents) - return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 0xa0 ? 6 : 5].raw) -} - -function getSPKI(x509: string): string { - const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '') - const raw = decodeBase64(pem) - return formatPEM(spkiFromX509(raw), 'PUBLIC KEY') -} - -export const fromX509: PEMImportFunction = (pem, alg, options?) => { - let spki: string - try { - spki = getSPKI(pem) - } catch (cause) { - // @ts-ignore - throw new TypeError('failed to parse the X.509 certificate', { cause }) - } - return fromSPKI(spki, alg, options) -} diff --git a/dist/deno/runtime/base64url.ts b/dist/deno/runtime/base64url.ts deleted file mode 100644 index 45dff570c3..0000000000 --- a/dist/deno/runtime/base64url.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { encoder, decoder } from '../lib/buffer_utils.ts' - -export const encodeBase64 = (input: Uint8Array | string) => { - let unencoded = input - if (typeof unencoded === 'string') { - unencoded = encoder.encode(unencoded) - } - const CHUNK_SIZE = 0x8000 - const arr = [] - for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { - // @ts-expect-error - arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))) - } - return btoa(arr.join('')) -} - -export const encode = (input: Uint8Array | string) => { - return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_') -} - -export const decodeBase64 = (encoded: string): Uint8Array => { - const binary = atob(encoded) - const bytes = new Uint8Array(binary.length) - for (let i = 0; i < binary.length; i++) { - bytes[i] = binary.charCodeAt(i) - } - return bytes -} - -export const decode = (input: Uint8Array | string) => { - let encoded = input - if (encoded instanceof Uint8Array) { - encoded = decoder.decode(encoded) - } - encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '') - try { - return decodeBase64(encoded) - } catch { - throw new TypeError('The input to be decoded is not correctly encoded.') - } -} diff --git a/dist/deno/runtime/bogus.ts b/dist/deno/runtime/bogus.ts deleted file mode 100644 index 3f7bcfdf66..0000000000 --- a/dist/deno/runtime/bogus.ts +++ /dev/null @@ -1,7 +0,0 @@ -const bogusWebCrypto: [HmacImportParams, boolean, KeyUsage[]] = [ - { hash: 'SHA-256', name: 'HMAC' }, - true, - ['sign'], -] - -export default bogusWebCrypto diff --git a/dist/deno/runtime/check_cek_length.ts b/dist/deno/runtime/check_cek_length.ts deleted file mode 100644 index 44aeda9684..0000000000 --- a/dist/deno/runtime/check_cek_length.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { JWEInvalid } from '../util/errors.ts' - -const checkCekLength = (cek: Uint8Array, expected: number) => { - const actual = cek.byteLength << 3 - if (actual !== expected) { - throw new JWEInvalid( - `Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`, - ) - } -} - -export default checkCekLength diff --git a/dist/deno/runtime/check_key_length.ts b/dist/deno/runtime/check_key_length.ts deleted file mode 100644 index fac5e16f32..0000000000 --- a/dist/deno/runtime/check_key_length.ts +++ /dev/null @@ -1,8 +0,0 @@ -export default (alg: string, key: CryptoKey) => { - if (alg.startsWith('RS') || alg.startsWith('PS')) { - const { modulusLength } = key.algorithm - if (typeof modulusLength !== 'number' || modulusLength < 2048) { - throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`) - } - } -} diff --git a/dist/deno/runtime/decrypt.ts b/dist/deno/runtime/decrypt.ts deleted file mode 100644 index 5210491dea..0000000000 --- a/dist/deno/runtime/decrypt.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { concat, uint64be } from '../lib/buffer_utils.ts' - -import type { DecryptFunction } from './interfaces.d.ts' -import checkIvLength from '../lib/check_iv_length.ts' -import checkCekLength from './check_cek_length.ts' -import timingSafeEqual from './timing_safe_equal.ts' -import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.ts' -import crypto, { isCryptoKey } from './webcrypto.ts' -import { checkEncCryptoKey } from '../lib/crypto_key.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { types } from './is_key_like.ts' - -async function cbcDecrypt( - enc: string, - cek: Uint8Array | CryptoKey, - ciphertext: Uint8Array, - iv: Uint8Array, - tag: Uint8Array, - aad: Uint8Array, -) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, 'Uint8Array')) - } - const keySize = parseInt(enc.slice(1, 4), 10) - const encKey = await crypto.subtle.importKey( - 'raw', - cek.subarray(keySize >> 3), - 'AES-CBC', - false, - ['decrypt'], - ) - const macKey = await crypto.subtle.importKey( - 'raw', - cek.subarray(0, keySize >> 3), - { - hash: `SHA-${keySize << 1}`, - name: 'HMAC', - }, - false, - ['sign'], - ) - - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)) - const expectedTag = new Uint8Array( - (await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3), - ) - - let macCheckPassed!: boolean - try { - macCheckPassed = timingSafeEqual(tag, expectedTag) - } catch { - // - } - if (!macCheckPassed) { - throw new JWEDecryptionFailed() - } - - let plaintext!: Uint8Array - try { - plaintext = new Uint8Array( - await crypto.subtle.decrypt({ iv, name: 'AES-CBC' }, encKey, ciphertext), - ) - } catch { - // - } - if (!plaintext) { - throw new JWEDecryptionFailed() - } - - return plaintext -} - -async function gcmDecrypt( - enc: string, - cek: Uint8Array | CryptoKey, - ciphertext: Uint8Array, - iv: Uint8Array, - tag: Uint8Array, - aad: Uint8Array, -) { - let encKey: CryptoKey - if (cek instanceof Uint8Array) { - encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']) - } else { - checkEncCryptoKey(cek, enc, 'decrypt') - encKey = cek - } - - try { - return new Uint8Array( - await crypto.subtle.decrypt( - { - additionalData: aad, - iv, - name: 'AES-GCM', - tagLength: 128, - }, - encKey, - concat(ciphertext, tag), - ), - ) - } catch { - throw new JWEDecryptionFailed() - } -} - -const decrypt: DecryptFunction = async ( - enc: string, - cek: unknown, - ciphertext: Uint8Array, - iv: Uint8Array, - tag: Uint8Array, - aad: Uint8Array, -) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')) - } - - checkIvLength(enc, iv) - - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(-3), 10)) - return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(1, 4), 10)) - return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) - default: - throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm') - } -} - -export default decrypt diff --git a/dist/deno/runtime/digest.ts b/dist/deno/runtime/digest.ts deleted file mode 100644 index 58a6e302a1..0000000000 --- a/dist/deno/runtime/digest.ts +++ /dev/null @@ -1,11 +0,0 @@ -import crypto from './webcrypto.ts' -import type { DigestFunction } from './interfaces.d.ts' - -const digest: DigestFunction = async ( - algorithm: 'sha256' | 'sha384' | 'sha512', - data: Uint8Array, -): Promise => { - const subtleDigest = `SHA-${algorithm.slice(-3)}` - return new Uint8Array(await crypto.subtle.digest(subtleDigest, data)) -} -export default digest diff --git a/dist/deno/runtime/ecdhes.ts b/dist/deno/runtime/ecdhes.ts deleted file mode 100644 index d5f67827fb..0000000000 --- a/dist/deno/runtime/ecdhes.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.ts' -import crypto, { isCryptoKey } from './webcrypto.ts' -import { checkEncCryptoKey } from '../lib/crypto_key.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { types } from './is_key_like.ts' - -export async function deriveKey( - publicKey: unknown, - privateKey: unknown, - algorithm: string, - keyLength: number, - apu: Uint8Array = new Uint8Array(0), - apv: Uint8Array = new Uint8Array(0), -) { - if (!isCryptoKey(publicKey)) { - throw new TypeError(invalidKeyInput(publicKey, ...types)) - } - checkEncCryptoKey(publicKey, 'ECDH') - if (!isCryptoKey(privateKey)) { - throw new TypeError(invalidKeyInput(privateKey, ...types)) - } - checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits') - - const value = concat( - lengthAndInput(encoder.encode(algorithm)), - lengthAndInput(apu), - lengthAndInput(apv), - uint32be(keyLength), - ) - - let length: number - if (publicKey.algorithm.name === 'X25519') { - length = 256 - } else if (publicKey.algorithm.name === 'X448') { - length = 448 - } else { - length = - Math.ceil(parseInt((publicKey.algorithm).namedCurve.substr(-3), 10) / 8) << 3 - } - - const sharedSecret = new Uint8Array( - await crypto.subtle.deriveBits( - { - name: publicKey.algorithm.name, - public: publicKey, - }, - privateKey, - length, - ), - ) - - return concatKdf(sharedSecret, keyLength, value) -} - -export async function generateEpk(key: unknown) { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)) - } - - return crypto.subtle.generateKey(key.algorithm, true, ['deriveBits']) -} - -export function ecdhAllowed(key: unknown) { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)) - } - return ( - ['P-256', 'P-384', 'P-521'].includes((key.algorithm).namedCurve) || - key.algorithm.name === 'X25519' || - key.algorithm.name === 'X448' - ) -} diff --git a/dist/deno/runtime/encrypt.ts b/dist/deno/runtime/encrypt.ts deleted file mode 100644 index f74773c6bb..0000000000 --- a/dist/deno/runtime/encrypt.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { concat, uint64be } from '../lib/buffer_utils.ts' -import type { EncryptFunction } from './interfaces.d.ts' -import checkIvLength from '../lib/check_iv_length.ts' -import checkCekLength from './check_cek_length.ts' -import crypto, { isCryptoKey } from './webcrypto.ts' -import { checkEncCryptoKey } from '../lib/crypto_key.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { JOSENotSupported } from '../util/errors.ts' -import { types } from './is_key_like.ts' - -async function cbcEncrypt( - enc: string, - plaintext: Uint8Array, - cek: Uint8Array | CryptoKey, - iv: Uint8Array, - aad: Uint8Array, -) { - if (!(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, 'Uint8Array')) - } - const keySize = parseInt(enc.slice(1, 4), 10) - const encKey = await crypto.subtle.importKey( - 'raw', - cek.subarray(keySize >> 3), - 'AES-CBC', - false, - ['encrypt'], - ) - const macKey = await crypto.subtle.importKey( - 'raw', - cek.subarray(0, keySize >> 3), - { - hash: `SHA-${keySize << 1}`, - name: 'HMAC', - }, - false, - ['sign'], - ) - - const ciphertext = new Uint8Array( - await crypto.subtle.encrypt( - { - iv, - name: 'AES-CBC', - }, - encKey, - plaintext, - ), - ) - - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)) - const tag = new Uint8Array( - (await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3), - ) - - return { ciphertext, tag } -} - -async function gcmEncrypt( - enc: string, - plaintext: Uint8Array, - cek: Uint8Array | CryptoKey, - iv: Uint8Array, - aad: Uint8Array, -) { - let encKey: CryptoKey - if (cek instanceof Uint8Array) { - encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']) - } else { - checkEncCryptoKey(cek, enc, 'encrypt') - encKey = cek - } - - const encrypted = new Uint8Array( - await crypto.subtle.encrypt( - { - additionalData: aad, - iv, - name: 'AES-GCM', - tagLength: 128, - }, - encKey, - plaintext, - ), - ) - - const tag = encrypted.slice(-16) - const ciphertext = encrypted.slice(0, -16) - - return { ciphertext, tag } -} - -const encrypt: EncryptFunction = async ( - enc: string, - plaintext: Uint8Array, - cek: unknown, - iv: Uint8Array, - aad: Uint8Array, -) => { - if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { - throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')) - } - - checkIvLength(enc, iv) - - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(-3), 10)) - return cbcEncrypt(enc, plaintext, cek, iv, aad) - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(1, 4), 10)) - return gcmEncrypt(enc, plaintext, cek, iv, aad) - default: - throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm') - } -} - -export default encrypt diff --git a/dist/deno/runtime/env.ts b/dist/deno/runtime/env.ts deleted file mode 100644 index c756022f1b..0000000000 --- a/dist/deno/runtime/env.ts +++ /dev/null @@ -1,10 +0,0 @@ -export function isCloudflareWorkers() { - return ( - // @ts-ignore - typeof WebSocketPair !== 'undefined' || - // @ts-ignore - (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') || - // @ts-ignore - (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel') - ) -} diff --git a/dist/deno/runtime/fetch_jwks.ts b/dist/deno/runtime/fetch_jwks.ts deleted file mode 100644 index 6b7aad808f..0000000000 --- a/dist/deno/runtime/fetch_jwks.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { FetchFunction } from './interfaces.d.ts' -import { JOSEError, JWKSTimeout } from '../util/errors.ts' - -type AcceptedRequestOptions = Pick - -const fetchJwks: FetchFunction = async ( - url: URL, - timeout: number, - options: AcceptedRequestOptions, -) => { - let controller!: AbortController - let id!: ReturnType - let timedOut = false - if (typeof AbortController === 'function') { - controller = new AbortController() - id = setTimeout(() => { - timedOut = true - controller.abort() - }, timeout) - } - - const response = await fetch(url.href, { - signal: controller ? controller.signal : undefined, - redirect: 'manual', - headers: options.headers, - }).catch((err) => { - if (timedOut) throw new JWKSTimeout() - throw err - }) - - if (id !== undefined) clearTimeout(id) - - if (response.status !== 200) { - throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response') - } - - try { - return await response.json() - } catch { - throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON') - } -} -export default fetchJwks diff --git a/dist/deno/runtime/generate.ts b/dist/deno/runtime/generate.ts deleted file mode 100644 index b9672cf2fb..0000000000 --- a/dist/deno/runtime/generate.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { isCloudflareWorkers } from './env.ts' -import crypto from './webcrypto.ts' -import { JOSENotSupported } from '../util/errors.ts' -import random from './random.ts' -import type { GenerateKeyPairOptions } from '../key/generate_key_pair.ts' -import type { GenerateSecretOptions } from '../key/generate_secret.ts' - -export async function generateSecret(alg: string, options?: GenerateSecretOptions) { - let length: number - let algorithm: AesKeyGenParams | HmacKeyGenParams - let keyUsages: KeyUsage[] - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': - length = parseInt(alg.slice(-3), 10) - algorithm = { name: 'HMAC', hash: `SHA-${length}`, length } - keyUsages = ['sign', 'verify'] - break - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - length = parseInt(alg.slice(-3), 10) - return random(new Uint8Array(length >> 3)) - case 'A128KW': - case 'A192KW': - case 'A256KW': - length = parseInt(alg.slice(1, 4), 10) - algorithm = { name: 'AES-KW', length } - keyUsages = ['wrapKey', 'unwrapKey'] - break - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - length = parseInt(alg.slice(1, 4), 10) - algorithm = { name: 'AES-GCM', length } - keyUsages = ['encrypt', 'decrypt'] - break - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') - } - - return >( - (crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages)) - ) -} - -function getModulusLengthOption(options?: GenerateKeyPairOptions) { - const modulusLength = options?.modulusLength ?? 2048 - if (typeof modulusLength !== 'number' || modulusLength < 2048) { - throw new JOSENotSupported( - 'Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used', - ) - } - return modulusLength -} - -export async function generateKeyPair(alg: string, options?: GenerateKeyPairOptions) { - let algorithm: RsaHashedKeyGenParams | EcKeyGenParams | KeyAlgorithm - let keyUsages: KeyUsage[] - - switch (alg) { - case 'PS256': - case 'PS384': - case 'PS512': - algorithm = { - name: 'RSA-PSS', - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([0x01, 0x00, 0x01]), - modulusLength: getModulusLengthOption(options), - } - keyUsages = ['sign', 'verify'] - break - case 'RS256': - case 'RS384': - case 'RS512': - algorithm = { - name: 'RSASSA-PKCS1-v1_5', - hash: `SHA-${alg.slice(-3)}`, - publicExponent: new Uint8Array([0x01, 0x00, 0x01]), - modulusLength: getModulusLengthOption(options), - } - keyUsages = ['sign', 'verify'] - break - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - algorithm = { - name: 'RSA-OAEP', - hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, - publicExponent: new Uint8Array([0x01, 0x00, 0x01]), - modulusLength: getModulusLengthOption(options), - } - keyUsages = ['decrypt', 'unwrapKey', 'encrypt', 'wrapKey'] - break - case 'ES256': - algorithm = { name: 'ECDSA', namedCurve: 'P-256' } - keyUsages = ['sign', 'verify'] - break - case 'ES384': - algorithm = { name: 'ECDSA', namedCurve: 'P-384' } - keyUsages = ['sign', 'verify'] - break - case 'ES512': - algorithm = { name: 'ECDSA', namedCurve: 'P-521' } - keyUsages = ['sign', 'verify'] - break - case 'EdDSA': - keyUsages = ['sign', 'verify'] - const crv = options?.crv ?? 'Ed25519' - switch (crv) { - case 'Ed25519': - case 'Ed448': - algorithm = { name: crv } - break - default: - throw new JOSENotSupported('Invalid or unsupported crv option provided') - } - break - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - keyUsages = ['deriveKey', 'deriveBits'] - const crv = options?.crv ?? 'P-256' - switch (crv) { - case 'P-256': - case 'P-384': - case 'P-521': { - algorithm = { name: 'ECDH', namedCurve: crv } - break - } - case 'X25519': - case 'X448': - algorithm = { name: crv } - break - default: - throw new JOSENotSupported( - 'Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448', - ) - } - break - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') - } - - try { - return <{ publicKey: CryptoKey; privateKey: CryptoKey }>( - await crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages) - ) - } catch (err) { - if ( - algorithm.name === 'Ed25519' && - (err)?.name === 'NotSupportedError' && - isCloudflareWorkers() - ) { - algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } - return <{ publicKey: CryptoKey; privateKey: CryptoKey }>( - await crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages) - ) - } - throw err - } -} diff --git a/dist/deno/runtime/get_sign_verify_key.ts b/dist/deno/runtime/get_sign_verify_key.ts deleted file mode 100644 index 9a813f8e3c..0000000000 --- a/dist/deno/runtime/get_sign_verify_key.ts +++ /dev/null @@ -1,26 +0,0 @@ -import crypto, { isCryptoKey } from './webcrypto.ts' -import { checkSigCryptoKey } from '../lib/crypto_key.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { types } from './is_key_like.ts' - -export default function getCryptoKey(alg: string, key: unknown, usage: KeyUsage) { - if (isCryptoKey(key)) { - checkSigCryptoKey(key, alg, usage) - return key - } - - if (key instanceof Uint8Array) { - if (!alg.startsWith('HS')) { - throw new TypeError(invalidKeyInput(key, ...types)) - } - return crypto.subtle.importKey( - 'raw', - key, - { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, - false, - [usage], - ) - } - - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) -} diff --git a/dist/deno/runtime/interfaces.d.ts b/dist/deno/runtime/interfaces.d.ts deleted file mode 100644 index 242c79603f..0000000000 --- a/dist/deno/runtime/interfaces.d.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { JWK, KeyLike } from '../types.d.ts' -import type { PEMImportOptions } from '../key/import.ts' - -type AsyncOrSync = Promise | T - -export interface TimingSafeEqual { - (a: Uint8Array, b: Uint8Array): boolean -} -export interface SignFunction { - (alg: string, key: unknown, data: Uint8Array): Promise -} -export interface VerifyFunction { - (alg: string, key: unknown, signature: Uint8Array, data: Uint8Array): Promise -} -export interface AesKwWrapFunction { - (alg: string, key: unknown, cek: Uint8Array): AsyncOrSync -} -export interface AesKwUnwrapFunction { - (alg: string, key: unknown, encryptedKey: Uint8Array): AsyncOrSync -} -export interface RsaEsEncryptFunction { - (alg: string, key: unknown, cek: Uint8Array): AsyncOrSync -} -export interface RsaEsDecryptFunction { - (alg: string, key: unknown, encryptedKey: Uint8Array): AsyncOrSync -} -export interface Pbes2KWEncryptFunction { - (alg: string, key: unknown, cek: Uint8Array, p2c?: number, p2s?: Uint8Array): Promise<{ - encryptedKey: Uint8Array - p2c: number - p2s: string - }> -} -export interface Pbes2KWDecryptFunction { - ( - alg: string, - key: unknown, - encryptedKey: Uint8Array, - p2c: number, - p2s: Uint8Array, - ): Promise -} -export interface EncryptFunction { - (enc: string, plaintext: Uint8Array, cek: unknown, iv: Uint8Array, aad: Uint8Array): AsyncOrSync<{ - ciphertext: Uint8Array - tag: Uint8Array - }> -} -export interface DecryptFunction { - ( - enc: string, - cek: unknown, - ciphertext: Uint8Array, - iv: Uint8Array, - tag: Uint8Array, - additionalData: Uint8Array, - ): AsyncOrSync -} -export interface FetchFunction { - (url: URL, timeout: number, options?: any): Promise<{ [propName: string]: unknown }> -} -export interface DigestFunction { - (digest: 'sha256' | 'sha384' | 'sha512', data: Uint8Array): AsyncOrSync -} -export interface JWKImportFunction { - (jwk: JWK): AsyncOrSync -} -export interface PEMImportFunction { - (pem: string, alg: string, options?: PEMImportOptions): AsyncOrSync -} -interface ExportFunction { - (key: unknown): AsyncOrSync -} -export type JWKExportFunction = ExportFunction -export type PEMExportFunction = ExportFunction diff --git a/dist/deno/runtime/is_key_like.ts b/dist/deno/runtime/is_key_like.ts deleted file mode 100644 index 7023da56fc..0000000000 --- a/dist/deno/runtime/is_key_like.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { KeyLike } from '../types.d.ts' -import { isCryptoKey } from './webcrypto.ts' - -export default (key: unknown): key is KeyLike => { - return isCryptoKey(key) -} - -export const types = ['CryptoKey'] diff --git a/dist/deno/runtime/jwk_to_key.ts b/dist/deno/runtime/jwk_to_key.ts deleted file mode 100644 index 8367979fff..0000000000 --- a/dist/deno/runtime/jwk_to_key.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { isCloudflareWorkers } from './env.ts' -import crypto from './webcrypto.ts' -import type { JWKImportFunction } from './interfaces.d.ts' -import { JOSENotSupported } from '../util/errors.ts' -import type { JWK } from '../types.d.ts' -import { decode as base64url } from './base64url.ts' - -function subtleMapping(jwk: JWK): { - algorithm: RsaHashedImportParams | EcKeyAlgorithm | Algorithm - keyUsages: KeyUsage[] -} { - let algorithm: RsaHashedImportParams | EcKeyAlgorithm | Algorithm - let keyUsages: KeyUsage[] - - switch (jwk.kty) { - case 'oct': { - switch (jwk.alg) { - case 'HS256': - case 'HS384': - case 'HS512': - algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.slice(-3)}` } - keyUsages = ['sign', 'verify'] - break - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`) - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': - algorithm = { name: 'AES-GCM' } - keyUsages = ['encrypt', 'decrypt'] - break - case 'A128KW': - case 'A192KW': - case 'A256KW': - algorithm = { name: 'AES-KW' } - keyUsages = ['wrapKey', 'unwrapKey'] - break - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': - algorithm = { name: 'PBKDF2' } - keyUsages = ['deriveBits'] - break - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') - } - break - } - case 'RSA': { - switch (jwk.alg) { - case 'PS256': - case 'PS384': - case 'PS512': - algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` } - keyUsages = jwk.d ? ['sign'] : ['verify'] - break - case 'RS256': - case 'RS384': - case 'RS512': - algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` } - keyUsages = jwk.d ? ['sign'] : ['verify'] - break - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - algorithm = { - name: 'RSA-OAEP', - hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`, - } - keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'] - break - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') - } - break - } - case 'EC': { - switch (jwk.alg) { - case 'ES256': - algorithm = { name: 'ECDSA', namedCurve: 'P-256' } - keyUsages = jwk.d ? ['sign'] : ['verify'] - break - case 'ES384': - algorithm = { name: 'ECDSA', namedCurve: 'P-384' } - keyUsages = jwk.d ? ['sign'] : ['verify'] - break - case 'ES512': - algorithm = { name: 'ECDSA', namedCurve: 'P-521' } - keyUsages = jwk.d ? ['sign'] : ['verify'] - break - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': - algorithm = { name: 'ECDH', namedCurve: jwk.crv! } - keyUsages = jwk.d ? ['deriveBits'] : [] - break - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') - } - break - } - case 'OKP': { - switch (jwk.alg) { - case 'EdDSA': - algorithm = { name: jwk.crv! } - keyUsages = jwk.d ? ['sign'] : ['verify'] - break - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': - algorithm = { name: jwk.crv! } - keyUsages = jwk.d ? ['deriveBits'] : [] - break - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') - } - break - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value') - } - - return { algorithm, keyUsages } -} - -const parse: JWKImportFunction = async (jwk: JWK): Promise => { - if (!jwk.alg) { - throw new TypeError('"alg" argument is required when "jwk.alg" is not present') - } - - const { algorithm, keyUsages } = subtleMapping(jwk) - const rest: [RsaHashedImportParams | EcKeyAlgorithm | Algorithm, boolean, KeyUsage[]] = [ - algorithm, - jwk.ext ?? false, - jwk.key_ops ?? keyUsages, - ] - - if (algorithm.name === 'PBKDF2') { - return crypto.subtle.importKey('raw', base64url(jwk.k!), ...rest) - } - - const keyData: JWK = { ...jwk } - delete keyData.alg - delete keyData.use - try { - return await crypto.subtle.importKey('jwk', keyData, ...rest) - } catch (err) { - if ( - algorithm.name === 'Ed25519' && - (err)?.name === 'NotSupportedError' && - isCloudflareWorkers() - ) { - rest[0] = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } - return await crypto.subtle.importKey('jwk', keyData, ...rest) - } - throw err - } -} -export default parse diff --git a/dist/deno/runtime/key_to_jwk.ts b/dist/deno/runtime/key_to_jwk.ts deleted file mode 100644 index c279b618cc..0000000000 --- a/dist/deno/runtime/key_to_jwk.ts +++ /dev/null @@ -1,25 +0,0 @@ -import crypto, { isCryptoKey } from './webcrypto.ts' -import type { JWKExportFunction } from './interfaces.d.ts' -import type { JWK } from '../types.d.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { encode as base64url } from './base64url.ts' -import { types } from './is_key_like.ts' - -const keyToJWK: JWKExportFunction = async (key: unknown): Promise => { - if (key instanceof Uint8Array) { - return { - kty: 'oct', - k: base64url(key), - } - } - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) - } - if (!key.extractable) { - throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK') - } - const { ext, key_ops, alg, use, ...jwk } = await crypto.subtle.exportKey('jwk', key) - - return jwk -} -export default keyToJWK diff --git a/dist/deno/runtime/pbes2kw.ts b/dist/deno/runtime/pbes2kw.ts deleted file mode 100644 index 03976bdcc7..0000000000 --- a/dist/deno/runtime/pbes2kw.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { Pbes2KWDecryptFunction, Pbes2KWEncryptFunction } from './interfaces.d.ts' -import random from './random.ts' -import { p2s as concatSalt } from '../lib/buffer_utils.ts' -import { encode as base64url } from './base64url.ts' -import { wrap, unwrap } from './aeskw.ts' -import checkP2s from '../lib/check_p2s.ts' -import crypto, { isCryptoKey } from './webcrypto.ts' -import { checkEncCryptoKey } from '../lib/crypto_key.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { types } from './is_key_like.ts' - -function getCryptoKey(key: unknown, alg: string) { - if (key instanceof Uint8Array) { - return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']) - } - - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey') - return key - } - - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) -} - -async function deriveKey(p2s: Uint8Array, alg: string, p2c: number, key: unknown) { - checkP2s(p2s) - - const salt = concatSalt(alg, p2s) - const keylen = parseInt(alg.slice(13, 16), 10) - const subtleAlg = { - hash: `SHA-${alg.slice(8, 11)}`, - iterations: p2c, - name: 'PBKDF2', - salt, - } - const wrapAlg = { - length: keylen, - name: 'AES-KW', - } - - const cryptoKey = await getCryptoKey(key, alg) - - if (cryptoKey.usages.includes('deriveBits')) { - return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen)) - } - - if (cryptoKey.usages.includes('deriveKey')) { - return crypto.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ['wrapKey', 'unwrapKey']) - } - - throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"') -} - -export const encrypt: Pbes2KWEncryptFunction = async ( - alg: string, - key: unknown, - cek: Uint8Array, - p2c: number = 2048, - p2s: Uint8Array = random(new Uint8Array(16)), -) => { - const derived = await deriveKey(p2s, alg, p2c, key) - - const encryptedKey = await wrap(alg.slice(-6), derived, cek) - - return { encryptedKey, p2c, p2s: base64url(p2s) } -} - -export const decrypt: Pbes2KWDecryptFunction = async ( - alg: string, - key: unknown, - encryptedKey: Uint8Array, - p2c: number, - p2s: Uint8Array, -) => { - const derived = await deriveKey(p2s, alg, p2c, key) - - return unwrap(alg.slice(-6), derived, encryptedKey) -} diff --git a/dist/deno/runtime/random.ts b/dist/deno/runtime/random.ts deleted file mode 100644 index b885796ffb..0000000000 --- a/dist/deno/runtime/random.ts +++ /dev/null @@ -1,3 +0,0 @@ -import crypto from './webcrypto.ts' - -export default crypto.getRandomValues.bind(crypto) diff --git a/dist/deno/runtime/rsaes.ts b/dist/deno/runtime/rsaes.ts deleted file mode 100644 index e5e4bd514e..0000000000 --- a/dist/deno/runtime/rsaes.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { RsaEsDecryptFunction, RsaEsEncryptFunction } from './interfaces.d.ts' -import subtleAlgorithm from './subtle_rsaes.ts' -import bogusWebCrypto from './bogus.ts' -import crypto, { isCryptoKey } from './webcrypto.ts' -import { checkEncCryptoKey } from '../lib/crypto_key.ts' -import checkKeyLength from './check_key_length.ts' -import invalidKeyInput from '../lib/invalid_key_input.ts' -import { types } from './is_key_like.ts' - -export const encrypt: RsaEsEncryptFunction = async (alg: string, key: unknown, cek: Uint8Array) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)) - } - checkEncCryptoKey(key, alg, 'encrypt', 'wrapKey') - checkKeyLength(alg, key) - - if (key.usages.includes('encrypt')) { - return new Uint8Array(await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek)) - } - - if (key.usages.includes('wrapKey')) { - // we're importing the cek to end up with CryptoKey instance that can be wrapped, the algorithm used is irrelevant - const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto) - return new Uint8Array( - await crypto.subtle.wrapKey('raw', cryptoKeyCek, key, subtleAlgorithm(alg)), - ) - } - - throw new TypeError( - 'RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation', - ) -} - -export const decrypt: RsaEsDecryptFunction = async ( - alg: string, - key: unknown, - encryptedKey: Uint8Array, -) => { - if (!isCryptoKey(key)) { - throw new TypeError(invalidKeyInput(key, ...types)) - } - checkEncCryptoKey(key, alg, 'decrypt', 'unwrapKey') - checkKeyLength(alg, key) - - if (key.usages.includes('decrypt')) { - return new Uint8Array(await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey)) - } - - if (key.usages.includes('unwrapKey')) { - const cryptoKeyCek = await crypto.subtle.unwrapKey( - 'raw', - encryptedKey, - key, - subtleAlgorithm(alg), - ...bogusWebCrypto, - ) - - return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)) - } - - throw new TypeError( - 'RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation', - ) -} diff --git a/dist/deno/runtime/sign.ts b/dist/deno/runtime/sign.ts deleted file mode 100644 index 8a0c5af1b6..0000000000 --- a/dist/deno/runtime/sign.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { SignFunction } from './interfaces.d.ts' -import subtleAlgorithm from './subtle_dsa.ts' -import crypto from './webcrypto.ts' -import checkKeyLength from './check_key_length.ts' -import getSignKey from './get_sign_verify_key.ts' - -const sign: SignFunction = async (alg, key: unknown, data) => { - const cryptoKey = await getSignKey(alg, key, 'sign') - checkKeyLength(alg, cryptoKey) - const signature = await crypto.subtle.sign( - subtleAlgorithm(alg, cryptoKey.algorithm), - cryptoKey, - data, - ) - return new Uint8Array(signature) -} - -export default sign diff --git a/dist/deno/runtime/subtle_dsa.ts b/dist/deno/runtime/subtle_dsa.ts deleted file mode 100644 index db40dc693e..0000000000 --- a/dist/deno/runtime/subtle_dsa.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { isCloudflareWorkers } from './env.ts' -import { JOSENotSupported } from '../util/errors.ts' - -export default function subtleDsa(alg: string, algorithm: KeyAlgorithm | EcKeyAlgorithm) { - const hash = `SHA-${alg.slice(-3)}` - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': - return { hash, name: 'HMAC' } - case 'PS256': - case 'PS384': - case 'PS512': - // @ts-expect-error - return { hash, name: 'RSA-PSS', saltLength: alg.slice(-3) >> 3 } - case 'RS256': - case 'RS384': - case 'RS512': - return { hash, name: 'RSASSA-PKCS1-v1_5' } - case 'ES256': - case 'ES384': - case 'ES512': - return { hash, name: 'ECDSA', namedCurve: (algorithm).namedCurve } - case 'EdDSA': - if (isCloudflareWorkers() && algorithm.name === 'NODE-ED25519') { - return { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } - } - - return { name: algorithm.name } - default: - throw new JOSENotSupported( - `alg ${alg} is not supported either by JOSE or your javascript runtime`, - ) - } -} diff --git a/dist/deno/runtime/subtle_rsaes.ts b/dist/deno/runtime/subtle_rsaes.ts deleted file mode 100644 index 16fb3d3c59..0000000000 --- a/dist/deno/runtime/subtle_rsaes.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { JOSENotSupported } from '../util/errors.ts' - -export default function subtleRsaEs(alg: string) { - switch (alg) { - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - return 'RSA-OAEP' - default: - throw new JOSENotSupported( - `alg ${alg} is not supported either by JOSE or your javascript runtime`, - ) - } -} diff --git a/dist/deno/runtime/timing_safe_equal.ts b/dist/deno/runtime/timing_safe_equal.ts deleted file mode 100644 index 53bc719686..0000000000 --- a/dist/deno/runtime/timing_safe_equal.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { TimingSafeEqual } from './interfaces.d.ts' - -const timingSafeEqual: TimingSafeEqual = (a, b) => { - if (!(a instanceof Uint8Array)) { - throw new TypeError('First argument must be a buffer') - } - if (!(b instanceof Uint8Array)) { - throw new TypeError('Second argument must be a buffer') - } - if (a.length !== b.length) { - throw new TypeError('Input buffers must have the same length') - } - - const len = a.length - let out = 0 - let i = -1 - while (++i < len) { - out |= a[i] ^ b[i] - } - return out === 0 -} - -export default timingSafeEqual diff --git a/dist/deno/runtime/verify.ts b/dist/deno/runtime/verify.ts deleted file mode 100644 index c904d9422e..0000000000 --- a/dist/deno/runtime/verify.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { VerifyFunction } from './interfaces.d.ts' -import subtleAlgorithm from './subtle_dsa.ts' -import crypto from './webcrypto.ts' -import checkKeyLength from './check_key_length.ts' -import getVerifyKey from './get_sign_verify_key.ts' - -const verify: VerifyFunction = async (alg, key: unknown, signature, data) => { - const cryptoKey = await getVerifyKey(alg, key, 'verify') - checkKeyLength(alg, cryptoKey) - const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm) - try { - return await crypto.subtle.verify(algorithm, cryptoKey, signature, data) - } catch { - return false - } -} - -export default verify diff --git a/dist/deno/runtime/webcrypto.ts b/dist/deno/runtime/webcrypto.ts deleted file mode 100644 index fd524e1fe4..0000000000 --- a/dist/deno/runtime/webcrypto.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default crypto - -export const isCryptoKey = (key: unknown): key is CryptoKey => key instanceof CryptoKey diff --git a/dist/deno/runtime/zlib.ts b/dist/deno/runtime/zlib.ts deleted file mode 100644 index 653d1b419f..0000000000 --- a/dist/deno/runtime/zlib.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { JOSENotSupported } from '../util/errors.ts' -import type { InflateFunction, DeflateFunction } from '../types.d.ts' - -export const inflate: InflateFunction = async () => { - throw new JOSENotSupported( - 'JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.', - ) -} -export const deflate: DeflateFunction = async () => { - throw new JOSENotSupported( - 'JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.', - ) -} diff --git a/dist/deno/types.d.ts b/dist/deno/types.d.ts deleted file mode 100644 index 3310685b47..0000000000 --- a/dist/deno/types.d.ts +++ /dev/null @@ -1,628 +0,0 @@ -/** - * KeyLike are runtime-specific classes representing asymmetric keys or symmetric secrets. These are - * instances of [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) and - * additionally [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) in Node.js runtime. - * [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) - * instances are also accepted as symmetric secret representation only. - * - * [Key Import Functions](../modules/key_import.md#readme) can be used to import PEM, or JWK - * formatted asymmetric keys and certificates to these runtime-specific representations. - * - * In Node.js the [Buffer](https://nodejs.org/api/buffer.html#buffer) class is a subclass of - * Uint8Array and so Buffer can be provided for symmetric secrets as well. - * - * [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) is a representation of a - * key/secret available in the Node.js runtime. In addition to the import functions of this library - * you may use the runtime APIs - * [crypto.createPublicKey](https://nodejs.org/api/crypto.html#cryptocreatepublickeykey), - * [crypto.createPrivateKey](https://nodejs.org/api/crypto.html#cryptocreateprivatekeykey), and - * [crypto.createSecretKey](https://nodejs.org/api/crypto.html#cryptocreatesecretkeykey-encoding) to - * obtain a KeyObject from your existing key material. - * - * [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) is a representation of a - * key/secret available in the Browser and Web-interoperable runtimes. In addition to the import - * functions of this library you may use the - * [SubtleCrypto.importKey](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) - * API to obtain a CryptoKey from your existing key material. - * - * @example Import a PEM-encoded SPKI Public Key - * - * ```js - * const algorithm = 'ES256' - * const spki = `-----BEGIN PUBLIC KEY----- - * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM - * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== - * -----END PUBLIC KEY-----` - * const ecPublicKey = await jose.importSPKI(spki, algorithm) - * ``` - * - * @example Import SPKI from an X.509 Certificate - * - * ```js - * const algorithm = 'ES256' - * const x509 = `-----BEGIN CERTIFICATE----- - * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np - * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw - * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN - * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI - * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 - * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA - * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh - * v+A1QWZMuTWqYt+uh/YSRNDn - * -----END CERTIFICATE-----` - * const ecPublicKey = await jose.importX509(x509, algorithm) - * ``` - * - * @example Import a PEM-encoded PKCS8 Private Key - * - * ```js - * const algorithm = 'ES256' - * const pkcs8 = `-----BEGIN PRIVATE KEY----- - * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN - * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg - * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa - * -----END PRIVATE KEY-----` - * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) - * ``` - * - * @example Import a JSON Web Key (JWK) - * - * ```js - * const ecPublicKey = await jose.importJWK( - * { - * crv: 'P-256', - * kty: 'EC', - * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', - * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', - * }, - * 'ES256', - * ) - * - * const rsaPublicKey = await jose.importJWK( - * { - * kty: 'RSA', - * e: 'AQAB', - * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', - * }, - * 'PS256', - * ) - * ``` - */ -export type KeyLike = { type: string } - -/** - * JSON Web Key ([JWK](https://www.rfc-editor.org/rfc/rfc7517)). "RSA", "EC", "OKP", and "oct" key - * types are supported. - */ -export interface JWK { - /** JWK "alg" (Algorithm) Parameter. */ - alg?: string - crv?: string - d?: string - dp?: string - dq?: string - e?: string - /** JWK "ext" (Extractable) Parameter. */ - ext?: boolean - k?: string - /** JWK "key_ops" (Key Operations) Parameter. */ - key_ops?: string[] - /** JWK "kid" (Key ID) Parameter. */ - kid?: string - /** JWK "kty" (Key Type) Parameter. */ - kty?: string - n?: string - oth?: Array<{ - d?: string - r?: string - t?: string - }> - p?: string - q?: string - qi?: string - /** JWK "use" (Public Key Use) Parameter. */ - use?: string - x?: string - y?: string - /** JWK "x5c" (X.509 Certificate Chain) Parameter. */ - x5c?: string[] - /** JWK "x5t" (X.509 Certificate SHA-1 Thumbprint) Parameter. */ - x5t?: string - /** "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Parameter. */ - 'x5t#S256'?: string - /** JWK "x5u" (X.509 URL) Parameter. */ - x5u?: string - - [propName: string]: unknown -} - -/** - * Generic Interface for consuming operations dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * If you cannot match a key suitable for the token, throw an error instead. - * - * @param protectedHeader JWE or JWS Protected Header. - * @param token The consumed JWE or JWS token. - */ -export interface GetKeyFunction { - (protectedHeader: T, token: T2): Promise | KeyLike | Uint8Array -} - -/** - * Flattened JWS definition for verify function inputs, allows payload as Uint8Array for detached - * signature validation. - */ -export interface FlattenedJWSInput { - /** - * The "header" member MUST be present and contain the value JWS Unprotected Header when the JWS - * Unprotected Header value is non- empty; otherwise, it MUST be absent. This value is represented - * as an unencoded JSON object, rather than as a string. These Header Parameter values are not - * integrity protected. - */ - header?: JWSHeaderParameters - - /** - * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 - * "b64": false is used the value passed may also be a Uint8Array. - */ - payload: string | Uint8Array - - /** - * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWS Protected - * Header)) when the JWS Protected Header value is non-empty; otherwise, it MUST be absent. These - * Header Parameter values are integrity protected. - */ - protected?: string - - /** The "signature" member MUST be present and contain the value BASE64URL(JWS Signature). */ - signature: string -} - -/** - * General JWS definition for verify function inputs, allows payload as Uint8Array for detached - * signature validation. - */ -export interface GeneralJWSInput { - /** - * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 - * "b64": false is used the value passed may also be a Uint8Array. - */ - payload: string | Uint8Array - - /** - * The "signatures" member value MUST be an array of JSON objects. Each object represents a - * signature or MAC over the JWS Payload and the JWS Protected Header. - */ - signatures: Omit[] -} - -/** - * Flattened JWS definition. Payload is returned as an empty string when JWS Unencoded Payload - * Option [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. - */ -export interface FlattenedJWS extends Partial { - payload: string - signature: string -} - -/** - * General JWS definition. Payload is returned as an empty string when JWS Unencoded Payload Option - * [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. - */ -export interface GeneralJWS { - payload: string - signatures: Omit[] -} - -export interface JoseHeaderParameters { - /** "kid" (Key ID) Header Parameter. */ - kid?: string - - /** "x5t" (X.509 Certificate SHA-1 Thumbprint) Header Parameter. */ - x5t?: string - - /** "x5c" (X.509 Certificate Chain) Header Parameter. */ - x5c?: string[] - - /** "x5u" (X.509 URL) Header Parameter. */ - x5u?: string - - /** "jku" (JWK Set URL) Header Parameter. */ - jku?: string - - /** "jwk" (JSON Web Key) Header Parameter. */ - jwk?: Pick - - /** "typ" (Type) Header Parameter. */ - typ?: string - - /** "cty" (Content Type) Header Parameter. */ - cty?: string -} - -/** Recognized JWS Header Parameters, any other Header Members may also be present. */ -export interface JWSHeaderParameters extends JoseHeaderParameters { - /** JWS "alg" (Algorithm) Header Parameter. */ - alg?: string - - /** - * This JWS Extension Header Parameter modifies the JWS Payload representation and the JWS Signing - * Input computation as per [RFC7797](https://www.rfc-editor.org/rfc/rfc7797). - */ - b64?: boolean - - /** JWS "crit" (Critical) Header Parameter. */ - crit?: string[] - - /** Any other JWS Header member. */ - [propName: string]: unknown -} - -/** Recognized JWE Key Management-related Header Parameters. */ -export interface JWEKeyManagementHeaderParameters { - apu?: Uint8Array - apv?: Uint8Array - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - p2c?: number - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - p2s?: Uint8Array - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - iv?: Uint8Array - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - epk?: KeyLike -} - -/** Flattened JWE definition. */ -export interface FlattenedJWE { - /** - * The "aad" member MUST be present and contain the value BASE64URL(JWE AAD)) when the JWE AAD - * value is non-empty; otherwise, it MUST be absent. A JWE AAD value can be included to supply a - * base64url-encoded value to be integrity protected but not encrypted. - */ - aad?: string - - /** The "ciphertext" member MUST be present and contain the value BASE64URL(JWE Ciphertext). */ - ciphertext: string - - /** - * The "encrypted_key" member MUST be present and contain the value BASE64URL(JWE Encrypted Key) - * when the JWE Encrypted Key value is non-empty; otherwise, it MUST be absent. - */ - encrypted_key?: string - - /** - * The "header" member MUST be present and contain the value JWE Per- Recipient Unprotected Header - * when the JWE Per-Recipient Unprotected Header value is non-empty; otherwise, it MUST be absent. - * This value is represented as an unencoded JSON object, rather than as a string. These Header - * Parameter values are not integrity protected. - */ - header?: JWEHeaderParameters - - /** - * The "iv" member MUST be present and contain the value BASE64URL(JWE Initialization Vector) when - * the JWE Initialization Vector value is non-empty; otherwise, it MUST be absent. - */ - iv: string - - /** - * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWE Protected - * Header)) when the JWE Protected Header value is non-empty; otherwise, it MUST be absent. These - * Header Parameter values are integrity protected. - */ - protected?: string - - /** - * The "tag" member MUST be present and contain the value BASE64URL(JWE Authentication Tag) when - * the JWE Authentication Tag value is non-empty; otherwise, it MUST be absent. - */ - tag: string - - /** - * The "unprotected" member MUST be present and contain the value JWE Shared Unprotected Header - * when the JWE Shared Unprotected Header value is non-empty; otherwise, it MUST be absent. This - * value is represented as an unencoded JSON object, rather than as a string. These Header - * Parameter values are not integrity protected. - */ - unprotected?: JWEHeaderParameters -} - -export interface GeneralJWE extends Omit { - recipients: Pick[] -} - -/** Recognized JWE Header Parameters, any other Header members may also be present. */ -export interface JWEHeaderParameters extends JoseHeaderParameters { - /** JWE "alg" (Algorithm) Header Parameter. */ - alg?: string - - /** JWE "enc" (Encryption Algorithm) Header Parameter. */ - enc?: string - - /** JWE "crit" (Critical) Header Parameter. */ - crit?: string[] - - /** JWE "zip" (Compression Algorithm) Header Parameter. */ - zip?: string - - /** Any other JWE Header member. */ - [propName: string]: unknown -} - -/** Shared Interface with a "crit" property for all sign, verify, encrypt and decrypt operations. */ -export interface CritOption { - /** - * An object with keys representing recognized "crit" (Critical) Header Parameter names. The value - * for those is either `true` or `false`. `true` when the Header Parameter MUST be integrity - * protected, `false` when it's irrelevant. - * - * This makes the "Extension Header Parameter "..." is not recognized" error go away. - * - * Use this when a given JWS/JWT/JWE profile requires the use of proprietary non-registered "crit" - * (Critical) Header Parameters. This will only make sure the Header Parameter is syntactically - * correct when provided and that it is optionally integrity protected. It will not process the - * Header Parameter in any way or reject the operation if it is missing. You MUST still verify the - * Header Parameter was present and process it according to the profile's validation steps after - * the operation succeeds. - * - * The JWS extension Header Parameter `b64` is always recognized and processed properly. No other - * registered Header Parameters that need this kind of default built-in treatment are currently - * available. - */ - crit?: { - [propName: string]: boolean - } -} - -/** JWE Decryption options. */ -export interface DecryptOptions extends CritOption { - /** A list of accepted JWE "alg" (Algorithm) Header Parameter values. */ - keyManagementAlgorithms?: string[] - - /** - * A list of accepted JWE "enc" (Encryption Algorithm) Header Parameter values. By default all - * "enc" (Encryption Algorithm) values applicable for the used key/secret are allowed. - */ - contentEncryptionAlgorithms?: string[] - - /** - * In a browser runtime you have to provide an implementation for Inflate Raw when you expect JWEs - * with compressed plaintext. - */ - inflateRaw?: InflateFunction - - /** - * (PBES2 Key Management Algorithms only) Maximum allowed "p2c" (PBES2 Count) Header Parameter - * value. The PBKDF2 iteration count defines the algorithm's computational expense. By default - * this value is set to 10000. - */ - maxPBES2Count?: number -} - -/** JWE Deflate option. */ -export interface DeflateOption { - /** - * In a browser runtime you have to provide an implementation for Deflate Raw when you will be - * producing JWEs with compressed plaintext. - */ - deflateRaw?: DeflateFunction -} - -/** JWE Encryption options. */ -export interface EncryptOptions extends CritOption, DeflateOption {} - -/** JWT Claims Set verification options. */ -export interface JWTClaimVerificationOptions { - /** Expected JWT "aud" (Audience) Claim value(s). */ - audience?: string | string[] - - /** - * Expected clock tolerance - * - * - In seconds when number (e.g. 5) - * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). - */ - clockTolerance?: string | number - - /** Expected JWT "iss" (Issuer) Claim value(s). */ - issuer?: string | string[] - - /** - * Maximum time elapsed (in seconds) from the JWT "iat" (Issued At) Claim value. - * - * - In seconds when number (e.g. 5) - * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). - */ - maxTokenAge?: string | number - - /** Expected JWT "sub" (Subject) Claim value. */ - subject?: string - - /** Expected JWT "typ" (Type) Header Parameter value. */ - typ?: string - - /** Date to use when comparing NumericDate claims, defaults to `new Date()`. */ - currentDate?: Date -} - -/** JWS Verification options. */ -export interface VerifyOptions extends CritOption { - /** - * A list of accepted JWS "alg" (Algorithm) Header Parameter values. By default all "alg" - * (Algorithm) values applicable for the used key/secret are allowed. Note: "none" is never - * accepted. - */ - algorithms?: string[] -} - -/** JWS Signing options. */ -export interface SignOptions extends CritOption {} - -/** Recognized JWT Claims Set members, any other members may also be present. */ -export interface JWTPayload { - /** - * JWT Issuer - * - * @see [RFC7519#section-4.1.1](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1) - */ - iss?: string - - /** - * JWT Subject - * - * @see [RFC7519#section-4.1.2](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2) - */ - sub?: string - - /** JWT Audience [RFC7519#section-4.1.3](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3). */ - aud?: string | string[] - - /** - * JWT ID - * - * @see [RFC7519#section-4.1.7](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7) - */ - jti?: string - - /** - * JWT Not Before - * - * @see [RFC7519#section-4.1.5](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5) - */ - nbf?: number - - /** - * JWT Expiration Time - * - * @see [RFC7519#section-4.1.4](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4) - */ - exp?: number - - /** - * JWT Issued At - * - * @see [RFC7519#section-4.1.6](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6) - */ - iat?: number - - /** Any other JWT Claim Set member. */ - [propName: string]: unknown -} - -/** - * Deflate Raw implementation, e.g. promisified - * [zlib.deflateRaw](https://nodejs.org/api/zlib.html#zlibdeflaterawbuffer-options-callback). - */ -export interface DeflateFunction { - (input: Uint8Array): Promise -} - -/** - * Inflate Raw implementation, e.g. promisified - * [zlib.inflateRaw](https://nodejs.org/api/zlib.html#zlibinflaterawbuffer-options-callback). - */ -export interface InflateFunction { - (input: Uint8Array): Promise -} - -export interface FlattenedDecryptResult { - /** JWE AAD. */ - additionalAuthenticatedData?: Uint8Array - - /** Plaintext. */ - plaintext: Uint8Array - - /** JWE Protected Header. */ - protectedHeader?: JWEHeaderParameters - - /** JWE Shared Unprotected Header. */ - sharedUnprotectedHeader?: JWEHeaderParameters - - /** JWE Per-Recipient Unprotected Header. */ - unprotectedHeader?: JWEHeaderParameters -} - -export interface GeneralDecryptResult extends FlattenedDecryptResult {} - -export interface CompactDecryptResult { - /** Plaintext. */ - plaintext: Uint8Array - - /** JWE Protected Header. */ - protectedHeader: CompactJWEHeaderParameters -} - -export interface FlattenedVerifyResult { - /** JWS Payload. */ - payload: Uint8Array - - /** JWS Protected Header. */ - protectedHeader?: JWSHeaderParameters - - /** JWS Unprotected Header. */ - unprotectedHeader?: JWSHeaderParameters -} - -export interface GeneralVerifyResult extends FlattenedVerifyResult {} - -export interface CompactVerifyResult { - /** JWS Payload. */ - payload: Uint8Array - - /** JWS Protected Header. */ - protectedHeader: CompactJWSHeaderParameters -} - -export interface JWTVerifyResult { - /** JWT Claims Set. */ - payload: JWTPayload - - /** JWS Protected Header. */ - protectedHeader: JWTHeaderParameters -} - -export interface JWTDecryptResult { - /** JWT Claims Set. */ - payload: JWTPayload - - /** JWE Protected Header. */ - protectedHeader: CompactJWEHeaderParameters -} - -export interface ResolvedKey { - /** Key resolved from the key resolver function. */ - key: KeyLike | Uint8Array -} - -/** Recognized Compact JWS Header Parameters, any other Header Members may also be present. */ -export interface CompactJWSHeaderParameters extends JWSHeaderParameters { - alg: string -} - -/** Recognized Signed JWT Header Parameters, any other Header Members may also be present. */ -export interface JWTHeaderParameters extends CompactJWSHeaderParameters { - b64?: true -} - -/** Recognized Compact JWE Header Parameters, any other Header Members may also be present. */ -export interface CompactJWEHeaderParameters extends JWEHeaderParameters { - alg: string - enc: string -} - -/** JSON Web Key Set */ -export interface JSONWebKeySet { - keys: JWK[] -} diff --git a/dist/deno/util/base64url.ts b/dist/deno/util/base64url.ts deleted file mode 100644 index f3d76163fc..0000000000 --- a/dist/deno/util/base64url.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as base64url from '../runtime/base64url.ts' - -/** - * Utility function to encode a string or Uint8Array as a base64url string. - * - * @param input Value that will be base64url-encoded. - */ -interface Base64UrlEncode { - (input: Uint8Array | string): string -} -/** - * Utility function to decode a base64url encoded string. - * - * @param input Value that will be base64url-decoded. - */ -interface Base64UrlDecode { - (input: Uint8Array | string): Uint8Array -} - -export const encode: Base64UrlEncode = base64url.encode -export const decode: Base64UrlDecode = base64url.decode diff --git a/dist/deno/util/decode_jwt.ts b/dist/deno/util/decode_jwt.ts deleted file mode 100644 index f5eb8cb13f..0000000000 --- a/dist/deno/util/decode_jwt.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { decode as base64url } from './base64url.ts' -import { decoder } from '../lib/buffer_utils.ts' -import isObject from '../lib/is_object.ts' -import type { JWTPayload } from '../types.d.ts' -import { JWTInvalid } from './errors.ts' - -/** - * Decodes a signed JSON Web Token payload. This does not validate the JWT Claims Set types or - * values. This does not validate the JWS Signature. For a proper Signed JWT Claims Set validation - * and JWS signature verification use `jose.jwtVerify()`. For an encrypted JWT Claims Set validation - * and JWE decryption use `jose.jwtDecrypt()`. - * - * @example Usage - * - * ```js - * const claims = jose.decodeJwt(token) - * console.log(claims) - * ``` - * - * @param jwt JWT token in compact JWS serialization. - */ -export function decodeJwt(jwt: string) { - if (typeof jwt !== 'string') - throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string') - - const { 1: payload, length } = jwt.split('.') - - if (length === 5) throw new JWTInvalid('Only JWTs using Compact JWS serialization can be decoded') - if (length !== 3) throw new JWTInvalid('Invalid JWT') - if (!payload) throw new JWTInvalid('JWTs must contain a payload') - - let decoded: Uint8Array - try { - decoded = base64url(payload) - } catch { - throw new JWTInvalid('Failed to parse the base64url encoded payload') - } - - let result: unknown - try { - result = JSON.parse(decoder.decode(decoded)) - } catch { - throw new JWTInvalid('Failed to parse the decoded payload as JSON') - } - - if (!isObject(result)) throw new JWTInvalid('Invalid JWT Claims Set') - - return result -} diff --git a/dist/deno/util/decode_protected_header.ts b/dist/deno/util/decode_protected_header.ts deleted file mode 100644 index 7e8f91b0fe..0000000000 --- a/dist/deno/util/decode_protected_header.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { decode as base64url } from './base64url.ts' -import { decoder } from '../lib/buffer_utils.ts' -import isObject from '../lib/is_object.ts' -import type { JWSHeaderParameters, JWEHeaderParameters } from '../types.d.ts' - -export type ProtectedHeaderParameters = JWSHeaderParameters & JWEHeaderParameters - -/** - * Decodes the Protected Header of a JWE/JWS/JWT token utilizing any JOSE serialization. - * - * @example Usage - * - * ```js - * const protectedHeader = jose.decodeProtectedHeader(token) - * console.log(protectedHeader) - * ``` - * - * @param token JWE/JWS/JWT token in any JOSE serialization. - */ -export function decodeProtectedHeader(token: string | object) { - let protectedB64u!: string - - if (typeof token === 'string') { - const parts = token.split('.') - if (parts.length === 3 || parts.length === 5) { - ;[protectedB64u] = parts - } - } else if (typeof token === 'object' && token) { - if ('protected' in token) { - protectedB64u = (<{ protected: string }>token).protected - } else { - throw new TypeError('Token does not contain a Protected Header') - } - } - - try { - if (typeof protectedB64u !== 'string' || !protectedB64u) { - throw new Error() - } - const result = JSON.parse(decoder.decode(base64url(protectedB64u!))) - if (!isObject(result)) { - throw new Error() - } - return result - } catch { - throw new TypeError('Invalid Token or Protected Header formatting') - } -} diff --git a/dist/deno/util/errors.ts b/dist/deno/util/errors.ts deleted file mode 100644 index 7eedb68807..0000000000 --- a/dist/deno/util/errors.ts +++ /dev/null @@ -1,185 +0,0 @@ -import type { KeyLike } from '../types.d.ts' - -/** A generic Error subclass that all other specific JOSE Error subclasses inherit from. */ -export class JOSEError extends Error { - /** A unique error code for the particular error subclass. */ - static get code(): string { - return 'ERR_JOSE_GENERIC' - } - - /** A unique error code for the particular error subclass. */ - code: string = 'ERR_JOSE_GENERIC' - - constructor(message?: string) { - super(message) - this.name = this.constructor.name - // @ts-ignore - Error.captureStackTrace?.(this, this.constructor) - } -} - -/** An error subclass thrown when a JWT Claim Set member validation fails. */ -export class JWTClaimValidationFailed extends JOSEError { - static get code(): 'ERR_JWT_CLAIM_VALIDATION_FAILED' { - return 'ERR_JWT_CLAIM_VALIDATION_FAILED' - } - - code = 'ERR_JWT_CLAIM_VALIDATION_FAILED' - - /** The Claim for which the validation failed. */ - claim: string - - /** Reason code for the validation failure. */ - reason: string - - constructor(message: string, claim = 'unspecified', reason = 'unspecified') { - super(message) - this.claim = claim - this.reason = reason - } -} - -/** An error subclass thrown when a JWT is expired. */ -export class JWTExpired extends JOSEError implements JWTClaimValidationFailed { - static get code(): 'ERR_JWT_EXPIRED' { - return 'ERR_JWT_EXPIRED' - } - - code = 'ERR_JWT_EXPIRED' - - /** The Claim for which the validation failed. */ - claim: string - - /** Reason code for the validation failure. */ - reason: string - - constructor(message: string, claim = 'unspecified', reason = 'unspecified') { - super(message) - this.claim = claim - this.reason = reason - } -} - -/** An error subclass thrown when a JOSE Algorithm is not allowed per developer preference. */ -export class JOSEAlgNotAllowed extends JOSEError { - static get code(): 'ERR_JOSE_ALG_NOT_ALLOWED' { - return 'ERR_JOSE_ALG_NOT_ALLOWED' - } - - code = 'ERR_JOSE_ALG_NOT_ALLOWED' -} - -/** - * An error subclass thrown when a particular feature or algorithm is not supported by this - * implementation or JOSE in general. - */ -export class JOSENotSupported extends JOSEError { - static get code(): 'ERR_JOSE_NOT_SUPPORTED' { - return 'ERR_JOSE_NOT_SUPPORTED' - } - - code = 'ERR_JOSE_NOT_SUPPORTED' -} - -/** An error subclass thrown when a JWE ciphertext decryption fails. */ -export class JWEDecryptionFailed extends JOSEError { - static get code(): 'ERR_JWE_DECRYPTION_FAILED' { - return 'ERR_JWE_DECRYPTION_FAILED' - } - - code = 'ERR_JWE_DECRYPTION_FAILED' - - message = 'decryption operation failed' -} - -/** An error subclass thrown when a JWE is invalid. */ -export class JWEInvalid extends JOSEError { - static get code(): 'ERR_JWE_INVALID' { - return 'ERR_JWE_INVALID' - } - - code = 'ERR_JWE_INVALID' -} - -/** An error subclass thrown when a JWS is invalid. */ -export class JWSInvalid extends JOSEError { - static get code(): 'ERR_JWS_INVALID' { - return 'ERR_JWS_INVALID' - } - - code = 'ERR_JWS_INVALID' -} - -/** An error subclass thrown when a JWT is invalid. */ -export class JWTInvalid extends JOSEError { - static get code(): 'ERR_JWT_INVALID' { - return 'ERR_JWT_INVALID' - } - - code = 'ERR_JWT_INVALID' -} - -/** An error subclass thrown when a JWK is invalid. */ -export class JWKInvalid extends JOSEError { - static get code(): 'ERR_JWK_INVALID' { - return 'ERR_JWK_INVALID' - } - - code = 'ERR_JWK_INVALID' -} - -/** An error subclass thrown when a JWKS is invalid. */ -export class JWKSInvalid extends JOSEError { - static get code(): 'ERR_JWKS_INVALID' { - return 'ERR_JWKS_INVALID' - } - - code = 'ERR_JWKS_INVALID' -} - -/** An error subclass thrown when no keys match from a JWKS. */ -export class JWKSNoMatchingKey extends JOSEError { - static get code(): 'ERR_JWKS_NO_MATCHING_KEY' { - return 'ERR_JWKS_NO_MATCHING_KEY' - } - - code = 'ERR_JWKS_NO_MATCHING_KEY' - - message = 'no applicable key found in the JSON Web Key Set' -} - -/** An error subclass thrown when multiple keys match from a JWKS. */ -export class JWKSMultipleMatchingKeys extends JOSEError { - /** @ignore */ - [Symbol.asyncIterator]!: () => AsyncIterableIterator - - static get code(): 'ERR_JWKS_MULTIPLE_MATCHING_KEYS' { - return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS' - } - - code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS' - - message = 'multiple matching keys found in the JSON Web Key Set' -} - -/** Timeout was reached when retrieving the JWKS response. */ -export class JWKSTimeout extends JOSEError { - static get code(): 'ERR_JWKS_TIMEOUT' { - return 'ERR_JWKS_TIMEOUT' - } - - code = 'ERR_JWKS_TIMEOUT' - - message = 'request timed out' -} - -/** An error subclass thrown when JWS signature verification fails. */ -export class JWSSignatureVerificationFailed extends JOSEError { - static get code(): 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED' { - return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED' - } - - code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED' - - message = 'signature verification failed' -} diff --git a/dist/node/cjs/index.js b/dist/node/cjs/index.js deleted file mode 100644 index 5f41840500..0000000000 --- a/dist/node/cjs/index.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.base64url = exports.generateSecret = exports.generateKeyPair = exports.errors = exports.decodeJwt = exports.decodeProtectedHeader = exports.importJWK = exports.importX509 = exports.importPKCS8 = exports.importSPKI = exports.exportJWK = exports.exportSPKI = exports.exportPKCS8 = exports.UnsecuredJWT = exports.createRemoteJWKSet = exports.createLocalJWKSet = exports.EmbeddedJWK = exports.calculateJwkThumbprintUri = exports.calculateJwkThumbprint = exports.EncryptJWT = exports.SignJWT = exports.GeneralSign = exports.FlattenedSign = exports.CompactSign = exports.FlattenedEncrypt = exports.CompactEncrypt = exports.jwtDecrypt = exports.jwtVerify = exports.generalVerify = exports.flattenedVerify = exports.compactVerify = exports.GeneralEncrypt = exports.generalDecrypt = exports.flattenedDecrypt = exports.compactDecrypt = void 0; -var decrypt_js_1 = require("./jwe/compact/decrypt.js"); -Object.defineProperty(exports, "compactDecrypt", { enumerable: true, get: function () { return decrypt_js_1.compactDecrypt; } }); -var decrypt_js_2 = require("./jwe/flattened/decrypt.js"); -Object.defineProperty(exports, "flattenedDecrypt", { enumerable: true, get: function () { return decrypt_js_2.flattenedDecrypt; } }); -var decrypt_js_3 = require("./jwe/general/decrypt.js"); -Object.defineProperty(exports, "generalDecrypt", { enumerable: true, get: function () { return decrypt_js_3.generalDecrypt; } }); -var encrypt_js_1 = require("./jwe/general/encrypt.js"); -Object.defineProperty(exports, "GeneralEncrypt", { enumerable: true, get: function () { return encrypt_js_1.GeneralEncrypt; } }); -var verify_js_1 = require("./jws/compact/verify.js"); -Object.defineProperty(exports, "compactVerify", { enumerable: true, get: function () { return verify_js_1.compactVerify; } }); -var verify_js_2 = require("./jws/flattened/verify.js"); -Object.defineProperty(exports, "flattenedVerify", { enumerable: true, get: function () { return verify_js_2.flattenedVerify; } }); -var verify_js_3 = require("./jws/general/verify.js"); -Object.defineProperty(exports, "generalVerify", { enumerable: true, get: function () { return verify_js_3.generalVerify; } }); -var verify_js_4 = require("./jwt/verify.js"); -Object.defineProperty(exports, "jwtVerify", { enumerable: true, get: function () { return verify_js_4.jwtVerify; } }); -var decrypt_js_4 = require("./jwt/decrypt.js"); -Object.defineProperty(exports, "jwtDecrypt", { enumerable: true, get: function () { return decrypt_js_4.jwtDecrypt; } }); -var encrypt_js_2 = require("./jwe/compact/encrypt.js"); -Object.defineProperty(exports, "CompactEncrypt", { enumerable: true, get: function () { return encrypt_js_2.CompactEncrypt; } }); -var encrypt_js_3 = require("./jwe/flattened/encrypt.js"); -Object.defineProperty(exports, "FlattenedEncrypt", { enumerable: true, get: function () { return encrypt_js_3.FlattenedEncrypt; } }); -var sign_js_1 = require("./jws/compact/sign.js"); -Object.defineProperty(exports, "CompactSign", { enumerable: true, get: function () { return sign_js_1.CompactSign; } }); -var sign_js_2 = require("./jws/flattened/sign.js"); -Object.defineProperty(exports, "FlattenedSign", { enumerable: true, get: function () { return sign_js_2.FlattenedSign; } }); -var sign_js_3 = require("./jws/general/sign.js"); -Object.defineProperty(exports, "GeneralSign", { enumerable: true, get: function () { return sign_js_3.GeneralSign; } }); -var sign_js_4 = require("./jwt/sign.js"); -Object.defineProperty(exports, "SignJWT", { enumerable: true, get: function () { return sign_js_4.SignJWT; } }); -var encrypt_js_4 = require("./jwt/encrypt.js"); -Object.defineProperty(exports, "EncryptJWT", { enumerable: true, get: function () { return encrypt_js_4.EncryptJWT; } }); -var thumbprint_js_1 = require("./jwk/thumbprint.js"); -Object.defineProperty(exports, "calculateJwkThumbprint", { enumerable: true, get: function () { return thumbprint_js_1.calculateJwkThumbprint; } }); -Object.defineProperty(exports, "calculateJwkThumbprintUri", { enumerable: true, get: function () { return thumbprint_js_1.calculateJwkThumbprintUri; } }); -var embedded_js_1 = require("./jwk/embedded.js"); -Object.defineProperty(exports, "EmbeddedJWK", { enumerable: true, get: function () { return embedded_js_1.EmbeddedJWK; } }); -var local_js_1 = require("./jwks/local.js"); -Object.defineProperty(exports, "createLocalJWKSet", { enumerable: true, get: function () { return local_js_1.createLocalJWKSet; } }); -var remote_js_1 = require("./jwks/remote.js"); -Object.defineProperty(exports, "createRemoteJWKSet", { enumerable: true, get: function () { return remote_js_1.createRemoteJWKSet; } }); -var unsecured_js_1 = require("./jwt/unsecured.js"); -Object.defineProperty(exports, "UnsecuredJWT", { enumerable: true, get: function () { return unsecured_js_1.UnsecuredJWT; } }); -var export_js_1 = require("./key/export.js"); -Object.defineProperty(exports, "exportPKCS8", { enumerable: true, get: function () { return export_js_1.exportPKCS8; } }); -Object.defineProperty(exports, "exportSPKI", { enumerable: true, get: function () { return export_js_1.exportSPKI; } }); -Object.defineProperty(exports, "exportJWK", { enumerable: true, get: function () { return export_js_1.exportJWK; } }); -var import_js_1 = require("./key/import.js"); -Object.defineProperty(exports, "importSPKI", { enumerable: true, get: function () { return import_js_1.importSPKI; } }); -Object.defineProperty(exports, "importPKCS8", { enumerable: true, get: function () { return import_js_1.importPKCS8; } }); -Object.defineProperty(exports, "importX509", { enumerable: true, get: function () { return import_js_1.importX509; } }); -Object.defineProperty(exports, "importJWK", { enumerable: true, get: function () { return import_js_1.importJWK; } }); -var decode_protected_header_js_1 = require("./util/decode_protected_header.js"); -Object.defineProperty(exports, "decodeProtectedHeader", { enumerable: true, get: function () { return decode_protected_header_js_1.decodeProtectedHeader; } }); -var decode_jwt_js_1 = require("./util/decode_jwt.js"); -Object.defineProperty(exports, "decodeJwt", { enumerable: true, get: function () { return decode_jwt_js_1.decodeJwt; } }); -exports.errors = require("./util/errors.js"); -var generate_key_pair_js_1 = require("./key/generate_key_pair.js"); -Object.defineProperty(exports, "generateKeyPair", { enumerable: true, get: function () { return generate_key_pair_js_1.generateKeyPair; } }); -var generate_secret_js_1 = require("./key/generate_secret.js"); -Object.defineProperty(exports, "generateSecret", { enumerable: true, get: function () { return generate_secret_js_1.generateSecret; } }); -exports.base64url = require("./util/base64url.js"); diff --git a/dist/node/cjs/jwe/compact/decrypt.js b/dist/node/cjs/jwe/compact/decrypt.js deleted file mode 100644 index 055b3c4564..0000000000 --- a/dist/node/cjs/jwe/compact/decrypt.js +++ /dev/null @@ -1,31 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.compactDecrypt = void 0; -const decrypt_js_1 = require("../flattened/decrypt.js"); -const errors_js_1 = require("../../util/errors.js"); -const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); -async function compactDecrypt(jwe, key, options) { - if (jwe instanceof Uint8Array) { - jwe = buffer_utils_js_1.decoder.decode(jwe); - } - if (typeof jwe !== 'string') { - throw new errors_js_1.JWEInvalid('Compact JWE must be a string or Uint8Array'); - } - const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.'); - if (length !== 5) { - throw new errors_js_1.JWEInvalid('Invalid Compact JWE'); - } - const decrypted = await (0, decrypt_js_1.flattenedDecrypt)({ - ciphertext, - iv: (iv || undefined), - protected: protectedHeader || undefined, - tag: (tag || undefined), - encrypted_key: encryptedKey || undefined, - }, key, options); - const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: decrypted.key }; - } - return result; -} -exports.compactDecrypt = compactDecrypt; diff --git a/dist/node/cjs/jwe/compact/encrypt.js b/dist/node/cjs/jwe/compact/encrypt.js deleted file mode 100644 index 949fbb6df7..0000000000 --- a/dist/node/cjs/jwe/compact/encrypt.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.CompactEncrypt = void 0; -const encrypt_js_1 = require("../flattened/encrypt.js"); -class CompactEncrypt { - constructor(plaintext) { - this._flattened = new encrypt_js_1.FlattenedEncrypt(plaintext); - } - setContentEncryptionKey(cek) { - this._flattened.setContentEncryptionKey(cek); - return this; - } - setInitializationVector(iv) { - this._flattened.setInitializationVector(iv); - return this; - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - setKeyManagementParameters(parameters) { - this._flattened.setKeyManagementParameters(parameters); - return this; - } - async encrypt(key, options) { - const jwe = await this._flattened.encrypt(key, options); - return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.'); - } -} -exports.CompactEncrypt = CompactEncrypt; diff --git a/dist/node/cjs/jwe/flattened/decrypt.js b/dist/node/cjs/jwe/flattened/decrypt.js deleted file mode 100644 index fc0ef8d3c6..0000000000 --- a/dist/node/cjs/jwe/flattened/decrypt.js +++ /dev/null @@ -1,141 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.flattenedDecrypt = void 0; -const base64url_js_1 = require("../../runtime/base64url.js"); -const decrypt_js_1 = require("../../runtime/decrypt.js"); -const zlib_js_1 = require("../../runtime/zlib.js"); -const errors_js_1 = require("../../util/errors.js"); -const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); -const is_object_js_1 = require("../../lib/is_object.js"); -const decrypt_key_management_js_1 = require("../../lib/decrypt_key_management.js"); -const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); -const cek_js_1 = require("../../lib/cek.js"); -const validate_crit_js_1 = require("../../lib/validate_crit.js"); -const validate_algorithms_js_1 = require("../../lib/validate_algorithms.js"); -async function flattenedDecrypt(jwe, key, options) { - var _a; - if (!(0, is_object_js_1.default)(jwe)) { - throw new errors_js_1.JWEInvalid('Flattened JWE must be an object'); - } - if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { - throw new errors_js_1.JWEInvalid('JOSE Header missing'); - } - if (typeof jwe.iv !== 'string') { - throw new errors_js_1.JWEInvalid('JWE Initialization Vector missing or incorrect type'); - } - if (typeof jwe.ciphertext !== 'string') { - throw new errors_js_1.JWEInvalid('JWE Ciphertext missing or incorrect type'); - } - if (typeof jwe.tag !== 'string') { - throw new errors_js_1.JWEInvalid('JWE Authentication Tag missing or incorrect type'); - } - if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { - throw new errors_js_1.JWEInvalid('JWE Protected Header incorrect type'); - } - if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { - throw new errors_js_1.JWEInvalid('JWE Encrypted Key incorrect type'); - } - if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { - throw new errors_js_1.JWEInvalid('JWE AAD incorrect type'); - } - if (jwe.header !== undefined && !(0, is_object_js_1.default)(jwe.header)) { - throw new errors_js_1.JWEInvalid('JWE Shared Unprotected Header incorrect type'); - } - if (jwe.unprotected !== undefined && !(0, is_object_js_1.default)(jwe.unprotected)) { - throw new errors_js_1.JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type'); - } - let parsedProt; - if (jwe.protected) { - try { - const protectedHeader = (0, base64url_js_1.decode)(jwe.protected); - parsedProt = JSON.parse(buffer_utils_js_1.decoder.decode(protectedHeader)); - } - catch { - throw new errors_js_1.JWEInvalid('JWE Protected Header is invalid'); - } - } - if (!(0, is_disjoint_js_1.default)(parsedProt, jwe.header, jwe.unprotected)) { - throw new errors_js_1.JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...parsedProt, - ...jwe.header, - ...jwe.unprotected, - }; - (0, validate_crit_js_1.default)(errors_js_1.JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - if (joseHeader.zip !== undefined) { - if (!parsedProt || !parsedProt.zip) { - throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== 'DEF') { - throw new errors_js_1.JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new errors_js_1.JWEInvalid('missing JWE Algorithm (alg) in JWE Header'); - } - if (typeof enc !== 'string' || !enc) { - throw new errors_js_1.JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header'); - } - const keyManagementAlgorithms = options && (0, validate_algorithms_js_1.default)('keyManagementAlgorithms', options.keyManagementAlgorithms); - const contentEncryptionAlgorithms = options && - (0, validate_algorithms_js_1.default)('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms); - if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { - throw new errors_js_1.JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { - throw new errors_js_1.JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); - } - let encryptedKey; - if (jwe.encrypted_key !== undefined) { - encryptedKey = (0, base64url_js_1.decode)(jwe.encrypted_key); - } - let resolvedKey = false; - if (typeof key === 'function') { - key = await key(parsedProt, jwe); - resolvedKey = true; - } - let cek; - try { - cek = await (0, decrypt_key_management_js_1.default)(alg, key, encryptedKey, joseHeader, options); - } - catch (err) { - if (err instanceof TypeError || err instanceof errors_js_1.JWEInvalid || err instanceof errors_js_1.JOSENotSupported) { - throw err; - } - cek = (0, cek_js_1.default)(enc); - } - const iv = (0, base64url_js_1.decode)(jwe.iv); - const tag = (0, base64url_js_1.decode)(jwe.tag); - const protectedHeader = buffer_utils_js_1.encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ''); - let additionalData; - if (jwe.aad !== undefined) { - additionalData = (0, buffer_utils_js_1.concat)(protectedHeader, buffer_utils_js_1.encoder.encode('.'), buffer_utils_js_1.encoder.encode(jwe.aad)); - } - else { - additionalData = protectedHeader; - } - let plaintext = await (0, decrypt_js_1.default)(enc, cek, (0, base64url_js_1.decode)(jwe.ciphertext), iv, tag, additionalData); - if (joseHeader.zip === 'DEF') { - plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || zlib_js_1.inflate)(plaintext); - } - const result = { plaintext }; - if (jwe.protected !== undefined) { - result.protectedHeader = parsedProt; - } - if (jwe.aad !== undefined) { - result.additionalAuthenticatedData = (0, base64url_js_1.decode)(jwe.aad); - } - if (jwe.unprotected !== undefined) { - result.sharedUnprotectedHeader = jwe.unprotected; - } - if (jwe.header !== undefined) { - result.unprotectedHeader = jwe.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} -exports.flattenedDecrypt = flattenedDecrypt; diff --git a/dist/node/cjs/jwe/flattened/encrypt.js b/dist/node/cjs/jwe/flattened/encrypt.js deleted file mode 100644 index 8a69ccf40a..0000000000 --- a/dist/node/cjs/jwe/flattened/encrypt.js +++ /dev/null @@ -1,179 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FlattenedEncrypt = exports.unprotected = void 0; -const base64url_js_1 = require("../../runtime/base64url.js"); -const encrypt_js_1 = require("../../runtime/encrypt.js"); -const zlib_js_1 = require("../../runtime/zlib.js"); -const iv_js_1 = require("../../lib/iv.js"); -const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js"); -const errors_js_1 = require("../../util/errors.js"); -const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); -const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); -const validate_crit_js_1 = require("../../lib/validate_crit.js"); -exports.unprotected = Symbol(); -class FlattenedEncrypt { - constructor(plaintext) { - if (!(plaintext instanceof Uint8Array)) { - throw new TypeError('plaintext must be an instance of Uint8Array'); - } - this._plaintext = plaintext; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once'); - } - this._keyManagementParameters = parameters; - return this; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._sharedUnprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once'); - } - this._sharedUnprotectedHeader = sharedUnprotectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once'); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once'); - } - this._iv = iv; - return this; - } - async encrypt(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { - throw new errors_js_1.JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()'); - } - if (!(0, is_disjoint_js_1.default)(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { - throw new errors_js_1.JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...this._sharedUnprotectedHeader, - }; - (0, validate_crit_js_1.default)(errors_js_1.JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== 'DEF') { - throw new errors_js_1.JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new errors_js_1.JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (typeof enc !== 'string' || !enc) { - throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - let encryptedKey; - if (alg === 'dir') { - if (this._cek) { - throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption'); - } - } - else if (alg === 'ECDH-ES') { - if (this._cek) { - throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement'); - } - } - let cek; - { - let parameters; - ({ cek, encryptedKey, parameters } = await (0, encrypt_key_management_js_1.default)(alg, enc, key, this._cek, this._keyManagementParameters)); - if (parameters) { - if (options && exports.unprotected in options) { - if (!this._unprotectedHeader) { - this.setUnprotectedHeader(parameters); - } - else { - this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; - } - } - else { - if (!this._protectedHeader) { - this.setProtectedHeader(parameters); - } - else { - this._protectedHeader = { ...this._protectedHeader, ...parameters }; - } - } - } - } - this._iv || (this._iv = (0, iv_js_1.default)(enc)); - let additionalData; - let protectedHeader; - let aadMember; - if (this._protectedHeader) { - protectedHeader = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(JSON.stringify(this._protectedHeader))); - } - else { - protectedHeader = buffer_utils_js_1.encoder.encode(''); - } - if (this._aad) { - aadMember = (0, base64url_js_1.encode)(this._aad); - additionalData = (0, buffer_utils_js_1.concat)(protectedHeader, buffer_utils_js_1.encoder.encode('.'), buffer_utils_js_1.encoder.encode(aadMember)); - } - else { - additionalData = protectedHeader; - } - let ciphertext; - let tag; - if (joseHeader.zip === 'DEF') { - const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || zlib_js_1.deflate)(this._plaintext); - ({ ciphertext, tag } = await (0, encrypt_js_1.default)(enc, deflated, cek, this._iv, additionalData)); - } - else { - ; - ({ ciphertext, tag } = await (0, encrypt_js_1.default)(enc, this._plaintext, cek, this._iv, additionalData)); - } - const jwe = { - ciphertext: (0, base64url_js_1.encode)(ciphertext), - iv: (0, base64url_js_1.encode)(this._iv), - tag: (0, base64url_js_1.encode)(tag), - }; - if (encryptedKey) { - jwe.encrypted_key = (0, base64url_js_1.encode)(encryptedKey); - } - if (aadMember) { - jwe.aad = aadMember; - } - if (this._protectedHeader) { - jwe.protected = buffer_utils_js_1.decoder.decode(protectedHeader); - } - if (this._sharedUnprotectedHeader) { - jwe.unprotected = this._sharedUnprotectedHeader; - } - if (this._unprotectedHeader) { - jwe.header = this._unprotectedHeader; - } - return jwe; - } -} -exports.FlattenedEncrypt = FlattenedEncrypt; diff --git a/dist/node/cjs/jwe/general/decrypt.js b/dist/node/cjs/jwe/general/decrypt.js deleted file mode 100644 index accb23aa6a..0000000000 --- a/dist/node/cjs/jwe/general/decrypt.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.generalDecrypt = void 0; -const decrypt_js_1 = require("../flattened/decrypt.js"); -const errors_js_1 = require("../../util/errors.js"); -const is_object_js_1 = require("../../lib/is_object.js"); -async function generalDecrypt(jwe, key, options) { - if (!(0, is_object_js_1.default)(jwe)) { - throw new errors_js_1.JWEInvalid('General JWE must be an object'); - } - if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(is_object_js_1.default)) { - throw new errors_js_1.JWEInvalid('JWE Recipients missing or incorrect type'); - } - if (!jwe.recipients.length) { - throw new errors_js_1.JWEInvalid('JWE Recipients has no members'); - } - for (const recipient of jwe.recipients) { - try { - return await (0, decrypt_js_1.flattenedDecrypt)({ - aad: jwe.aad, - ciphertext: jwe.ciphertext, - encrypted_key: recipient.encrypted_key, - header: recipient.header, - iv: jwe.iv, - protected: jwe.protected, - tag: jwe.tag, - unprotected: jwe.unprotected, - }, key, options); - } - catch { - } - } - throw new errors_js_1.JWEDecryptionFailed(); -} -exports.generalDecrypt = generalDecrypt; diff --git a/dist/node/cjs/jwe/general/encrypt.js b/dist/node/cjs/jwe/general/encrypt.js deleted file mode 100644 index 3caa084eda..0000000000 --- a/dist/node/cjs/jwe/general/encrypt.js +++ /dev/null @@ -1,182 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.GeneralEncrypt = void 0; -const encrypt_js_1 = require("../flattened/encrypt.js"); -const errors_js_1 = require("../../util/errors.js"); -const cek_js_1 = require("../../lib/cek.js"); -const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); -const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js"); -const base64url_js_1 = require("../../runtime/base64url.js"); -const validate_crit_js_1 = require("../../lib/validate_crit.js"); -class IndividualRecipient { - constructor(enc, key, options) { - this.parent = enc; - this.key = key; - this.options = options; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addRecipient(...args) { - return this.parent.addRecipient(...args); - } - encrypt(...args) { - return this.parent.encrypt(...args); - } - done() { - return this.parent; - } -} -class GeneralEncrypt { - constructor(plaintext) { - this._recipients = []; - this._plaintext = plaintext; - } - addRecipient(key, options) { - const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); - this._recipients.push(recipient); - return recipient; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = sharedUnprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - async encrypt(options) { - var _a, _b, _c; - if (!this._recipients.length) { - throw new errors_js_1.JWEInvalid('at least one recipient must be added'); - } - options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; - if (this._recipients.length === 1) { - const [recipient] = this._recipients; - const flattened = await new encrypt_js_1.FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader) - .encrypt(recipient.key, { ...recipient.options, ...options }); - let jwe = { - ciphertext: flattened.ciphertext, - iv: flattened.iv, - recipients: [{}], - tag: flattened.tag, - }; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - if (flattened.encrypted_key) - jwe.recipients[0].encrypted_key = flattened.encrypted_key; - if (flattened.header) - jwe.recipients[0].header = flattened.header; - return jwe; - } - let enc; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - if (!(0, is_disjoint_js_1.default)(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { - throw new errors_js_1.JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - }; - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new errors_js_1.JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (alg === 'dir' || alg === 'ECDH-ES') { - throw new errors_js_1.JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); - } - if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { - throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - if (!enc) { - enc = joseHeader.enc; - } - else if (enc !== joseHeader.enc) { - throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); - } - (0, validate_crit_js_1.default)(errors_js_1.JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - } - } - const cek = (0, cek_js_1.default)(enc); - let jwe = { - ciphertext: '', - iv: '', - recipients: [], - tag: '', - }; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - const target = {}; - jwe.recipients.push(target); - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - }; - const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined; - if (i === 0) { - const flattened = await new encrypt_js_1.FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setContentEncryptionKey(cek) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader) - .setKeyManagementParameters({ p2c }) - .encrypt(recipient.key, { - ...recipient.options, - ...options, - [encrypt_js_1.unprotected]: true, - }); - jwe.ciphertext = flattened.ciphertext; - jwe.iv = flattened.iv; - jwe.tag = flattened.tag; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - target.encrypted_key = flattened.encrypted_key; - if (flattened.header) - target.header = flattened.header; - continue; - } - const { encryptedKey, parameters } = await (0, encrypt_key_management_js_1.default)(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || - ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || - ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); - target.encrypted_key = (0, base64url_js_1.encode)(encryptedKey); - if (recipient.unprotectedHeader || parameters) - target.header = { ...recipient.unprotectedHeader, ...parameters }; - } - return jwe; - } -} -exports.GeneralEncrypt = GeneralEncrypt; diff --git a/dist/node/cjs/jwk/embedded.js b/dist/node/cjs/jwk/embedded.js deleted file mode 100644 index 3fe1268e68..0000000000 --- a/dist/node/cjs/jwk/embedded.js +++ /dev/null @@ -1,21 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.EmbeddedJWK = void 0; -const import_js_1 = require("../key/import.js"); -const is_object_js_1 = require("../lib/is_object.js"); -const errors_js_1 = require("../util/errors.js"); -async function EmbeddedJWK(protectedHeader, token) { - const joseHeader = { - ...protectedHeader, - ...token.header, - }; - if (!(0, is_object_js_1.default)(joseHeader.jwk)) { - throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); - } - const key = await (0, import_js_1.importJWK)({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); - if (key instanceof Uint8Array || key.type !== 'public') { - throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); - } - return key; -} -exports.EmbeddedJWK = EmbeddedJWK; diff --git a/dist/node/cjs/jwk/thumbprint.js b/dist/node/cjs/jwk/thumbprint.js deleted file mode 100644 index d50e2ba357..0000000000 --- a/dist/node/cjs/jwk/thumbprint.js +++ /dev/null @@ -1,58 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.calculateJwkThumbprintUri = exports.calculateJwkThumbprint = void 0; -const digest_js_1 = require("../runtime/digest.js"); -const base64url_js_1 = require("../runtime/base64url.js"); -const errors_js_1 = require("../util/errors.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const is_object_js_1 = require("../lib/is_object.js"); -const check = (value, description) => { - if (typeof value !== 'string' || !value) { - throw new errors_js_1.JWKInvalid(`${description} missing or invalid`); - } -}; -async function calculateJwkThumbprint(jwk, digestAlgorithm) { - if (!(0, is_object_js_1.default)(jwk)) { - throw new TypeError('JWK must be an object'); - } - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); - if (digestAlgorithm !== 'sha256' && - digestAlgorithm !== 'sha384' && - digestAlgorithm !== 'sha512') { - throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); - } - let components; - switch (jwk.kty) { - case 'EC': - check(jwk.crv, '"crv" (Curve) Parameter'); - check(jwk.x, '"x" (X Coordinate) Parameter'); - check(jwk.y, '"y" (Y Coordinate) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; - break; - case 'OKP': - check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); - check(jwk.x, '"x" (Public Key) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; - break; - case 'RSA': - check(jwk.e, '"e" (Exponent) Parameter'); - check(jwk.n, '"n" (Modulus) Parameter'); - components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; - break; - case 'oct': - check(jwk.k, '"k" (Key Value) Parameter'); - components = { k: jwk.k, kty: jwk.kty }; - break; - default: - throw new errors_js_1.JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); - } - const data = buffer_utils_js_1.encoder.encode(JSON.stringify(components)); - return (0, base64url_js_1.encode)(await (0, digest_js_1.default)(digestAlgorithm, data)); -} -exports.calculateJwkThumbprint = calculateJwkThumbprint; -async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); - const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); - return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; -} -exports.calculateJwkThumbprintUri = calculateJwkThumbprintUri; diff --git a/dist/node/cjs/jwks/local.js b/dist/node/cjs/jwks/local.js deleted file mode 100644 index e95a60724d..0000000000 --- a/dist/node/cjs/jwks/local.js +++ /dev/null @@ -1,119 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.createLocalJWKSet = exports.LocalJWKSet = exports.isJWKSLike = void 0; -const import_js_1 = require("../key/import.js"); -const errors_js_1 = require("../util/errors.js"); -const is_object_js_1 = require("../lib/is_object.js"); -function getKtyFromAlg(alg) { - switch (typeof alg === 'string' && alg.slice(0, 2)) { - case 'RS': - case 'PS': - return 'RSA'; - case 'ES': - return 'EC'; - case 'Ed': - return 'OKP'; - default: - throw new errors_js_1.JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); - } -} -function isJWKSLike(jwks) { - return (jwks && - typeof jwks === 'object' && - Array.isArray(jwks.keys) && - jwks.keys.every(isJWKLike)); -} -exports.isJWKSLike = isJWKSLike; -function isJWKLike(key) { - return (0, is_object_js_1.default)(key); -} -function clone(obj) { - if (typeof structuredClone === 'function') { - return structuredClone(obj); - } - return JSON.parse(JSON.stringify(obj)); -} -class LocalJWKSet { - constructor(jwks) { - this._cached = new WeakMap(); - if (!isJWKSLike(jwks)) { - throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed'); - } - this._jwks = clone(jwks); - } - async getKey(protectedHeader, token) { - const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; - const kty = getKtyFromAlg(alg); - const candidates = this._jwks.keys.filter((jwk) => { - let candidate = kty === jwk.kty; - if (candidate && typeof kid === 'string') { - candidate = kid === jwk.kid; - } - if (candidate && typeof jwk.alg === 'string') { - candidate = alg === jwk.alg; - } - if (candidate && typeof jwk.use === 'string') { - candidate = jwk.use === 'sig'; - } - if (candidate && Array.isArray(jwk.key_ops)) { - candidate = jwk.key_ops.includes('verify'); - } - if (candidate && alg === 'EdDSA') { - candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'; - } - if (candidate) { - switch (alg) { - case 'ES256': - candidate = jwk.crv === 'P-256'; - break; - case 'ES256K': - candidate = jwk.crv === 'secp256k1'; - break; - case 'ES384': - candidate = jwk.crv === 'P-384'; - break; - case 'ES512': - candidate = jwk.crv === 'P-521'; - break; - } - } - return candidate; - }); - const { 0: jwk, length } = candidates; - if (length === 0) { - throw new errors_js_1.JWKSNoMatchingKey(); - } - else if (length !== 1) { - const error = new errors_js_1.JWKSMultipleMatchingKeys(); - const { _cached } = this; - error[Symbol.asyncIterator] = async function* () { - for (const jwk of candidates) { - try { - yield await importWithAlgCache(_cached, jwk, alg); - } - catch { - continue; - } - } - }; - throw error; - } - return importWithAlgCache(this._cached, jwk, alg); - } -} -exports.LocalJWKSet = LocalJWKSet; -async function importWithAlgCache(cache, jwk, alg) { - const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); - if (cached[alg] === undefined) { - const keyObject = await (0, import_js_1.importJWK)({ ...jwk, ext: true }, alg); - if (keyObject.type !== 'public') { - throw new errors_js_1.JWKSInvalid('JSON Web Key Set members must be public keys'); - } - cached[alg] = keyObject; - } - return cached[alg]; -} -function createLocalJWKSet(jwks) { - return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); -} -exports.createLocalJWKSet = createLocalJWKSet; diff --git a/dist/node/cjs/jwks/remote.js b/dist/node/cjs/jwks/remote.js deleted file mode 100644 index 79794cdee1..0000000000 --- a/dist/node/cjs/jwks/remote.js +++ /dev/null @@ -1,85 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.createRemoteJWKSet = void 0; -const fetch_jwks_js_1 = require("../runtime/fetch_jwks.js"); -const env_js_1 = require("../runtime/env.js"); -const errors_js_1 = require("../util/errors.js"); -const local_js_1 = require("./local.js"); -class RemoteJWKSet extends local_js_1.LocalJWKSet { - constructor(url, options) { - super({ keys: [] }); - this._jwks = undefined; - if (!(url instanceof URL)) { - throw new TypeError('url must be an instance of URL'); - } - this._url = new URL(url.href); - this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; - this._timeoutDuration = - typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000; - this._cooldownDuration = - typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000; - this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000; - } - coolingDown() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cooldownDuration - : false; - } - fresh() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cacheMaxAge - : false; - } - async getKey(protectedHeader, token) { - if (!this._jwks || !this.fresh()) { - await this.reload(); - } - try { - return await super.getKey(protectedHeader, token); - } - catch (err) { - if (err instanceof errors_js_1.JWKSNoMatchingKey) { - if (this.coolingDown() === false) { - await this.reload(); - return super.getKey(protectedHeader, token); - } - } - throw err; - } - } - async reload() { - if (this._pendingFetch && (0, env_js_1.isCloudflareWorkers)()) { - return new Promise((resolve) => { - const isDone = () => { - if (this._pendingFetch === undefined) { - resolve(); - } - else { - setTimeout(isDone, 5); - } - }; - isDone(); - }); - } - if (!this._pendingFetch) { - this._pendingFetch = (0, fetch_jwks_js_1.default)(this._url, this._timeoutDuration, this._options) - .then((json) => { - if (!(0, local_js_1.isJWKSLike)(json)) { - throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed'); - } - this._jwks = { keys: json.keys }; - this._jwksTimestamp = Date.now(); - this._pendingFetch = undefined; - }) - .catch((err) => { - this._pendingFetch = undefined; - throw err; - }); - } - await this._pendingFetch; - } -} -function createRemoteJWKSet(url, options) { - return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); -} -exports.createRemoteJWKSet = createRemoteJWKSet; diff --git a/dist/node/cjs/jws/compact/sign.js b/dist/node/cjs/jws/compact/sign.js deleted file mode 100644 index e960ade473..0000000000 --- a/dist/node/cjs/jws/compact/sign.js +++ /dev/null @@ -1,21 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.CompactSign = void 0; -const sign_js_1 = require("../flattened/sign.js"); -class CompactSign { - constructor(payload) { - this._flattened = new sign_js_1.FlattenedSign(payload); - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - async sign(key, options) { - const jws = await this._flattened.sign(key, options); - if (jws.payload === undefined) { - throw new TypeError('use the flattened module for creating JWS with b64: false'); - } - return `${jws.protected}.${jws.payload}.${jws.signature}`; - } -} -exports.CompactSign = CompactSign; diff --git a/dist/node/cjs/jws/compact/verify.js b/dist/node/cjs/jws/compact/verify.js deleted file mode 100644 index b7e672477f..0000000000 --- a/dist/node/cjs/jws/compact/verify.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.compactVerify = void 0; -const verify_js_1 = require("../flattened/verify.js"); -const errors_js_1 = require("../../util/errors.js"); -const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); -async function compactVerify(jws, key, options) { - if (jws instanceof Uint8Array) { - jws = buffer_utils_js_1.decoder.decode(jws); - } - if (typeof jws !== 'string') { - throw new errors_js_1.JWSInvalid('Compact JWS must be a string or Uint8Array'); - } - const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.'); - if (length !== 3) { - throw new errors_js_1.JWSInvalid('Invalid Compact JWS'); - } - const verified = await (0, verify_js_1.flattenedVerify)({ payload, protected: protectedHeader, signature }, key, options); - const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: verified.key }; - } - return result; -} -exports.compactVerify = compactVerify; diff --git a/dist/node/cjs/jws/flattened/sign.js b/dist/node/cjs/jws/flattened/sign.js deleted file mode 100644 index 2281e97cf3..0000000000 --- a/dist/node/cjs/jws/flattened/sign.js +++ /dev/null @@ -1,85 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FlattenedSign = void 0; -const base64url_js_1 = require("../../runtime/base64url.js"); -const sign_js_1 = require("../../runtime/sign.js"); -const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); -const errors_js_1 = require("../../util/errors.js"); -const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); -const check_key_type_js_1 = require("../../lib/check_key_type.js"); -const validate_crit_js_1 = require("../../lib/validate_crit.js"); -class FlattenedSign { - constructor(payload) { - if (!(payload instanceof Uint8Array)) { - throw new TypeError('payload must be an instance of Uint8Array'); - } - this._payload = payload; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - async sign(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader) { - throw new errors_js_1.JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); - } - if (!(0, is_disjoint_js_1.default)(this._protectedHeader, this._unprotectedHeader)) { - throw new errors_js_1.JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - }; - const extensions = (0, validate_crit_js_1.default)(errors_js_1.JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - let b64 = true; - if (extensions.has('b64')) { - b64 = this._protectedHeader.b64; - if (typeof b64 !== 'boolean') { - throw new errors_js_1.JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new errors_js_1.JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - (0, check_key_type_js_1.default)(alg, key, 'sign'); - let payload = this._payload; - if (b64) { - payload = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(payload)); - } - let protectedHeader; - if (this._protectedHeader) { - protectedHeader = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(JSON.stringify(this._protectedHeader))); - } - else { - protectedHeader = buffer_utils_js_1.encoder.encode(''); - } - const data = (0, buffer_utils_js_1.concat)(protectedHeader, buffer_utils_js_1.encoder.encode('.'), payload); - const signature = await (0, sign_js_1.default)(alg, key, data); - const jws = { - signature: (0, base64url_js_1.encode)(signature), - payload: '', - }; - if (b64) { - jws.payload = buffer_utils_js_1.decoder.decode(payload); - } - if (this._unprotectedHeader) { - jws.header = this._unprotectedHeader; - } - if (this._protectedHeader) { - jws.protected = buffer_utils_js_1.decoder.decode(protectedHeader); - } - return jws; - } -} -exports.FlattenedSign = FlattenedSign; diff --git a/dist/node/cjs/jws/flattened/verify.js b/dist/node/cjs/jws/flattened/verify.js deleted file mode 100644 index 5f0c3930e1..0000000000 --- a/dist/node/cjs/jws/flattened/verify.js +++ /dev/null @@ -1,108 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.flattenedVerify = void 0; -const base64url_js_1 = require("../../runtime/base64url.js"); -const verify_js_1 = require("../../runtime/verify.js"); -const errors_js_1 = require("../../util/errors.js"); -const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); -const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); -const is_object_js_1 = require("../../lib/is_object.js"); -const check_key_type_js_1 = require("../../lib/check_key_type.js"); -const validate_crit_js_1 = require("../../lib/validate_crit.js"); -const validate_algorithms_js_1 = require("../../lib/validate_algorithms.js"); -async function flattenedVerify(jws, key, options) { - var _a; - if (!(0, is_object_js_1.default)(jws)) { - throw new errors_js_1.JWSInvalid('Flattened JWS must be an object'); - } - if (jws.protected === undefined && jws.header === undefined) { - throw new errors_js_1.JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); - } - if (jws.protected !== undefined && typeof jws.protected !== 'string') { - throw new errors_js_1.JWSInvalid('JWS Protected Header incorrect type'); - } - if (jws.payload === undefined) { - throw new errors_js_1.JWSInvalid('JWS Payload missing'); - } - if (typeof jws.signature !== 'string') { - throw new errors_js_1.JWSInvalid('JWS Signature missing or incorrect type'); - } - if (jws.header !== undefined && !(0, is_object_js_1.default)(jws.header)) { - throw new errors_js_1.JWSInvalid('JWS Unprotected Header incorrect type'); - } - let parsedProt = {}; - if (jws.protected) { - try { - const protectedHeader = (0, base64url_js_1.decode)(jws.protected); - parsedProt = JSON.parse(buffer_utils_js_1.decoder.decode(protectedHeader)); - } - catch { - throw new errors_js_1.JWSInvalid('JWS Protected Header is invalid'); - } - } - if (!(0, is_disjoint_js_1.default)(parsedProt, jws.header)) { - throw new errors_js_1.JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...parsedProt, - ...jws.header, - }; - const extensions = (0, validate_crit_js_1.default)(errors_js_1.JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - let b64 = true; - if (extensions.has('b64')) { - b64 = parsedProt.b64; - if (typeof b64 !== 'boolean') { - throw new errors_js_1.JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new errors_js_1.JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - const algorithms = options && (0, validate_algorithms_js_1.default)('algorithms', options.algorithms); - if (algorithms && !algorithms.has(alg)) { - throw new errors_js_1.JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (b64) { - if (typeof jws.payload !== 'string') { - throw new errors_js_1.JWSInvalid('JWS Payload must be a string'); - } - } - else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { - throw new errors_js_1.JWSInvalid('JWS Payload must be a string or an Uint8Array instance'); - } - let resolvedKey = false; - if (typeof key === 'function') { - key = await key(parsedProt, jws); - resolvedKey = true; - } - (0, check_key_type_js_1.default)(alg, key, 'verify'); - const data = (0, buffer_utils_js_1.concat)(buffer_utils_js_1.encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), buffer_utils_js_1.encoder.encode('.'), typeof jws.payload === 'string' ? buffer_utils_js_1.encoder.encode(jws.payload) : jws.payload); - const signature = (0, base64url_js_1.decode)(jws.signature); - const verified = await (0, verify_js_1.default)(alg, key, signature, data); - if (!verified) { - throw new errors_js_1.JWSSignatureVerificationFailed(); - } - let payload; - if (b64) { - payload = (0, base64url_js_1.decode)(jws.payload); - } - else if (typeof jws.payload === 'string') { - payload = buffer_utils_js_1.encoder.encode(jws.payload); - } - else { - payload = jws.payload; - } - const result = { payload }; - if (jws.protected !== undefined) { - result.protectedHeader = parsedProt; - } - if (jws.header !== undefined) { - result.unprotectedHeader = jws.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} -exports.flattenedVerify = flattenedVerify; diff --git a/dist/node/cjs/jws/general/sign.js b/dist/node/cjs/jws/general/sign.js deleted file mode 100644 index 6a876d905b..0000000000 --- a/dist/node/cjs/jws/general/sign.js +++ /dev/null @@ -1,71 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.GeneralSign = void 0; -const sign_js_1 = require("../flattened/sign.js"); -const errors_js_1 = require("../../util/errors.js"); -class IndividualSignature { - constructor(sig, key, options) { - this.parent = sig; - this.key = key; - this.options = options; - } - setProtectedHeader(protectedHeader) { - if (this.protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this.protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addSignature(...args) { - return this.parent.addSignature(...args); - } - sign(...args) { - return this.parent.sign(...args); - } - done() { - return this.parent; - } -} -class GeneralSign { - constructor(payload) { - this._signatures = []; - this._payload = payload; - } - addSignature(key, options) { - const signature = new IndividualSignature(this, key, options); - this._signatures.push(signature); - return signature; - } - async sign() { - if (!this._signatures.length) { - throw new errors_js_1.JWSInvalid('at least one signature must be added'); - } - const jws = { - signatures: [], - payload: '', - }; - for (let i = 0; i < this._signatures.length; i++) { - const signature = this._signatures[i]; - const flattened = new sign_js_1.FlattenedSign(this._payload); - flattened.setProtectedHeader(signature.protectedHeader); - flattened.setUnprotectedHeader(signature.unprotectedHeader); - const { payload, ...rest } = await flattened.sign(signature.key, signature.options); - if (i === 0) { - jws.payload = payload; - } - else if (jws.payload !== payload) { - throw new errors_js_1.JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)'); - } - jws.signatures.push(rest); - } - return jws; - } -} -exports.GeneralSign = GeneralSign; diff --git a/dist/node/cjs/jws/general/verify.js b/dist/node/cjs/jws/general/verify.js deleted file mode 100644 index 9d4a07a296..0000000000 --- a/dist/node/cjs/jws/general/verify.js +++ /dev/null @@ -1,28 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.generalVerify = void 0; -const verify_js_1 = require("../flattened/verify.js"); -const errors_js_1 = require("../../util/errors.js"); -const is_object_js_1 = require("../../lib/is_object.js"); -async function generalVerify(jws, key, options) { - if (!(0, is_object_js_1.default)(jws)) { - throw new errors_js_1.JWSInvalid('General JWS must be an object'); - } - if (!Array.isArray(jws.signatures) || !jws.signatures.every(is_object_js_1.default)) { - throw new errors_js_1.JWSInvalid('JWS Signatures missing or incorrect type'); - } - for (const signature of jws.signatures) { - try { - return await (0, verify_js_1.flattenedVerify)({ - header: signature.header, - payload: jws.payload, - protected: signature.protected, - signature: signature.signature, - }, key, options); - } - catch { - } - } - throw new errors_js_1.JWSSignatureVerificationFailed(); -} -exports.generalVerify = generalVerify; diff --git a/dist/node/cjs/jwt/decrypt.js b/dist/node/cjs/jwt/decrypt.js deleted file mode 100644 index 3539ceab53..0000000000 --- a/dist/node/cjs/jwt/decrypt.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.jwtDecrypt = void 0; -const decrypt_js_1 = require("../jwe/compact/decrypt.js"); -const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); -const errors_js_1 = require("../util/errors.js"); -async function jwtDecrypt(jwt, key, options) { - const decrypted = await (0, decrypt_js_1.compactDecrypt)(jwt, key, options); - const payload = (0, jwt_claims_set_js_1.default)(decrypted.protectedHeader, decrypted.plaintext, options); - const { protectedHeader } = decrypted; - if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { - throw new errors_js_1.JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', 'iss', 'mismatch'); - } - if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { - throw new errors_js_1.JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', 'sub', 'mismatch'); - } - if (protectedHeader.aud !== undefined && - JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { - throw new errors_js_1.JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch'); - } - const result = { payload, protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: decrypted.key }; - } - return result; -} -exports.jwtDecrypt = jwtDecrypt; diff --git a/dist/node/cjs/jwt/encrypt.js b/dist/node/cjs/jwt/encrypt.js deleted file mode 100644 index 8ce18f1e73..0000000000 --- a/dist/node/cjs/jwt/encrypt.js +++ /dev/null @@ -1,72 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.EncryptJWT = void 0; -const encrypt_js_1 = require("../jwe/compact/encrypt.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const produce_js_1 = require("./produce.js"); -class EncryptJWT extends produce_js_1.ProduceJWT { - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once'); - } - this._keyManagementParameters = parameters; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once'); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once'); - } - this._iv = iv; - return this; - } - replicateIssuerAsHeader() { - this._replicateIssuerAsHeader = true; - return this; - } - replicateSubjectAsHeader() { - this._replicateSubjectAsHeader = true; - return this; - } - replicateAudienceAsHeader() { - this._replicateAudienceAsHeader = true; - return this; - } - async encrypt(key, options) { - const enc = new encrypt_js_1.CompactEncrypt(buffer_utils_js_1.encoder.encode(JSON.stringify(this._payload))); - if (this._replicateIssuerAsHeader) { - this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; - } - if (this._replicateSubjectAsHeader) { - this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; - } - if (this._replicateAudienceAsHeader) { - this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; - } - enc.setProtectedHeader(this._protectedHeader); - if (this._iv) { - enc.setInitializationVector(this._iv); - } - if (this._cek) { - enc.setContentEncryptionKey(this._cek); - } - if (this._keyManagementParameters) { - enc.setKeyManagementParameters(this._keyManagementParameters); - } - return enc.encrypt(key, options); - } -} -exports.EncryptJWT = EncryptJWT; diff --git a/dist/node/cjs/jwt/produce.js b/dist/node/cjs/jwt/produce.js deleted file mode 100644 index 54d9ccb134..0000000000 --- a/dist/node/cjs/jwt/produce.js +++ /dev/null @@ -1,58 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ProduceJWT = void 0; -const epoch_js_1 = require("../lib/epoch.js"); -const is_object_js_1 = require("../lib/is_object.js"); -const secs_js_1 = require("../lib/secs.js"); -class ProduceJWT { - constructor(payload) { - if (!(0, is_object_js_1.default)(payload)) { - throw new TypeError('JWT Claims Set MUST be an object'); - } - this._payload = payload; - } - setIssuer(issuer) { - this._payload = { ...this._payload, iss: issuer }; - return this; - } - setSubject(subject) { - this._payload = { ...this._payload, sub: subject }; - return this; - } - setAudience(audience) { - this._payload = { ...this._payload, aud: audience }; - return this; - } - setJti(jwtId) { - this._payload = { ...this._payload, jti: jwtId }; - return this; - } - setNotBefore(input) { - if (typeof input === 'number') { - this._payload = { ...this._payload, nbf: input }; - } - else { - this._payload = { ...this._payload, nbf: (0, epoch_js_1.default)(new Date()) + (0, secs_js_1.default)(input) }; - } - return this; - } - setExpirationTime(input) { - if (typeof input === 'number') { - this._payload = { ...this._payload, exp: input }; - } - else { - this._payload = { ...this._payload, exp: (0, epoch_js_1.default)(new Date()) + (0, secs_js_1.default)(input) }; - } - return this; - } - setIssuedAt(input) { - if (typeof input === 'undefined') { - this._payload = { ...this._payload, iat: (0, epoch_js_1.default)(new Date()) }; - } - else { - this._payload = { ...this._payload, iat: input }; - } - return this; - } -} -exports.ProduceJWT = ProduceJWT; diff --git a/dist/node/cjs/jwt/sign.js b/dist/node/cjs/jwt/sign.js deleted file mode 100644 index ad9193c13a..0000000000 --- a/dist/node/cjs/jwt/sign.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.SignJWT = void 0; -const sign_js_1 = require("../jws/compact/sign.js"); -const errors_js_1 = require("../util/errors.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const produce_js_1 = require("./produce.js"); -class SignJWT extends produce_js_1.ProduceJWT { - setProtectedHeader(protectedHeader) { - this._protectedHeader = protectedHeader; - return this; - } - async sign(key, options) { - var _a; - const sig = new sign_js_1.CompactSign(buffer_utils_js_1.encoder.encode(JSON.stringify(this._payload))); - sig.setProtectedHeader(this._protectedHeader); - if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && - this._protectedHeader.crit.includes('b64') && - this._protectedHeader.b64 === false) { - throw new errors_js_1.JWTInvalid('JWTs MUST NOT use unencoded payload'); - } - return sig.sign(key, options); - } -} -exports.SignJWT = SignJWT; diff --git a/dist/node/cjs/jwt/unsecured.js b/dist/node/cjs/jwt/unsecured.js deleted file mode 100644 index 482782fed1..0000000000 --- a/dist/node/cjs/jwt/unsecured.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.UnsecuredJWT = void 0; -const base64url = require("../runtime/base64url.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const errors_js_1 = require("../util/errors.js"); -const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); -const produce_js_1 = require("./produce.js"); -class UnsecuredJWT extends produce_js_1.ProduceJWT { - encode() { - const header = base64url.encode(JSON.stringify({ alg: 'none' })); - const payload = base64url.encode(JSON.stringify(this._payload)); - return `${header}.${payload}.`; - } - static decode(jwt, options) { - if (typeof jwt !== 'string') { - throw new errors_js_1.JWTInvalid('Unsecured JWT must be a string'); - } - const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.'); - if (length !== 3 || signature !== '') { - throw new errors_js_1.JWTInvalid('Invalid Unsecured JWT'); - } - let header; - try { - header = JSON.parse(buffer_utils_js_1.decoder.decode(base64url.decode(encodedHeader))); - if (header.alg !== 'none') - throw new Error(); - } - catch { - throw new errors_js_1.JWTInvalid('Invalid Unsecured JWT'); - } - const payload = (0, jwt_claims_set_js_1.default)(header, base64url.decode(encodedPayload), options); - return { payload, header }; - } -} -exports.UnsecuredJWT = UnsecuredJWT; diff --git a/dist/node/cjs/jwt/verify.js b/dist/node/cjs/jwt/verify.js deleted file mode 100644 index d77bb96096..0000000000 --- a/dist/node/cjs/jwt/verify.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.jwtVerify = void 0; -const verify_js_1 = require("../jws/compact/verify.js"); -const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); -const errors_js_1 = require("../util/errors.js"); -async function jwtVerify(jwt, key, options) { - var _a; - const verified = await (0, verify_js_1.compactVerify)(jwt, key, options); - if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { - throw new errors_js_1.JWTInvalid('JWTs MUST NOT use unencoded payload'); - } - const payload = (0, jwt_claims_set_js_1.default)(verified.protectedHeader, verified.payload, options); - const result = { payload, protectedHeader: verified.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: verified.key }; - } - return result; -} -exports.jwtVerify = jwtVerify; diff --git a/dist/node/cjs/key/export.js b/dist/node/cjs/key/export.js deleted file mode 100644 index 1c083efe72..0000000000 --- a/dist/node/cjs/key/export.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.exportJWK = exports.exportPKCS8 = exports.exportSPKI = void 0; -const asn1_js_1 = require("../runtime/asn1.js"); -const asn1_js_2 = require("../runtime/asn1.js"); -const key_to_jwk_js_1 = require("../runtime/key_to_jwk.js"); -async function exportSPKI(key) { - return (0, asn1_js_1.toSPKI)(key); -} -exports.exportSPKI = exportSPKI; -async function exportPKCS8(key) { - return (0, asn1_js_2.toPKCS8)(key); -} -exports.exportPKCS8 = exportPKCS8; -async function exportJWK(key) { - return (0, key_to_jwk_js_1.default)(key); -} -exports.exportJWK = exportJWK; diff --git a/dist/node/cjs/key/generate_key_pair.js b/dist/node/cjs/key/generate_key_pair.js deleted file mode 100644 index 3d14da5c3e..0000000000 --- a/dist/node/cjs/key/generate_key_pair.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.generateKeyPair = void 0; -const generate_js_1 = require("../runtime/generate.js"); -async function generateKeyPair(alg, options) { - return (0, generate_js_1.generateKeyPair)(alg, options); -} -exports.generateKeyPair = generateKeyPair; diff --git a/dist/node/cjs/key/generate_secret.js b/dist/node/cjs/key/generate_secret.js deleted file mode 100644 index 5f3c9ba214..0000000000 --- a/dist/node/cjs/key/generate_secret.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.generateSecret = void 0; -const generate_js_1 = require("../runtime/generate.js"); -async function generateSecret(alg, options) { - return (0, generate_js_1.generateSecret)(alg, options); -} -exports.generateSecret = generateSecret; diff --git a/dist/node/cjs/key/import.js b/dist/node/cjs/key/import.js deleted file mode 100644 index e12b288006..0000000000 --- a/dist/node/cjs/key/import.js +++ /dev/null @@ -1,57 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.importJWK = exports.importPKCS8 = exports.importX509 = exports.importSPKI = void 0; -const base64url_js_1 = require("../runtime/base64url.js"); -const asn1_js_1 = require("../runtime/asn1.js"); -const jwk_to_key_js_1 = require("../runtime/jwk_to_key.js"); -const errors_js_1 = require("../util/errors.js"); -const is_object_js_1 = require("../lib/is_object.js"); -async function importSPKI(spki, alg, options) { - if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { - throw new TypeError('"spki" must be SPKI formatted string'); - } - return (0, asn1_js_1.fromSPKI)(spki, alg, options); -} -exports.importSPKI = importSPKI; -async function importX509(x509, alg, options) { - if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { - throw new TypeError('"x509" must be X.509 formatted string'); - } - return (0, asn1_js_1.fromX509)(x509, alg, options); -} -exports.importX509 = importX509; -async function importPKCS8(pkcs8, alg, options) { - if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { - throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); - } - return (0, asn1_js_1.fromPKCS8)(pkcs8, alg, options); -} -exports.importPKCS8 = importPKCS8; -async function importJWK(jwk, alg, octAsKeyObject) { - var _a; - if (!(0, is_object_js_1.default)(jwk)) { - throw new TypeError('JWK must be an object'); - } - alg || (alg = jwk.alg); - switch (jwk.kty) { - case 'oct': - if (typeof jwk.k !== 'string' || !jwk.k) { - throw new TypeError('missing "k" (Key Value) Parameter value'); - } - octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true); - if (octAsKeyObject) { - return (0, jwk_to_key_js_1.default)({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); - } - return (0, base64url_js_1.decode)(jwk.k); - case 'RSA': - if (jwk.oth !== undefined) { - throw new errors_js_1.JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); - } - case 'EC': - case 'OKP': - return (0, jwk_to_key_js_1.default)({ ...jwk, alg }); - default: - throw new errors_js_1.JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); - } -} -exports.importJWK = importJWK; diff --git a/dist/node/cjs/lib/aesgcmkw.js b/dist/node/cjs/lib/aesgcmkw.js deleted file mode 100644 index c3e61e8eab..0000000000 --- a/dist/node/cjs/lib/aesgcmkw.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.unwrap = exports.wrap = void 0; -const encrypt_js_1 = require("../runtime/encrypt.js"); -const decrypt_js_1 = require("../runtime/decrypt.js"); -const iv_js_1 = require("./iv.js"); -const base64url_js_1 = require("../runtime/base64url.js"); -async function wrap(alg, key, cek, iv) { - const jweAlgorithm = alg.slice(0, 7); - iv || (iv = (0, iv_js_1.default)(jweAlgorithm)); - const { ciphertext: encryptedKey, tag } = await (0, encrypt_js_1.default)(jweAlgorithm, cek, key, iv, new Uint8Array(0)); - return { encryptedKey, iv: (0, base64url_js_1.encode)(iv), tag: (0, base64url_js_1.encode)(tag) }; -} -exports.wrap = wrap; -async function unwrap(alg, key, encryptedKey, iv, tag) { - const jweAlgorithm = alg.slice(0, 7); - return (0, decrypt_js_1.default)(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); -} -exports.unwrap = unwrap; diff --git a/dist/node/cjs/lib/buffer_utils.js b/dist/node/cjs/lib/buffer_utils.js deleted file mode 100644 index 7932178142..0000000000 --- a/dist/node/cjs/lib/buffer_utils.js +++ /dev/null @@ -1,60 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.concatKdf = exports.lengthAndInput = exports.uint32be = exports.uint64be = exports.p2s = exports.concat = exports.decoder = exports.encoder = void 0; -const digest_js_1 = require("../runtime/digest.js"); -exports.encoder = new TextEncoder(); -exports.decoder = new TextDecoder(); -const MAX_INT32 = 2 ** 32; -function concat(...buffers) { - const size = buffers.reduce((acc, { length }) => acc + length, 0); - const buf = new Uint8Array(size); - let i = 0; - buffers.forEach((buffer) => { - buf.set(buffer, i); - i += buffer.length; - }); - return buf; -} -exports.concat = concat; -function p2s(alg, p2sInput) { - return concat(exports.encoder.encode(alg), new Uint8Array([0]), p2sInput); -} -exports.p2s = p2s; -function writeUInt32BE(buf, value, offset) { - if (value < 0 || value >= MAX_INT32) { - throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); - } - buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset); -} -function uint64be(value) { - const high = Math.floor(value / MAX_INT32); - const low = value % MAX_INT32; - const buf = new Uint8Array(8); - writeUInt32BE(buf, high, 0); - writeUInt32BE(buf, low, 4); - return buf; -} -exports.uint64be = uint64be; -function uint32be(value) { - const buf = new Uint8Array(4); - writeUInt32BE(buf, value); - return buf; -} -exports.uint32be = uint32be; -function lengthAndInput(input) { - return concat(uint32be(input.length), input); -} -exports.lengthAndInput = lengthAndInput; -async function concatKdf(secret, bits, value) { - const iterations = Math.ceil((bits >> 3) / 32); - const res = new Uint8Array(iterations * 32); - for (let iter = 0; iter < iterations; iter++) { - const buf = new Uint8Array(4 + secret.length + value.length); - buf.set(uint32be(iter + 1)); - buf.set(secret, 4); - buf.set(value, 4 + secret.length); - res.set(await (0, digest_js_1.default)('sha256', buf), iter * 32); - } - return res.slice(0, bits >> 3); -} -exports.concatKdf = concatKdf; diff --git a/dist/node/cjs/lib/cek.js b/dist/node/cjs/lib/cek.js deleted file mode 100644 index e4a0133909..0000000000 --- a/dist/node/cjs/lib/cek.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.bitLength = void 0; -const errors_js_1 = require("../util/errors.js"); -const random_js_1 = require("../runtime/random.js"); -function bitLength(alg) { - switch (alg) { - case 'A128GCM': - return 128; - case 'A192GCM': - return 192; - case 'A256GCM': - case 'A128CBC-HS256': - return 256; - case 'A192CBC-HS384': - return 384; - case 'A256CBC-HS512': - return 512; - default: - throw new errors_js_1.JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -exports.bitLength = bitLength; -exports.default = (alg) => (0, random_js_1.default)(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/cjs/lib/check_iv_length.js b/dist/node/cjs/lib/check_iv_length.js deleted file mode 100644 index 3fbee85bb0..0000000000 --- a/dist/node/cjs/lib/check_iv_length.js +++ /dev/null @@ -1,10 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const errors_js_1 = require("../util/errors.js"); -const iv_js_1 = require("./iv.js"); -const checkIvLength = (enc, iv) => { - if (iv.length << 3 !== (0, iv_js_1.bitLength)(enc)) { - throw new errors_js_1.JWEInvalid('Invalid Initialization Vector length'); - } -}; -exports.default = checkIvLength; diff --git a/dist/node/cjs/lib/check_key_type.js b/dist/node/cjs/lib/check_key_type.js deleted file mode 100644 index 5035f81f6b..0000000000 --- a/dist/node/cjs/lib/check_key_type.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const invalid_key_input_js_1 = require("./invalid_key_input.js"); -const is_key_like_js_1 = require("../runtime/is_key_like.js"); -const symmetricTypeCheck = (alg, key) => { - if (key instanceof Uint8Array) - return; - if (!(0, is_key_like_js_1.default)(key)) { - throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types, 'Uint8Array')); - } - if (key.type !== 'secret') { - throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for symmetric algorithms must be of type "secret"`); - } -}; -const asymmetricTypeCheck = (alg, key, usage) => { - if (!(0, is_key_like_js_1.default)(key)) { - throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types)); - } - if (key.type === 'secret') { - throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`); - } - if (usage === 'sign' && key.type === 'public') { - throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`); - } - if (usage === 'decrypt' && key.type === 'public') { - throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`); - } - if (key.algorithm && usage === 'verify' && key.type === 'private') { - throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`); - } - if (key.algorithm && usage === 'encrypt' && key.type === 'private') { - throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`); - } -}; -const checkKeyType = (alg, key, usage) => { - const symmetric = alg.startsWith('HS') || - alg === 'dir' || - alg.startsWith('PBES2') || - /^A\d{3}(?:GCM)?KW$/.test(alg); - if (symmetric) { - symmetricTypeCheck(alg, key); - } - else { - asymmetricTypeCheck(alg, key, usage); - } -}; -exports.default = checkKeyType; diff --git a/dist/node/cjs/lib/check_p2s.js b/dist/node/cjs/lib/check_p2s.js deleted file mode 100644 index 4bdeaa766c..0000000000 --- a/dist/node/cjs/lib/check_p2s.js +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const errors_js_1 = require("../util/errors.js"); -function checkP2s(p2s) { - if (!(p2s instanceof Uint8Array) || p2s.length < 8) { - throw new errors_js_1.JWEInvalid('PBES2 Salt Input must be 8 or more octets'); - } -} -exports.default = checkP2s; diff --git a/dist/node/cjs/lib/crypto_key.js b/dist/node/cjs/lib/crypto_key.js deleted file mode 100644 index 59de5e20e3..0000000000 --- a/dist/node/cjs/lib/crypto_key.js +++ /dev/null @@ -1,163 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.checkEncCryptoKey = exports.checkSigCryptoKey = void 0; -const env_js_1 = require("../runtime/env.js"); -function unusable(name, prop = 'algorithm.name') { - return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); -} -function isAlgorithm(algorithm, name) { - return algorithm.name === name; -} -function getHashLength(hash) { - return parseInt(hash.name.slice(4), 10); -} -function getNamedCurve(alg) { - switch (alg) { - case 'ES256': - return 'P-256'; - case 'ES384': - return 'P-384'; - case 'ES512': - return 'P-521'; - default: - throw new Error('unreachable'); - } -} -function checkUsage(key, usages) { - if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { - let msg = 'CryptoKey does not support this operation, its usages must include '; - if (usages.length > 2) { - const last = usages.pop(); - msg += `one of ${usages.join(', ')}, or ${last}.`; - } - else if (usages.length === 2) { - msg += `one of ${usages[0]} or ${usages[1]}.`; - } - else { - msg += `${usages[0]}.`; - } - throw new TypeError(msg); - } -} -function checkSigCryptoKey(key, alg, ...usages) { - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': { - if (!isAlgorithm(key.algorithm, 'HMAC')) - throw unusable('HMAC'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'RS256': - case 'RS384': - case 'RS512': { - if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) - throw unusable('RSASSA-PKCS1-v1_5'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'PS256': - case 'PS384': - case 'PS512': { - if (!isAlgorithm(key.algorithm, 'RSA-PSS')) - throw unusable('RSA-PSS'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'EdDSA': { - if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { - if ((0, env_js_1.isCloudflareWorkers)()) { - if (isAlgorithm(key.algorithm, 'NODE-ED25519')) - break; - throw unusable('Ed25519, Ed448, or NODE-ED25519'); - } - throw unusable('Ed25519 or Ed448'); - } - break; - } - case 'ES256': - case 'ES384': - case 'ES512': { - if (!isAlgorithm(key.algorithm, 'ECDSA')) - throw unusable('ECDSA'); - const expected = getNamedCurve(alg); - const actual = key.algorithm.namedCurve; - if (actual !== expected) - throw unusable(expected, 'algorithm.namedCurve'); - break; - } - default: - throw new TypeError('CryptoKey does not support this operation'); - } - checkUsage(key, usages); -} -exports.checkSigCryptoKey = checkSigCryptoKey; -function checkEncCryptoKey(key, alg, ...usages) { - switch (alg) { - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': { - if (!isAlgorithm(key.algorithm, 'AES-GCM')) - throw unusable('AES-GCM'); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, 'algorithm.length'); - break; - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - if (!isAlgorithm(key.algorithm, 'AES-KW')) - throw unusable('AES-KW'); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, 'algorithm.length'); - break; - } - case 'ECDH': { - switch (key.algorithm.name) { - case 'ECDH': - case 'X25519': - case 'X448': - break; - default: - throw unusable('ECDH, X25519, or X448'); - } - break; - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': - if (!isAlgorithm(key.algorithm, 'PBKDF2')) - throw unusable('PBKDF2'); - break; - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) - throw unusable('RSA-OAEP'); - const expected = parseInt(alg.slice(9), 10) || 1; - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - default: - throw new TypeError('CryptoKey does not support this operation'); - } - checkUsage(key, usages); -} -exports.checkEncCryptoKey = checkEncCryptoKey; diff --git a/dist/node/cjs/lib/decrypt_key_management.js b/dist/node/cjs/lib/decrypt_key_management.js deleted file mode 100644 index fb2aa37698..0000000000 --- a/dist/node/cjs/lib/decrypt_key_management.js +++ /dev/null @@ -1,100 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const aeskw_js_1 = require("../runtime/aeskw.js"); -const ECDH = require("../runtime/ecdhes.js"); -const pbes2kw_js_1 = require("../runtime/pbes2kw.js"); -const rsaes_js_1 = require("../runtime/rsaes.js"); -const base64url_js_1 = require("../runtime/base64url.js"); -const errors_js_1 = require("../util/errors.js"); -const cek_js_1 = require("../lib/cek.js"); -const import_js_1 = require("../key/import.js"); -const check_key_type_js_1 = require("./check_key_type.js"); -const is_object_js_1 = require("./is_object.js"); -const aesgcmkw_js_1 = require("./aesgcmkw.js"); -async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { - (0, check_key_type_js_1.default)(alg, key, 'decrypt'); - switch (alg) { - case 'dir': { - if (encryptedKey !== undefined) - throw new errors_js_1.JWEInvalid('Encountered unexpected JWE Encrypted Key'); - return key; - } - case 'ECDH-ES': - if (encryptedKey !== undefined) - throw new errors_js_1.JWEInvalid('Encountered unexpected JWE Encrypted Key'); - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - if (!(0, is_object_js_1.default)(joseHeader.epk)) - throw new errors_js_1.JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); - if (!ECDH.ecdhAllowed(key)) - throw new errors_js_1.JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); - const epk = await (0, import_js_1.importJWK)(joseHeader.epk, alg); - let partyUInfo; - let partyVInfo; - if (joseHeader.apu !== undefined) { - if (typeof joseHeader.apu !== 'string') - throw new errors_js_1.JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); - partyUInfo = (0, base64url_js_1.decode)(joseHeader.apu); - } - if (joseHeader.apv !== undefined) { - if (typeof joseHeader.apv !== 'string') - throw new errors_js_1.JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); - partyVInfo = (0, base64url_js_1.decode)(joseHeader.apv); - } - const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); - if (alg === 'ECDH-ES') - return sharedSecret; - if (encryptedKey === undefined) - throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); - return (0, aeskw_js_1.unwrap)(alg.slice(-6), sharedSecret, encryptedKey); - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - if (encryptedKey === undefined) - throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); - return (0, rsaes_js_1.decrypt)(alg, key, encryptedKey); - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - if (encryptedKey === undefined) - throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); - if (typeof joseHeader.p2c !== 'number') - throw new errors_js_1.JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); - const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 10000; - if (joseHeader.p2c > p2cLimit) - throw new errors_js_1.JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); - if (typeof joseHeader.p2s !== 'string') - throw new errors_js_1.JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); - return (0, pbes2kw_js_1.decrypt)(alg, key, encryptedKey, joseHeader.p2c, (0, base64url_js_1.decode)(joseHeader.p2s)); - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - if (encryptedKey === undefined) - throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); - return (0, aeskw_js_1.unwrap)(alg, key, encryptedKey); - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - if (encryptedKey === undefined) - throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); - if (typeof joseHeader.iv !== 'string') - throw new errors_js_1.JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); - if (typeof joseHeader.tag !== 'string') - throw new errors_js_1.JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); - const iv = (0, base64url_js_1.decode)(joseHeader.iv); - const tag = (0, base64url_js_1.decode)(joseHeader.tag); - return (0, aesgcmkw_js_1.unwrap)(alg, key, encryptedKey, iv, tag); - } - default: { - throw new errors_js_1.JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } -} -exports.default = decryptKeyManagement; diff --git a/dist/node/cjs/lib/encrypt_key_management.js b/dist/node/cjs/lib/encrypt_key_management.js deleted file mode 100644 index 709364b064..0000000000 --- a/dist/node/cjs/lib/encrypt_key_management.js +++ /dev/null @@ -1,89 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const aeskw_js_1 = require("../runtime/aeskw.js"); -const ECDH = require("../runtime/ecdhes.js"); -const pbes2kw_js_1 = require("../runtime/pbes2kw.js"); -const rsaes_js_1 = require("../runtime/rsaes.js"); -const base64url_js_1 = require("../runtime/base64url.js"); -const cek_js_1 = require("../lib/cek.js"); -const errors_js_1 = require("../util/errors.js"); -const export_js_1 = require("../key/export.js"); -const check_key_type_js_1 = require("./check_key_type.js"); -const aesgcmkw_js_1 = require("./aesgcmkw.js"); -async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { - let encryptedKey; - let parameters; - let cek; - (0, check_key_type_js_1.default)(alg, key, 'encrypt'); - switch (alg) { - case 'dir': { - cek = key; - break; - } - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - if (!ECDH.ecdhAllowed(key)) { - throw new errors_js_1.JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); - } - const { apu, apv } = providedParameters; - let { epk: ephemeralKey } = providedParameters; - ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey); - const { x, y, crv, kty } = await (0, export_js_1.exportJWK)(ephemeralKey); - const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); - parameters = { epk: { x, crv, kty } }; - if (kty === 'EC') - parameters.epk.y = y; - if (apu) - parameters.apu = (0, base64url_js_1.encode)(apu); - if (apv) - parameters.apv = (0, base64url_js_1.encode)(apv); - if (alg === 'ECDH-ES') { - cek = sharedSecret; - break; - } - cek = providedCek || (0, cek_js_1.default)(enc); - const kwAlg = alg.slice(-6); - encryptedKey = await (0, aeskw_js_1.wrap)(kwAlg, sharedSecret, cek); - break; - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - cek = providedCek || (0, cek_js_1.default)(enc); - encryptedKey = await (0, rsaes_js_1.encrypt)(alg, key, cek); - break; - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - cek = providedCek || (0, cek_js_1.default)(enc); - const { p2c, p2s } = providedParameters; - ({ encryptedKey, ...parameters } = await (0, pbes2kw_js_1.encrypt)(alg, key, cek, p2c, p2s)); - break; - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - cek = providedCek || (0, cek_js_1.default)(enc); - encryptedKey = await (0, aeskw_js_1.wrap)(alg, key, cek); - break; - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - cek = providedCek || (0, cek_js_1.default)(enc); - const { iv } = providedParameters; - ({ encryptedKey, ...parameters } = await (0, aesgcmkw_js_1.wrap)(alg, key, cek, iv)); - break; - } - default: { - throw new errors_js_1.JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } - return { cek, encryptedKey, parameters }; -} -exports.default = encryptKeyManagement; diff --git a/dist/node/cjs/lib/epoch.js b/dist/node/cjs/lib/epoch.js deleted file mode 100644 index a0792b4f7f..0000000000 --- a/dist/node/cjs/lib/epoch.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = (date) => Math.floor(date.getTime() / 1000); diff --git a/dist/node/cjs/lib/invalid_key_input.js b/dist/node/cjs/lib/invalid_key_input.js deleted file mode 100644 index e1d5fc1c55..0000000000 --- a/dist/node/cjs/lib/invalid_key_input.js +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.withAlg = void 0; -function message(msg, actual, ...types) { - if (types.length > 2) { - const last = types.pop(); - msg += `one of type ${types.join(', ')}, or ${last}.`; - } - else if (types.length === 2) { - msg += `one of type ${types[0]} or ${types[1]}.`; - } - else { - msg += `of type ${types[0]}.`; - } - if (actual == null) { - msg += ` Received ${actual}`; - } - else if (typeof actual === 'function' && actual.name) { - msg += ` Received function ${actual.name}`; - } - else if (typeof actual === 'object' && actual != null) { - if (actual.constructor && actual.constructor.name) { - msg += ` Received an instance of ${actual.constructor.name}`; - } - } - return msg; -} -exports.default = (actual, ...types) => { - return message('Key must be ', actual, ...types); -}; -function withAlg(alg, actual, ...types) { - return message(`Key for the ${alg} algorithm must be `, actual, ...types); -} -exports.withAlg = withAlg; diff --git a/dist/node/cjs/lib/is_disjoint.js b/dist/node/cjs/lib/is_disjoint.js deleted file mode 100644 index 66c2fc6c82..0000000000 --- a/dist/node/cjs/lib/is_disjoint.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const isDisjoint = (...headers) => { - const sources = headers.filter(Boolean); - if (sources.length === 0 || sources.length === 1) { - return true; - } - let acc; - for (const header of sources) { - const parameters = Object.keys(header); - if (!acc || acc.size === 0) { - acc = new Set(parameters); - continue; - } - for (const parameter of parameters) { - if (acc.has(parameter)) { - return false; - } - acc.add(parameter); - } - } - return true; -}; -exports.default = isDisjoint; diff --git a/dist/node/cjs/lib/is_object.js b/dist/node/cjs/lib/is_object.js deleted file mode 100644 index 870938b59b..0000000000 --- a/dist/node/cjs/lib/is_object.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function isObjectLike(value) { - return typeof value === 'object' && value !== null; -} -function isObject(input) { - if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { - return false; - } - if (Object.getPrototypeOf(input) === null) { - return true; - } - let proto = input; - while (Object.getPrototypeOf(proto) !== null) { - proto = Object.getPrototypeOf(proto); - } - return Object.getPrototypeOf(input) === proto; -} -exports.default = isObject; diff --git a/dist/node/cjs/lib/iv.js b/dist/node/cjs/lib/iv.js deleted file mode 100644 index db7d3a5912..0000000000 --- a/dist/node/cjs/lib/iv.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.bitLength = void 0; -const errors_js_1 = require("../util/errors.js"); -const random_js_1 = require("../runtime/random.js"); -function bitLength(alg) { - switch (alg) { - case 'A128GCM': - case 'A128GCMKW': - case 'A192GCM': - case 'A192GCMKW': - case 'A256GCM': - case 'A256GCMKW': - return 96; - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return 128; - default: - throw new errors_js_1.JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -exports.bitLength = bitLength; -exports.default = (alg) => (0, random_js_1.default)(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/cjs/lib/jwt_claims_set.js b/dist/node/cjs/lib/jwt_claims_set.js deleted file mode 100644 index ce5e0ebbe3..0000000000 --- a/dist/node/cjs/lib/jwt_claims_set.js +++ /dev/null @@ -1,93 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const errors_js_1 = require("../util/errors.js"); -const buffer_utils_js_1 = require("./buffer_utils.js"); -const epoch_js_1 = require("./epoch.js"); -const secs_js_1 = require("./secs.js"); -const is_object_js_1 = require("./is_object.js"); -const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ''); -const checkAudiencePresence = (audPayload, audOption) => { - if (typeof audPayload === 'string') { - return audOption.includes(audPayload); - } - if (Array.isArray(audPayload)) { - return audOption.some(Set.prototype.has.bind(new Set(audPayload))); - } - return false; -}; -exports.default = (protectedHeader, encodedPayload, options = {}) => { - const { typ } = options; - if (typ && - (typeof protectedHeader.typ !== 'string' || - normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { - throw new errors_js_1.JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed'); - } - let payload; - try { - payload = JSON.parse(buffer_utils_js_1.decoder.decode(encodedPayload)); - } - catch { - } - if (!(0, is_object_js_1.default)(payload)) { - throw new errors_js_1.JWTInvalid('JWT Claims Set must be a top-level JSON object'); - } - const { issuer } = options; - if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { - throw new errors_js_1.JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed'); - } - const { subject } = options; - if (subject && payload.sub !== subject) { - throw new errors_js_1.JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed'); - } - const { audience } = options; - if (audience && - !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) { - throw new errors_js_1.JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed'); - } - let tolerance; - switch (typeof options.clockTolerance) { - case 'string': - tolerance = (0, secs_js_1.default)(options.clockTolerance); - break; - case 'number': - tolerance = options.clockTolerance; - break; - case 'undefined': - tolerance = 0; - break; - default: - throw new TypeError('Invalid clockTolerance option type'); - } - const { currentDate } = options; - const now = (0, epoch_js_1.default)(currentDate || new Date()); - if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { - throw new errors_js_1.JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid'); - } - if (payload.nbf !== undefined) { - if (typeof payload.nbf !== 'number') { - throw new errors_js_1.JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid'); - } - if (payload.nbf > now + tolerance) { - throw new errors_js_1.JWTClaimValidationFailed('"nbf" claim timestamp check failed', 'nbf', 'check_failed'); - } - } - if (payload.exp !== undefined) { - if (typeof payload.exp !== 'number') { - throw new errors_js_1.JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid'); - } - if (payload.exp <= now - tolerance) { - throw new errors_js_1.JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed'); - } - } - if (options.maxTokenAge) { - const age = now - payload.iat; - const max = typeof options.maxTokenAge === 'number' ? options.maxTokenAge : (0, secs_js_1.default)(options.maxTokenAge); - if (age - tolerance > max) { - throw new errors_js_1.JWTExpired('"iat" claim timestamp check failed (too far in the past)', 'iat', 'check_failed'); - } - if (age < 0 - tolerance) { - throw new errors_js_1.JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed'); - } - } - return payload; -}; diff --git a/dist/node/cjs/lib/secs.js b/dist/node/cjs/lib/secs.js deleted file mode 100644 index f1b6a0c15d..0000000000 --- a/dist/node/cjs/lib/secs.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const minute = 60; -const hour = minute * 60; -const day = hour * 24; -const week = day * 7; -const year = day * 365.25; -const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; -exports.default = (str) => { - const matched = REGEX.exec(str); - if (!matched) { - throw new TypeError('Invalid time period format'); - } - const value = parseFloat(matched[1]); - const unit = matched[2].toLowerCase(); - switch (unit) { - case 'sec': - case 'secs': - case 'second': - case 'seconds': - case 's': - return Math.round(value); - case 'minute': - case 'minutes': - case 'min': - case 'mins': - case 'm': - return Math.round(value * minute); - case 'hour': - case 'hours': - case 'hr': - case 'hrs': - case 'h': - return Math.round(value * hour); - case 'day': - case 'days': - case 'd': - return Math.round(value * day); - case 'week': - case 'weeks': - case 'w': - return Math.round(value * week); - default: - return Math.round(value * year); - } -}; diff --git a/dist/node/cjs/lib/validate_algorithms.js b/dist/node/cjs/lib/validate_algorithms.js deleted file mode 100644 index 29f4e80df9..0000000000 --- a/dist/node/cjs/lib/validate_algorithms.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const validateAlgorithms = (option, algorithms) => { - if (algorithms !== undefined && - (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) { - throw new TypeError(`"${option}" option must be an array of strings`); - } - if (!algorithms) { - return undefined; - } - return new Set(algorithms); -}; -exports.default = validateAlgorithms; diff --git a/dist/node/cjs/lib/validate_crit.js b/dist/node/cjs/lib/validate_crit.js deleted file mode 100644 index b0229e3b72..0000000000 --- a/dist/node/cjs/lib/validate_crit.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const errors_js_1 = require("../util/errors.js"); -function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { - if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { - throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); - } - if (!protectedHeader || protectedHeader.crit === undefined) { - return new Set(); - } - if (!Array.isArray(protectedHeader.crit) || - protectedHeader.crit.length === 0 || - protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) { - throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); - } - let recognized; - if (recognizedOption !== undefined) { - recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); - } - else { - recognized = recognizedDefault; - } - for (const parameter of protectedHeader.crit) { - if (!recognized.has(parameter)) { - throw new errors_js_1.JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); - } - if (joseHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" is missing`); - } - else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); - } - } - return new Set(protectedHeader.crit); -} -exports.default = validateCrit; diff --git a/dist/node/cjs/runtime/aeskw.js b/dist/node/cjs/runtime/aeskw.js deleted file mode 100644 index ca26086881..0000000000 --- a/dist/node/cjs/runtime/aeskw.js +++ /dev/null @@ -1,55 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.unwrap = exports.wrap = void 0; -const buffer_1 = require("buffer"); -const crypto_1 = require("crypto"); -const errors_js_1 = require("../util/errors.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const crypto_key_js_1 = require("../lib/crypto_key.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const ciphers_js_1 = require("./ciphers.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -function checkKeySize(key, alg) { - if (key.symmetricKeySize << 3 !== parseInt(alg.slice(1, 4), 10)) { - throw new TypeError(`Invalid key size for alg: ${alg}`); - } -} -function ensureKeyObject(key, alg, usage) { - if ((0, is_key_object_js_1.default)(key)) { - return key; - } - if (key instanceof Uint8Array) { - return (0, crypto_1.createSecretKey)(key); - } - if ((0, webcrypto_js_1.isCryptoKey)(key)) { - (0, crypto_key_js_1.checkEncCryptoKey)(key, alg, usage); - return crypto_1.KeyObject.from(key); - } - throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); -} -const wrap = (alg, key, cek) => { - const size = parseInt(alg.slice(1, 4), 10); - const algorithm = `aes${size}-wrap`; - if (!(0, ciphers_js_1.default)(algorithm)) { - throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } - const keyObject = ensureKeyObject(key, alg, 'wrapKey'); - checkKeySize(keyObject, alg); - const cipher = (0, crypto_1.createCipheriv)(algorithm, keyObject, buffer_1.Buffer.alloc(8, 0xa6)); - return (0, buffer_utils_js_1.concat)(cipher.update(cek), cipher.final()); -}; -exports.wrap = wrap; -const unwrap = (alg, key, encryptedKey) => { - const size = parseInt(alg.slice(1, 4), 10); - const algorithm = `aes${size}-wrap`; - if (!(0, ciphers_js_1.default)(algorithm)) { - throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } - const keyObject = ensureKeyObject(key, alg, 'unwrapKey'); - checkKeySize(keyObject, alg); - const cipher = (0, crypto_1.createDecipheriv)(algorithm, keyObject, buffer_1.Buffer.alloc(8, 0xa6)); - return (0, buffer_utils_js_1.concat)(cipher.update(encryptedKey), cipher.final()); -}; -exports.unwrap = unwrap; diff --git a/dist/node/cjs/runtime/asn1.js b/dist/node/cjs/runtime/asn1.js deleted file mode 100644 index 3695dae247..0000000000 --- a/dist/node/cjs/runtime/asn1.js +++ /dev/null @@ -1,54 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.fromX509 = exports.fromSPKI = exports.fromPKCS8 = exports.toPKCS8 = exports.toSPKI = void 0; -const crypto_1 = require("crypto"); -const buffer_1 = require("buffer"); -const webcrypto_js_1 = require("./webcrypto.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -const genericExport = (keyType, keyFormat, key) => { - let keyObject; - if ((0, webcrypto_js_1.isCryptoKey)(key)) { - if (!key.extractable) { - throw new TypeError('CryptoKey is not extractable'); - } - keyObject = crypto_1.KeyObject.from(key); - } - else if ((0, is_key_object_js_1.default)(key)) { - keyObject = key; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types)); - } - if (keyObject.type !== keyType) { - throw new TypeError(`key is not a ${keyType} key`); - } - return keyObject.export({ format: 'pem', type: keyFormat }); -}; -const toSPKI = (key) => { - return genericExport('public', 'spki', key); -}; -exports.toSPKI = toSPKI; -const toPKCS8 = (key) => { - return genericExport('private', 'pkcs8', key); -}; -exports.toPKCS8 = toPKCS8; -const fromPKCS8 = (pem) => (0, crypto_1.createPrivateKey)({ - key: buffer_1.Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, ''), 'base64'), - type: 'pkcs8', - format: 'der', -}); -exports.fromPKCS8 = fromPKCS8; -const fromSPKI = (pem) => (0, crypto_1.createPublicKey)({ - key: buffer_1.Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, ''), 'base64'), - type: 'spki', - format: 'der', -}); -exports.fromSPKI = fromSPKI; -const fromX509 = (pem) => (0, crypto_1.createPublicKey)({ - key: pem, - type: 'spki', - format: 'pem', -}); -exports.fromX509 = fromX509; diff --git a/dist/node/cjs/runtime/asn1_sequence_decoder.js b/dist/node/cjs/runtime/asn1_sequence_decoder.js deleted file mode 100644 index 4f96522335..0000000000 --- a/dist/node/cjs/runtime/asn1_sequence_decoder.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const tagInteger = 0x02; -const tagSequence = 0x30; -class Asn1SequenceDecoder { - constructor(buffer) { - if (buffer[0] !== tagSequence) { - throw new TypeError(); - } - this.buffer = buffer; - this.offset = 1; - const len = this.decodeLength(); - if (len !== buffer.length - this.offset) { - throw new TypeError(); - } - } - decodeLength() { - let length = this.buffer[this.offset++]; - if (length & 0x80) { - const nBytes = length & ~0x80; - length = 0; - for (let i = 0; i < nBytes; i++) - length = (length << 8) | this.buffer[this.offset + i]; - this.offset += nBytes; - } - return length; - } - unsignedInteger() { - if (this.buffer[this.offset++] !== tagInteger) { - throw new TypeError(); - } - let length = this.decodeLength(); - if (this.buffer[this.offset] === 0) { - this.offset++; - length--; - } - const result = this.buffer.slice(this.offset, this.offset + length); - this.offset += length; - return result; - } - end() { - if (this.offset !== this.buffer.length) { - throw new TypeError(); - } - } -} -exports.default = Asn1SequenceDecoder; diff --git a/dist/node/cjs/runtime/asn1_sequence_encoder.js b/dist/node/cjs/runtime/asn1_sequence_encoder.js deleted file mode 100644 index 8b71d6dc28..0000000000 --- a/dist/node/cjs/runtime/asn1_sequence_encoder.js +++ /dev/null @@ -1,91 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const buffer_1 = require("buffer"); -const errors_js_1 = require("../util/errors.js"); -const tagInteger = 0x02; -const tagBitStr = 0x03; -const tagOctStr = 0x04; -const tagSequence = 0x30; -const bZero = buffer_1.Buffer.from([0x00]); -const bTagInteger = buffer_1.Buffer.from([tagInteger]); -const bTagBitStr = buffer_1.Buffer.from([tagBitStr]); -const bTagSequence = buffer_1.Buffer.from([tagSequence]); -const bTagOctStr = buffer_1.Buffer.from([tagOctStr]); -const encodeLength = (len) => { - if (len < 128) - return buffer_1.Buffer.from([len]); - const buffer = buffer_1.Buffer.alloc(5); - buffer.writeUInt32BE(len, 1); - let offset = 1; - while (buffer[offset] === 0) - offset++; - buffer[offset - 1] = 0x80 | (5 - offset); - return buffer.slice(offset - 1); -}; -const oids = new Map([ - ['P-256', buffer_1.Buffer.from('06 08 2A 86 48 CE 3D 03 01 07'.replace(/ /g, ''), 'hex')], - ['secp256k1', buffer_1.Buffer.from('06 05 2B 81 04 00 0A'.replace(/ /g, ''), 'hex')], - ['P-384', buffer_1.Buffer.from('06 05 2B 81 04 00 22'.replace(/ /g, ''), 'hex')], - ['P-521', buffer_1.Buffer.from('06 05 2B 81 04 00 23'.replace(/ /g, ''), 'hex')], - ['ecPublicKey', buffer_1.Buffer.from('06 07 2A 86 48 CE 3D 02 01'.replace(/ /g, ''), 'hex')], - ['X25519', buffer_1.Buffer.from('06 03 2B 65 6E'.replace(/ /g, ''), 'hex')], - ['X448', buffer_1.Buffer.from('06 03 2B 65 6F'.replace(/ /g, ''), 'hex')], - ['Ed25519', buffer_1.Buffer.from('06 03 2B 65 70'.replace(/ /g, ''), 'hex')], - ['Ed448', buffer_1.Buffer.from('06 03 2B 65 71'.replace(/ /g, ''), 'hex')], -]); -class DumbAsn1Encoder { - constructor() { - this.length = 0; - this.elements = []; - } - oidFor(oid) { - const bOid = oids.get(oid); - if (!bOid) { - throw new errors_js_1.JOSENotSupported('Invalid or unsupported OID'); - } - this.elements.push(bOid); - this.length += bOid.length; - } - zero() { - this.elements.push(bTagInteger, buffer_1.Buffer.from([0x01]), bZero); - this.length += 3; - } - one() { - this.elements.push(bTagInteger, buffer_1.Buffer.from([0x01]), buffer_1.Buffer.from([0x01])); - this.length += 3; - } - unsignedInteger(integer) { - if (integer[0] & 0x80) { - const len = encodeLength(integer.length + 1); - this.elements.push(bTagInteger, len, bZero, integer); - this.length += 2 + len.length + integer.length; - } - else { - let i = 0; - while (integer[i] === 0 && (integer[i + 1] & 0x80) === 0) - i++; - const len = encodeLength(integer.length - i); - this.elements.push(bTagInteger, encodeLength(integer.length - i), integer.slice(i)); - this.length += 1 + len.length + integer.length - i; - } - } - octStr(octStr) { - const len = encodeLength(octStr.length); - this.elements.push(bTagOctStr, encodeLength(octStr.length), octStr); - this.length += 1 + len.length + octStr.length; - } - bitStr(bitS) { - const len = encodeLength(bitS.length + 1); - this.elements.push(bTagBitStr, encodeLength(bitS.length + 1), bZero, bitS); - this.length += 1 + len.length + bitS.length + 1; - } - add(seq) { - this.elements.push(seq); - this.length += seq.length; - } - end(tag = bTagSequence) { - const len = encodeLength(this.length); - return buffer_1.Buffer.concat([tag, len, ...this.elements], 1 + len.length + this.length); - } -} -exports.default = DumbAsn1Encoder; diff --git a/dist/node/cjs/runtime/base64url.js b/dist/node/cjs/runtime/base64url.js deleted file mode 100644 index 3a38a4ba74..0000000000 --- a/dist/node/cjs/runtime/base64url.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.decode = exports.encode = exports.encodeBase64 = exports.decodeBase64 = void 0; -const buffer_1 = require("buffer"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -let encode; -exports.encode = encode; -function normalize(input) { - let encoded = input; - if (encoded instanceof Uint8Array) { - encoded = buffer_utils_js_1.decoder.decode(encoded); - } - return encoded; -} -if (buffer_1.Buffer.isEncoding('base64url')) { - exports.encode = encode = (input) => buffer_1.Buffer.from(input).toString('base64url'); -} -else { - exports.encode = encode = (input) => buffer_1.Buffer.from(input).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); -} -const decodeBase64 = (input) => buffer_1.Buffer.from(input, 'base64'); -exports.decodeBase64 = decodeBase64; -const encodeBase64 = (input) => buffer_1.Buffer.from(input).toString('base64'); -exports.encodeBase64 = encodeBase64; -const decode = (input) => buffer_1.Buffer.from(normalize(input), 'base64'); -exports.decode = decode; diff --git a/dist/node/cjs/runtime/cbc_tag.js b/dist/node/cjs/runtime/cbc_tag.js deleted file mode 100644 index 03412c2cfb..0000000000 --- a/dist/node/cjs/runtime/cbc_tag.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -function cbcTag(aad, iv, ciphertext, macSize, macKey, keySize) { - const macData = (0, buffer_utils_js_1.concat)(aad, iv, ciphertext, (0, buffer_utils_js_1.uint64be)(aad.length << 3)); - const hmac = (0, crypto_1.createHmac)(`sha${macSize}`, macKey); - hmac.update(macData); - return hmac.digest().slice(0, keySize >> 3); -} -exports.default = cbcTag; diff --git a/dist/node/cjs/runtime/check_cek_length.js b/dist/node/cjs/runtime/check_cek_length.js deleted file mode 100644 index 5192e750db..0000000000 --- a/dist/node/cjs/runtime/check_cek_length.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const errors_js_1 = require("../util/errors.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const checkCekLength = (enc, cek) => { - let expected; - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - expected = parseInt(enc.slice(-3), 10); - break; - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - expected = parseInt(enc.slice(1, 4), 10); - break; - default: - throw new errors_js_1.JOSENotSupported(`Content Encryption Algorithm ${enc} is not supported either by JOSE or your javascript runtime`); - } - if (cek instanceof Uint8Array) { - const actual = cek.byteLength << 3; - if (actual !== expected) { - throw new errors_js_1.JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); - } - return; - } - if ((0, is_key_object_js_1.default)(cek) && cek.type === 'secret') { - const actual = cek.symmetricKeySize << 3; - if (actual !== expected) { - throw new errors_js_1.JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); - } - return; - } - throw new TypeError('Invalid Content Encryption Key type'); -}; -exports.default = checkCekLength; diff --git a/dist/node/cjs/runtime/check_modulus_length.js b/dist/node/cjs/runtime/check_modulus_length.js deleted file mode 100644 index 72c670eba3..0000000000 --- a/dist/node/cjs/runtime/check_modulus_length.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.setModulusLength = exports.weakMap = void 0; -exports.weakMap = new WeakMap(); -const getLength = (buf, index) => { - let len = buf.readUInt8(1); - if ((len & 0x80) === 0) { - if (index === 0) { - return len; - } - return getLength(buf.subarray(2 + len), index - 1); - } - const num = len & 0x7f; - len = 0; - for (let i = 0; i < num; i++) { - len <<= 8; - const j = buf.readUInt8(2 + i); - len |= j; - } - if (index === 0) { - return len; - } - return getLength(buf.subarray(2 + len), index - 1); -}; -const getLengthOfSeqIndex = (sequence, index) => { - const len = sequence.readUInt8(1); - if ((len & 0x80) === 0) { - return getLength(sequence.subarray(2), index); - } - const num = len & 0x7f; - return getLength(sequence.subarray(2 + num), index); -}; -const getModulusLength = (key) => { - var _a, _b; - if (exports.weakMap.has(key)) { - return exports.weakMap.get(key); - } - const modulusLength = (_b = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.modulusLength) !== null && _b !== void 0 ? _b : (getLengthOfSeqIndex(key.export({ format: 'der', type: 'pkcs1' }), key.type === 'private' ? 1 : 0) - - 1) << - 3; - exports.weakMap.set(key, modulusLength); - return modulusLength; -}; -const setModulusLength = (keyObject, modulusLength) => { - exports.weakMap.set(keyObject, modulusLength); -}; -exports.setModulusLength = setModulusLength; -exports.default = (key, alg) => { - if (getModulusLength(key) < 2048) { - throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); - } -}; diff --git a/dist/node/cjs/runtime/ciphers.js b/dist/node/cjs/runtime/ciphers.js deleted file mode 100644 index e004c84562..0000000000 --- a/dist/node/cjs/runtime/ciphers.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -let ciphers; -exports.default = (algorithm) => { - ciphers || (ciphers = new Set((0, crypto_1.getCiphers)())); - return ciphers.has(algorithm); -}; diff --git a/dist/node/cjs/runtime/decrypt.js b/dist/node/cjs/runtime/decrypt.js deleted file mode 100644 index 6e0de6d472..0000000000 --- a/dist/node/cjs/runtime/decrypt.js +++ /dev/null @@ -1,97 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const check_iv_length_js_1 = require("../lib/check_iv_length.js"); -const check_cek_length_js_1 = require("./check_cek_length.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const errors_js_1 = require("../util/errors.js"); -const timing_safe_equal_js_1 = require("./timing_safe_equal.js"); -const cbc_tag_js_1 = require("./cbc_tag.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const crypto_key_js_1 = require("../lib/crypto_key.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const ciphers_js_1 = require("./ciphers.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - if ((0, is_key_object_js_1.default)(cek)) { - cek = cek.export(); - } - const encKey = cek.subarray(keySize >> 3); - const macKey = cek.subarray(0, keySize >> 3); - const macSize = parseInt(enc.slice(-3), 10); - const algorithm = `aes-${keySize}-cbc`; - if (!(0, ciphers_js_1.default)(algorithm)) { - throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - const expectedTag = (0, cbc_tag_js_1.default)(aad, iv, ciphertext, macSize, macKey, keySize); - let macCheckPassed; - try { - macCheckPassed = (0, timing_safe_equal_js_1.default)(tag, expectedTag); - } - catch { - } - if (!macCheckPassed) { - throw new errors_js_1.JWEDecryptionFailed(); - } - let plaintext; - try { - const decipher = (0, crypto_1.createDecipheriv)(algorithm, encKey, iv); - plaintext = (0, buffer_utils_js_1.concat)(decipher.update(ciphertext), decipher.final()); - } - catch { - } - if (!plaintext) { - throw new errors_js_1.JWEDecryptionFailed(); - } - return plaintext; -} -function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - const algorithm = `aes-${keySize}-gcm`; - if (!(0, ciphers_js_1.default)(algorithm)) { - throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - try { - const decipher = (0, crypto_1.createDecipheriv)(algorithm, cek, iv, { authTagLength: 16 }); - decipher.setAuthTag(tag); - if (aad.byteLength) { - decipher.setAAD(aad, { plaintextLength: ciphertext.length }); - } - const plaintext = decipher.update(ciphertext); - decipher.final(); - return plaintext; - } - catch { - throw new errors_js_1.JWEDecryptionFailed(); - } -} -const decrypt = (enc, cek, ciphertext, iv, tag, aad) => { - let key; - if ((0, webcrypto_js_1.isCryptoKey)(cek)) { - (0, crypto_key_js_1.checkEncCryptoKey)(cek, enc, 'decrypt'); - key = crypto_1.KeyObject.from(cek); - } - else if (cek instanceof Uint8Array || (0, is_key_object_js_1.default)(cek)) { - key = cek; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(cek, ...is_key_like_js_1.types, 'Uint8Array')); - } - (0, check_cek_length_js_1.default)(enc, key); - (0, check_iv_length_js_1.default)(enc, iv); - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return cbcDecrypt(enc, key, ciphertext, iv, tag, aad); - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - return gcmDecrypt(enc, key, ciphertext, iv, tag, aad); - default: - throw new errors_js_1.JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); - } -}; -exports.default = decrypt; diff --git a/dist/node/cjs/runtime/digest.js b/dist/node/cjs/runtime/digest.js deleted file mode 100644 index 13c194a8ed..0000000000 --- a/dist/node/cjs/runtime/digest.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const digest = (algorithm, data) => (0, crypto_1.createHash)(algorithm).update(data).digest(); -exports.default = digest; diff --git a/dist/node/cjs/runtime/dsa_digest.js b/dist/node/cjs/runtime/dsa_digest.js deleted file mode 100644 index fde4883e81..0000000000 --- a/dist/node/cjs/runtime/dsa_digest.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const errors_js_1 = require("../util/errors.js"); -function dsaDigest(alg) { - switch (alg) { - case 'PS256': - case 'RS256': - case 'ES256': - case 'ES256K': - return 'sha256'; - case 'PS384': - case 'RS384': - case 'ES384': - return 'sha384'; - case 'PS512': - case 'RS512': - case 'ES512': - return 'sha512'; - case 'EdDSA': - return undefined; - default: - throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} -exports.default = dsaDigest; diff --git a/dist/node/cjs/runtime/ecdhes.js b/dist/node/cjs/runtime/ecdhes.js deleted file mode 100644 index d769af7603..0000000000 --- a/dist/node/cjs/runtime/ecdhes.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ecdhAllowed = exports.generateEpk = exports.deriveKey = void 0; -const crypto_1 = require("crypto"); -const util_1 = require("util"); -const get_named_curve_js_1 = require("./get_named_curve.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const errors_js_1 = require("../util/errors.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const crypto_key_js_1 = require("../lib/crypto_key.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -const generateKeyPair = (0, util_1.promisify)(crypto_1.generateKeyPair); -async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { - let publicKey; - if ((0, webcrypto_js_1.isCryptoKey)(publicKee)) { - (0, crypto_key_js_1.checkEncCryptoKey)(publicKee, 'ECDH'); - publicKey = crypto_1.KeyObject.from(publicKee); - } - else if ((0, is_key_object_js_1.default)(publicKee)) { - publicKey = publicKee; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(publicKee, ...is_key_like_js_1.types)); - } - let privateKey; - if ((0, webcrypto_js_1.isCryptoKey)(privateKee)) { - (0, crypto_key_js_1.checkEncCryptoKey)(privateKee, 'ECDH', 'deriveBits'); - privateKey = crypto_1.KeyObject.from(privateKee); - } - else if ((0, is_key_object_js_1.default)(privateKee)) { - privateKey = privateKee; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(privateKee, ...is_key_like_js_1.types)); - } - const value = (0, buffer_utils_js_1.concat)((0, buffer_utils_js_1.lengthAndInput)(buffer_utils_js_1.encoder.encode(algorithm)), (0, buffer_utils_js_1.lengthAndInput)(apu), (0, buffer_utils_js_1.lengthAndInput)(apv), (0, buffer_utils_js_1.uint32be)(keyLength)); - const sharedSecret = (0, crypto_1.diffieHellman)({ privateKey, publicKey }); - return (0, buffer_utils_js_1.concatKdf)(sharedSecret, keyLength, value); -} -exports.deriveKey = deriveKey; -async function generateEpk(kee) { - let key; - if ((0, webcrypto_js_1.isCryptoKey)(kee)) { - key = crypto_1.KeyObject.from(kee); - } - else if ((0, is_key_object_js_1.default)(kee)) { - key = kee; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(kee, ...is_key_like_js_1.types)); - } - switch (key.asymmetricKeyType) { - case 'x25519': - return generateKeyPair('x25519'); - case 'x448': { - return generateKeyPair('x448'); - } - case 'ec': { - const namedCurve = (0, get_named_curve_js_1.default)(key); - return generateKeyPair('ec', { namedCurve }); - } - default: - throw new errors_js_1.JOSENotSupported('Invalid or unsupported EPK'); - } -} -exports.generateEpk = generateEpk; -const ecdhAllowed = (key) => ['P-256', 'P-384', 'P-521', 'X25519', 'X448'].includes((0, get_named_curve_js_1.default)(key)); -exports.ecdhAllowed = ecdhAllowed; diff --git a/dist/node/cjs/runtime/encrypt.js b/dist/node/cjs/runtime/encrypt.js deleted file mode 100644 index 940a1ed28b..0000000000 --- a/dist/node/cjs/runtime/encrypt.js +++ /dev/null @@ -1,74 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const check_iv_length_js_1 = require("../lib/check_iv_length.js"); -const check_cek_length_js_1 = require("./check_cek_length.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const cbc_tag_js_1 = require("./cbc_tag.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const crypto_key_js_1 = require("../lib/crypto_key.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const errors_js_1 = require("../util/errors.js"); -const ciphers_js_1 = require("./ciphers.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -function cbcEncrypt(enc, plaintext, cek, iv, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - if ((0, is_key_object_js_1.default)(cek)) { - cek = cek.export(); - } - const encKey = cek.subarray(keySize >> 3); - const macKey = cek.subarray(0, keySize >> 3); - const algorithm = `aes-${keySize}-cbc`; - if (!(0, ciphers_js_1.default)(algorithm)) { - throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - const cipher = (0, crypto_1.createCipheriv)(algorithm, encKey, iv); - const ciphertext = (0, buffer_utils_js_1.concat)(cipher.update(plaintext), cipher.final()); - const macSize = parseInt(enc.slice(-3), 10); - const tag = (0, cbc_tag_js_1.default)(aad, iv, ciphertext, macSize, macKey, keySize); - return { ciphertext, tag }; -} -function gcmEncrypt(enc, plaintext, cek, iv, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - const algorithm = `aes-${keySize}-gcm`; - if (!(0, ciphers_js_1.default)(algorithm)) { - throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - const cipher = (0, crypto_1.createCipheriv)(algorithm, cek, iv, { authTagLength: 16 }); - if (aad.byteLength) { - cipher.setAAD(aad, { plaintextLength: plaintext.length }); - } - const ciphertext = cipher.update(plaintext); - cipher.final(); - const tag = cipher.getAuthTag(); - return { ciphertext, tag }; -} -const encrypt = (enc, plaintext, cek, iv, aad) => { - let key; - if ((0, webcrypto_js_1.isCryptoKey)(cek)) { - (0, crypto_key_js_1.checkEncCryptoKey)(cek, enc, 'encrypt'); - key = crypto_1.KeyObject.from(cek); - } - else if (cek instanceof Uint8Array || (0, is_key_object_js_1.default)(cek)) { - key = cek; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(cek, ...is_key_like_js_1.types, 'Uint8Array')); - } - (0, check_cek_length_js_1.default)(enc, key); - (0, check_iv_length_js_1.default)(enc, iv); - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return cbcEncrypt(enc, plaintext, key, iv, aad); - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - return gcmEncrypt(enc, plaintext, key, iv, aad); - default: - throw new errors_js_1.JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); - } -}; -exports.default = encrypt; diff --git a/dist/node/cjs/runtime/env.js b/dist/node/cjs/runtime/env.js deleted file mode 100644 index e6a6f4acfe..0000000000 --- a/dist/node/cjs/runtime/env.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.isCloudflareWorkers = void 0; -function isCloudflareWorkers() { - return false; -} -exports.isCloudflareWorkers = isCloudflareWorkers; diff --git a/dist/node/cjs/runtime/fetch_jwks.js b/dist/node/cjs/runtime/fetch_jwks.js deleted file mode 100644 index b034fd5bb4..0000000000 --- a/dist/node/cjs/runtime/fetch_jwks.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const http = require("http"); -const https = require("https"); -const events_1 = require("events"); -const errors_js_1 = require("../util/errors.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const fetchJwks = async (url, timeout, options) => { - let get; - switch (url.protocol) { - case 'https:': - get = https.get; - break; - case 'http:': - get = http.get; - break; - default: - throw new TypeError('Unsupported URL protocol.'); - } - const { agent, headers } = options; - const req = get(url.href, { - agent, - timeout, - headers, - }); - const [response] = (await Promise.race([(0, events_1.once)(req, 'response'), (0, events_1.once)(req, 'timeout')])); - if (!response) { - req.destroy(); - throw new errors_js_1.JWKSTimeout(); - } - if (response.statusCode !== 200) { - throw new errors_js_1.JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response'); - } - const parts = []; - for await (const part of response) { - parts.push(part); - } - try { - return JSON.parse(buffer_utils_js_1.decoder.decode((0, buffer_utils_js_1.concat)(...parts))); - } - catch { - throw new errors_js_1.JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON'); - } -}; -exports.default = fetchJwks; diff --git a/dist/node/cjs/runtime/flags.js b/dist/node/cjs/runtime/flags.js deleted file mode 100644 index 7a4e64dd74..0000000000 --- a/dist/node/cjs/runtime/flags.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.jwkImport = exports.jwkExport = exports.rsaPssParams = exports.oneShotCallback = void 0; -const [major, minor] = process.versions.node.split('.').map((str) => parseInt(str, 10)); -exports.oneShotCallback = major >= 16 || (major === 15 && minor >= 13); -exports.rsaPssParams = !('electron' in process.versions) && (major >= 17 || (major === 16 && minor >= 9)); -exports.jwkExport = major >= 16 || (major === 15 && minor >= 9); -exports.jwkImport = major >= 16 || (major === 15 && minor >= 12); diff --git a/dist/node/cjs/runtime/generate.js b/dist/node/cjs/runtime/generate.js deleted file mode 100644 index 38aa92bae3..0000000000 --- a/dist/node/cjs/runtime/generate.js +++ /dev/null @@ -1,105 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.generateKeyPair = exports.generateSecret = void 0; -const crypto_1 = require("crypto"); -const util_1 = require("util"); -const random_js_1 = require("./random.js"); -const check_modulus_length_js_1 = require("./check_modulus_length.js"); -const errors_js_1 = require("../util/errors.js"); -const generate = (0, util_1.promisify)(crypto_1.generateKeyPair); -async function generateSecret(alg, options) { - let length; - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - length = parseInt(alg.slice(-3), 10); - break; - case 'A128KW': - case 'A192KW': - case 'A256KW': - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - length = parseInt(alg.slice(1, 4), 10); - break; - default: - throw new errors_js_1.JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - return (0, crypto_1.createSecretKey)((0, random_js_1.default)(new Uint8Array(length >> 3))); -} -exports.generateSecret = generateSecret; -async function generateKeyPair(alg, options) { - var _a, _b; - switch (alg) { - case 'RS256': - case 'RS384': - case 'RS512': - case 'PS256': - case 'PS384': - case 'PS512': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - case 'RSA1_5': { - const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; - if (typeof modulusLength !== 'number' || modulusLength < 2048) { - throw new errors_js_1.JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used'); - } - const keypair = await generate('rsa', { - modulusLength, - publicExponent: 0x10001, - }); - (0, check_modulus_length_js_1.setModulusLength)(keypair.privateKey, modulusLength); - (0, check_modulus_length_js_1.setModulusLength)(keypair.publicKey, modulusLength); - return keypair; - } - case 'ES256': - return generate('ec', { namedCurve: 'P-256' }); - case 'ES256K': - return generate('ec', { namedCurve: 'secp256k1' }); - case 'ES384': - return generate('ec', { namedCurve: 'P-384' }); - case 'ES512': - return generate('ec', { namedCurve: 'P-521' }); - case 'EdDSA': { - switch (options === null || options === void 0 ? void 0 : options.crv) { - case undefined: - case 'Ed25519': - return generate('ed25519'); - case 'Ed448': - return generate('ed448'); - default: - throw new errors_js_1.JOSENotSupported('Invalid or unsupported crv option provided, supported values are Ed25519 and Ed448'); - } - } - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': - const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256'; - switch (crv) { - case undefined: - case 'P-256': - case 'P-384': - case 'P-521': - return generate('ec', { namedCurve: crv }); - case 'X25519': - return generate('x25519'); - case 'X448': - return generate('x448'); - default: - throw new errors_js_1.JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448'); - } - default: - throw new errors_js_1.JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } -} -exports.generateKeyPair = generateKeyPair; diff --git a/dist/node/cjs/runtime/get_named_curve.js b/dist/node/cjs/runtime/get_named_curve.js deleted file mode 100644 index bb46729e3d..0000000000 --- a/dist/node/cjs/runtime/get_named_curve.js +++ /dev/null @@ -1,95 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.setCurve = exports.weakMap = void 0; -const buffer_1 = require("buffer"); -const crypto_1 = require("crypto"); -const errors_js_1 = require("../util/errors.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -const p256 = buffer_1.Buffer.from([42, 134, 72, 206, 61, 3, 1, 7]); -const p384 = buffer_1.Buffer.from([43, 129, 4, 0, 34]); -const p521 = buffer_1.Buffer.from([43, 129, 4, 0, 35]); -const secp256k1 = buffer_1.Buffer.from([43, 129, 4, 0, 10]); -exports.weakMap = new WeakMap(); -const namedCurveToJOSE = (namedCurve) => { - switch (namedCurve) { - case 'prime256v1': - return 'P-256'; - case 'secp384r1': - return 'P-384'; - case 'secp521r1': - return 'P-521'; - case 'secp256k1': - return 'secp256k1'; - default: - throw new errors_js_1.JOSENotSupported('Unsupported key curve for this operation'); - } -}; -const getNamedCurve = (kee, raw) => { - var _a; - let key; - if ((0, webcrypto_js_1.isCryptoKey)(kee)) { - key = crypto_1.KeyObject.from(kee); - } - else if ((0, is_key_object_js_1.default)(kee)) { - key = kee; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(kee, ...is_key_like_js_1.types)); - } - if (key.type === 'secret') { - throw new TypeError('only "private" or "public" type keys can be used for this operation'); - } - switch (key.asymmetricKeyType) { - case 'ed25519': - case 'ed448': - return `Ed${key.asymmetricKeyType.slice(2)}`; - case 'x25519': - case 'x448': - return `X${key.asymmetricKeyType.slice(1)}`; - case 'ec': { - if (exports.weakMap.has(key)) { - return exports.weakMap.get(key); - } - let namedCurve = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.namedCurve; - if (!namedCurve && key.type === 'private') { - namedCurve = getNamedCurve((0, crypto_1.createPublicKey)(key), true); - } - else if (!namedCurve) { - const buf = key.export({ format: 'der', type: 'spki' }); - const i = buf[1] < 128 ? 14 : 15; - const len = buf[i]; - const curveOid = buf.slice(i + 1, i + 1 + len); - if (curveOid.equals(p256)) { - namedCurve = 'prime256v1'; - } - else if (curveOid.equals(p384)) { - namedCurve = 'secp384r1'; - } - else if (curveOid.equals(p521)) { - namedCurve = 'secp521r1'; - } - else if (curveOid.equals(secp256k1)) { - namedCurve = 'secp256k1'; - } - else { - throw new errors_js_1.JOSENotSupported('Unsupported key curve for this operation'); - } - } - if (raw) - return namedCurve; - const curve = namedCurveToJOSE(namedCurve); - exports.weakMap.set(key, curve); - return curve; - } - default: - throw new TypeError('Invalid asymmetric key type for this operation'); - } -}; -function setCurve(keyObject, curve) { - exports.weakMap.set(keyObject, curve); -} -exports.setCurve = setCurve; -exports.default = getNamedCurve; diff --git a/dist/node/cjs/runtime/get_sign_verify_key.js b/dist/node/cjs/runtime/get_sign_verify_key.js deleted file mode 100644 index fea98c71d5..0000000000 --- a/dist/node/cjs/runtime/get_sign_verify_key.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const webcrypto_js_1 = require("./webcrypto.js"); -const crypto_key_js_1 = require("../lib/crypto_key.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -function getSignVerifyKey(alg, key, usage) { - if (key instanceof Uint8Array) { - if (!alg.startsWith('HS')) { - throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types)); - } - return (0, crypto_1.createSecretKey)(key); - } - if (key instanceof crypto_1.KeyObject) { - return key; - } - if ((0, webcrypto_js_1.isCryptoKey)(key)) { - (0, crypto_key_js_1.checkSigCryptoKey)(key, alg, usage); - return crypto_1.KeyObject.from(key); - } - throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); -} -exports.default = getSignVerifyKey; diff --git a/dist/node/cjs/runtime/hmac_digest.js b/dist/node/cjs/runtime/hmac_digest.js deleted file mode 100644 index c3935124c7..0000000000 --- a/dist/node/cjs/runtime/hmac_digest.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const errors_js_1 = require("../util/errors.js"); -function hmacDigest(alg) { - switch (alg) { - case 'HS256': - return 'sha256'; - case 'HS384': - return 'sha384'; - case 'HS512': - return 'sha512'; - default: - throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} -exports.default = hmacDigest; diff --git a/dist/node/cjs/runtime/is_key_like.js b/dist/node/cjs/runtime/is_key_like.js deleted file mode 100644 index cd157df0a3..0000000000 --- a/dist/node/cjs/runtime/is_key_like.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.types = void 0; -const webcrypto_js_1 = require("./webcrypto.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -exports.default = (key) => (0, is_key_object_js_1.default)(key) || (0, webcrypto_js_1.isCryptoKey)(key); -const types = ['KeyObject']; -exports.types = types; -if (globalThis.CryptoKey || (webcrypto_js_1.default === null || webcrypto_js_1.default === void 0 ? void 0 : webcrypto_js_1.default.CryptoKey)) { - types.push('CryptoKey'); -} diff --git a/dist/node/cjs/runtime/is_key_object.js b/dist/node/cjs/runtime/is_key_object.js deleted file mode 100644 index 54b02cca1b..0000000000 --- a/dist/node/cjs/runtime/is_key_object.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const util = require("util"); -exports.default = util.types.isKeyObject - ? (obj) => util.types.isKeyObject(obj) - : (obj) => obj != null && obj instanceof crypto_1.KeyObject; diff --git a/dist/node/cjs/runtime/jwk_to_key.js b/dist/node/cjs/runtime/jwk_to_key.js deleted file mode 100644 index 8a3ead7800..0000000000 --- a/dist/node/cjs/runtime/jwk_to_key.js +++ /dev/null @@ -1,118 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const buffer_1 = require("buffer"); -const crypto_1 = require("crypto"); -const base64url_js_1 = require("./base64url.js"); -const errors_js_1 = require("../util/errors.js"); -const get_named_curve_js_1 = require("./get_named_curve.js"); -const check_modulus_length_js_1 = require("./check_modulus_length.js"); -const asn1_sequence_encoder_js_1 = require("./asn1_sequence_encoder.js"); -const flags_js_1 = require("./flags.js"); -const parse = (jwk) => { - if (flags_js_1.jwkImport && jwk.kty !== 'oct') { - return jwk.d - ? (0, crypto_1.createPrivateKey)({ format: 'jwk', key: jwk }) - : (0, crypto_1.createPublicKey)({ format: 'jwk', key: jwk }); - } - switch (jwk.kty) { - case 'oct': { - return (0, crypto_1.createSecretKey)((0, base64url_js_1.decode)(jwk.k)); - } - case 'RSA': { - const enc = new asn1_sequence_encoder_js_1.default(); - const isPrivate = jwk.d !== undefined; - const modulus = buffer_1.Buffer.from(jwk.n, 'base64'); - const exponent = buffer_1.Buffer.from(jwk.e, 'base64'); - if (isPrivate) { - enc.zero(); - enc.unsignedInteger(modulus); - enc.unsignedInteger(exponent); - enc.unsignedInteger(buffer_1.Buffer.from(jwk.d, 'base64')); - enc.unsignedInteger(buffer_1.Buffer.from(jwk.p, 'base64')); - enc.unsignedInteger(buffer_1.Buffer.from(jwk.q, 'base64')); - enc.unsignedInteger(buffer_1.Buffer.from(jwk.dp, 'base64')); - enc.unsignedInteger(buffer_1.Buffer.from(jwk.dq, 'base64')); - enc.unsignedInteger(buffer_1.Buffer.from(jwk.qi, 'base64')); - } - else { - enc.unsignedInteger(modulus); - enc.unsignedInteger(exponent); - } - const der = enc.end(); - const createInput = { - key: der, - format: 'der', - type: 'pkcs1', - }; - const keyObject = isPrivate ? (0, crypto_1.createPrivateKey)(createInput) : (0, crypto_1.createPublicKey)(createInput); - (0, check_modulus_length_js_1.setModulusLength)(keyObject, modulus.length << 3); - return keyObject; - } - case 'EC': { - const enc = new asn1_sequence_encoder_js_1.default(); - const isPrivate = jwk.d !== undefined; - const pub = buffer_1.Buffer.concat([ - buffer_1.Buffer.alloc(1, 4), - buffer_1.Buffer.from(jwk.x, 'base64'), - buffer_1.Buffer.from(jwk.y, 'base64'), - ]); - if (isPrivate) { - enc.zero(); - const enc$1 = new asn1_sequence_encoder_js_1.default(); - enc$1.oidFor('ecPublicKey'); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - const enc$2 = new asn1_sequence_encoder_js_1.default(); - enc$2.one(); - enc$2.octStr(buffer_1.Buffer.from(jwk.d, 'base64')); - const enc$3 = new asn1_sequence_encoder_js_1.default(); - enc$3.bitStr(pub); - const f2 = enc$3.end(buffer_1.Buffer.from([0xa1])); - enc$2.add(f2); - const f = enc$2.end(); - const enc$4 = new asn1_sequence_encoder_js_1.default(); - enc$4.add(f); - const f3 = enc$4.end(buffer_1.Buffer.from([0x04])); - enc.add(f3); - const der = enc.end(); - const keyObject = (0, crypto_1.createPrivateKey)({ key: der, format: 'der', type: 'pkcs8' }); - (0, get_named_curve_js_1.setCurve)(keyObject, jwk.crv); - return keyObject; - } - const enc$1 = new asn1_sequence_encoder_js_1.default(); - enc$1.oidFor('ecPublicKey'); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - enc.bitStr(pub); - const der = enc.end(); - const keyObject = (0, crypto_1.createPublicKey)({ key: der, format: 'der', type: 'spki' }); - (0, get_named_curve_js_1.setCurve)(keyObject, jwk.crv); - return keyObject; - } - case 'OKP': { - const enc = new asn1_sequence_encoder_js_1.default(); - const isPrivate = jwk.d !== undefined; - if (isPrivate) { - enc.zero(); - const enc$1 = new asn1_sequence_encoder_js_1.default(); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - const enc$2 = new asn1_sequence_encoder_js_1.default(); - enc$2.octStr(buffer_1.Buffer.from(jwk.d, 'base64')); - const f = enc$2.end(buffer_1.Buffer.from([0x04])); - enc.add(f); - const der = enc.end(); - return (0, crypto_1.createPrivateKey)({ key: der, format: 'der', type: 'pkcs8' }); - } - const enc$1 = new asn1_sequence_encoder_js_1.default(); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - enc.bitStr(buffer_1.Buffer.from(jwk.x, 'base64')); - const der = enc.end(); - return (0, crypto_1.createPublicKey)({ key: der, format: 'der', type: 'spki' }); - } - default: - throw new errors_js_1.JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); - } -}; -exports.default = parse; diff --git a/dist/node/cjs/runtime/key_to_jwk.js b/dist/node/cjs/runtime/key_to_jwk.js deleted file mode 100644 index 6ee2127570..0000000000 --- a/dist/node/cjs/runtime/key_to_jwk.js +++ /dev/null @@ -1,160 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const base64url_js_1 = require("./base64url.js"); -const asn1_sequence_decoder_js_1 = require("./asn1_sequence_decoder.js"); -const errors_js_1 = require("../util/errors.js"); -const get_named_curve_js_1 = require("./get_named_curve.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -const flags_js_1 = require("./flags.js"); -const keyToJWK = (key) => { - let keyObject; - if ((0, webcrypto_js_1.isCryptoKey)(key)) { - if (!key.extractable) { - throw new TypeError('CryptoKey is not extractable'); - } - keyObject = crypto_1.KeyObject.from(key); - } - else if ((0, is_key_object_js_1.default)(key)) { - keyObject = key; - } - else if (key instanceof Uint8Array) { - return { - kty: 'oct', - k: (0, base64url_js_1.encode)(key), - }; - } - else { - throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); - } - if (flags_js_1.jwkExport) { - if (keyObject.type !== 'secret' && - !['rsa', 'ec', 'ed25519', 'x25519', 'ed448', 'x448'].includes(keyObject.asymmetricKeyType)) { - throw new errors_js_1.JOSENotSupported('Unsupported key asymmetricKeyType'); - } - return keyObject.export({ format: 'jwk' }); - } - switch (keyObject.type) { - case 'secret': - return { - kty: 'oct', - k: (0, base64url_js_1.encode)(keyObject.export()), - }; - case 'private': - case 'public': { - switch (keyObject.asymmetricKeyType) { - case 'rsa': { - const der = keyObject.export({ format: 'der', type: 'pkcs1' }); - const dec = new asn1_sequence_decoder_js_1.default(der); - if (keyObject.type === 'private') { - dec.unsignedInteger(); - } - const n = (0, base64url_js_1.encode)(dec.unsignedInteger()); - const e = (0, base64url_js_1.encode)(dec.unsignedInteger()); - let jwk; - if (keyObject.type === 'private') { - jwk = { - d: (0, base64url_js_1.encode)(dec.unsignedInteger()), - p: (0, base64url_js_1.encode)(dec.unsignedInteger()), - q: (0, base64url_js_1.encode)(dec.unsignedInteger()), - dp: (0, base64url_js_1.encode)(dec.unsignedInteger()), - dq: (0, base64url_js_1.encode)(dec.unsignedInteger()), - qi: (0, base64url_js_1.encode)(dec.unsignedInteger()), - }; - } - dec.end(); - return { kty: 'RSA', n, e, ...jwk }; - } - case 'ec': { - const crv = (0, get_named_curve_js_1.default)(keyObject); - let len; - let offset; - let correction; - switch (crv) { - case 'secp256k1': - len = 64; - offset = 31 + 2; - correction = -1; - break; - case 'P-256': - len = 64; - offset = 34 + 2; - correction = -1; - break; - case 'P-384': - len = 96; - offset = 33 + 2; - correction = -3; - break; - case 'P-521': - len = 132; - offset = 33 + 2; - correction = -3; - break; - default: - throw new errors_js_1.JOSENotSupported('Unsupported curve'); - } - if (keyObject.type === 'public') { - const der = keyObject.export({ type: 'spki', format: 'der' }); - return { - kty: 'EC', - crv, - x: (0, base64url_js_1.encode)(der.subarray(-len, -len / 2)), - y: (0, base64url_js_1.encode)(der.subarray(-len / 2)), - }; - } - const der = keyObject.export({ type: 'pkcs8', format: 'der' }); - if (der.length < 100) { - offset += correction; - } - return { - ...keyToJWK((0, crypto_1.createPublicKey)(keyObject)), - d: (0, base64url_js_1.encode)(der.subarray(offset, offset + len / 2)), - }; - } - case 'ed25519': - case 'x25519': { - const crv = (0, get_named_curve_js_1.default)(keyObject); - if (keyObject.type === 'public') { - const der = keyObject.export({ type: 'spki', format: 'der' }); - return { - kty: 'OKP', - crv, - x: (0, base64url_js_1.encode)(der.subarray(-32)), - }; - } - const der = keyObject.export({ type: 'pkcs8', format: 'der' }); - return { - ...keyToJWK((0, crypto_1.createPublicKey)(keyObject)), - d: (0, base64url_js_1.encode)(der.subarray(-32)), - }; - } - case 'ed448': - case 'x448': { - const crv = (0, get_named_curve_js_1.default)(keyObject); - if (keyObject.type === 'public') { - const der = keyObject.export({ type: 'spki', format: 'der' }); - return { - kty: 'OKP', - crv, - x: (0, base64url_js_1.encode)(der.subarray(crv === 'Ed448' ? -57 : -56)), - }; - } - const der = keyObject.export({ type: 'pkcs8', format: 'der' }); - return { - ...keyToJWK((0, crypto_1.createPublicKey)(keyObject)), - d: (0, base64url_js_1.encode)(der.subarray(crv === 'Ed448' ? -57 : -56)), - }; - } - default: - throw new errors_js_1.JOSENotSupported('Unsupported key asymmetricKeyType'); - } - } - default: - throw new errors_js_1.JOSENotSupported('Unsupported key type'); - } -}; -exports.default = keyToJWK; diff --git a/dist/node/cjs/runtime/node_key.js b/dist/node/cjs/runtime/node_key.js deleted file mode 100644 index df67562ab4..0000000000 --- a/dist/node/cjs/runtime/node_key.js +++ /dev/null @@ -1,78 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const get_named_curve_js_1 = require("./get_named_curve.js"); -const errors_js_1 = require("../util/errors.js"); -const check_modulus_length_js_1 = require("./check_modulus_length.js"); -const flags_js_1 = require("./flags.js"); -const PSS = { - padding: crypto_1.constants.RSA_PKCS1_PSS_PADDING, - saltLength: crypto_1.constants.RSA_PSS_SALTLEN_DIGEST, -}; -const ecCurveAlgMap = new Map([ - ['ES256', 'P-256'], - ['ES256K', 'secp256k1'], - ['ES384', 'P-384'], - ['ES512', 'P-521'], -]); -function keyForCrypto(alg, key) { - switch (alg) { - case 'EdDSA': - if (!['ed25519', 'ed448'].includes(key.asymmetricKeyType)) { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ed25519 or ed448'); - } - return key; - case 'RS256': - case 'RS384': - case 'RS512': - if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); - } - (0, check_modulus_length_js_1.default)(key, alg); - return key; - case flags_js_1.rsaPssParams && 'PS256': - case flags_js_1.rsaPssParams && 'PS384': - case flags_js_1.rsaPssParams && 'PS512': - if (key.asymmetricKeyType === 'rsa-pss') { - const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails; - const length = parseInt(alg.slice(-3), 10); - if (hashAlgorithm !== undefined && - (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm)) { - throw new TypeError(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${alg}`); - } - if (saltLength !== undefined && saltLength > length >> 3) { - throw new TypeError(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of "alg" ${alg}`); - } - } - else if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa or rsa-pss'); - } - (0, check_modulus_length_js_1.default)(key, alg); - return { key, ...PSS }; - case !flags_js_1.rsaPssParams && 'PS256': - case !flags_js_1.rsaPssParams && 'PS384': - case !flags_js_1.rsaPssParams && 'PS512': - if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); - } - (0, check_modulus_length_js_1.default)(key, alg); - return { key, ...PSS }; - case 'ES256': - case 'ES256K': - case 'ES384': - case 'ES512': { - if (key.asymmetricKeyType !== 'ec') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ec'); - } - const actual = (0, get_named_curve_js_1.default)(key); - const expected = ecCurveAlgMap.get(alg); - if (actual !== expected) { - throw new TypeError(`Invalid key curve for the algorithm, its curve must be ${expected}, got ${actual}`); - } - return { dsaEncoding: 'ieee-p1363', key }; - } - default: - throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} -exports.default = keyForCrypto; diff --git a/dist/node/cjs/runtime/pbes2kw.js b/dist/node/cjs/runtime/pbes2kw.js deleted file mode 100644 index 8298b0e7d8..0000000000 --- a/dist/node/cjs/runtime/pbes2kw.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.decrypt = exports.encrypt = void 0; -const util_1 = require("util"); -const crypto_1 = require("crypto"); -const random_js_1 = require("./random.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const base64url_js_1 = require("./base64url.js"); -const aeskw_js_1 = require("./aeskw.js"); -const check_p2s_js_1 = require("../lib/check_p2s.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const crypto_key_js_1 = require("../lib/crypto_key.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -const pbkdf2 = (0, util_1.promisify)(crypto_1.pbkdf2); -function getPassword(key, alg) { - if ((0, is_key_object_js_1.default)(key)) { - return key.export(); - } - if (key instanceof Uint8Array) { - return key; - } - if ((0, webcrypto_js_1.isCryptoKey)(key)) { - (0, crypto_key_js_1.checkEncCryptoKey)(key, alg, 'deriveBits', 'deriveKey'); - return crypto_1.KeyObject.from(key).export(); - } - throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); -} -const encrypt = async (alg, key, cek, p2c = 2048, p2s = (0, random_js_1.default)(new Uint8Array(16))) => { - (0, check_p2s_js_1.default)(p2s); - const salt = (0, buffer_utils_js_1.p2s)(alg, p2s); - const keylen = parseInt(alg.slice(13, 16), 10) >> 3; - const password = getPassword(key, alg); - const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); - const encryptedKey = await (0, aeskw_js_1.wrap)(alg.slice(-6), derivedKey, cek); - return { encryptedKey, p2c, p2s: (0, base64url_js_1.encode)(p2s) }; -}; -exports.encrypt = encrypt; -const decrypt = async (alg, key, encryptedKey, p2c, p2s) => { - (0, check_p2s_js_1.default)(p2s); - const salt = (0, buffer_utils_js_1.p2s)(alg, p2s); - const keylen = parseInt(alg.slice(13, 16), 10) >> 3; - const password = getPassword(key, alg); - const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); - return (0, aeskw_js_1.unwrap)(alg.slice(-6), derivedKey, encryptedKey); -}; -exports.decrypt = decrypt; diff --git a/dist/node/cjs/runtime/random.js b/dist/node/cjs/runtime/random.js deleted file mode 100644 index 459da2bb08..0000000000 --- a/dist/node/cjs/runtime/random.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = void 0; -var crypto_1 = require("crypto"); -Object.defineProperty(exports, "default", { enumerable: true, get: function () { return crypto_1.randomFillSync; } }); diff --git a/dist/node/cjs/runtime/rsaes.js b/dist/node/cjs/runtime/rsaes.js deleted file mode 100644 index 4e625226b8..0000000000 --- a/dist/node/cjs/runtime/rsaes.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.decrypt = exports.encrypt = void 0; -const crypto_1 = require("crypto"); -const check_modulus_length_js_1 = require("./check_modulus_length.js"); -const webcrypto_js_1 = require("./webcrypto.js"); -const crypto_key_js_1 = require("../lib/crypto_key.js"); -const is_key_object_js_1 = require("./is_key_object.js"); -const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); -const is_key_like_js_1 = require("./is_key_like.js"); -const checkKey = (key, alg) => { - if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); - } - (0, check_modulus_length_js_1.default)(key, alg); -}; -const resolvePadding = (alg) => { - switch (alg) { - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - return crypto_1.constants.RSA_PKCS1_OAEP_PADDING; - case 'RSA1_5': - return crypto_1.constants.RSA_PKCS1_PADDING; - default: - return undefined; - } -}; -const resolveOaepHash = (alg) => { - switch (alg) { - case 'RSA-OAEP': - return 'sha1'; - case 'RSA-OAEP-256': - return 'sha256'; - case 'RSA-OAEP-384': - return 'sha384'; - case 'RSA-OAEP-512': - return 'sha512'; - default: - return undefined; - } -}; -function ensureKeyObject(key, alg, ...usages) { - if ((0, is_key_object_js_1.default)(key)) { - return key; - } - if ((0, webcrypto_js_1.isCryptoKey)(key)) { - (0, crypto_key_js_1.checkEncCryptoKey)(key, alg, ...usages); - return crypto_1.KeyObject.from(key); - } - throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types)); -} -const encrypt = (alg, key, cek) => { - const padding = resolvePadding(alg); - const oaepHash = resolveOaepHash(alg); - const keyObject = ensureKeyObject(key, alg, 'wrapKey', 'encrypt'); - checkKey(keyObject, alg); - return (0, crypto_1.publicEncrypt)({ key: keyObject, oaepHash, padding }, cek); -}; -exports.encrypt = encrypt; -const decrypt = (alg, key, encryptedKey) => { - const padding = resolvePadding(alg); - const oaepHash = resolveOaepHash(alg); - const keyObject = ensureKeyObject(key, alg, 'unwrapKey', 'decrypt'); - checkKey(keyObject, alg); - return (0, crypto_1.privateDecrypt)({ key: keyObject, oaepHash, padding }, encryptedKey); -}; -exports.decrypt = decrypt; diff --git a/dist/node/cjs/runtime/sign.js b/dist/node/cjs/runtime/sign.js deleted file mode 100644 index cc19300d9e..0000000000 --- a/dist/node/cjs/runtime/sign.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto = require("crypto"); -const util_1 = require("util"); -const dsa_digest_js_1 = require("./dsa_digest.js"); -const hmac_digest_js_1 = require("./hmac_digest.js"); -const node_key_js_1 = require("./node_key.js"); -const get_sign_verify_key_js_1 = require("./get_sign_verify_key.js"); -let oneShotSign; -if (crypto.sign.length > 3) { - oneShotSign = (0, util_1.promisify)(crypto.sign); -} -else { - oneShotSign = crypto.sign; -} -const sign = async (alg, key, data) => { - const keyObject = (0, get_sign_verify_key_js_1.default)(alg, key, 'sign'); - if (alg.startsWith('HS')) { - const hmac = crypto.createHmac((0, hmac_digest_js_1.default)(alg), keyObject); - hmac.update(data); - return hmac.digest(); - } - return oneShotSign((0, dsa_digest_js_1.default)(alg), data, (0, node_key_js_1.default)(alg, keyObject)); -}; -exports.default = sign; diff --git a/dist/node/cjs/runtime/timing_safe_equal.js b/dist/node/cjs/runtime/timing_safe_equal.js deleted file mode 100644 index e1e4ef6100..0000000000 --- a/dist/node/cjs/runtime/timing_safe_equal.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = require("crypto"); -const timingSafeEqual = crypto_1.timingSafeEqual; -exports.default = timingSafeEqual; diff --git a/dist/node/cjs/runtime/verify.js b/dist/node/cjs/runtime/verify.js deleted file mode 100644 index c9a1549020..0000000000 --- a/dist/node/cjs/runtime/verify.js +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto = require("crypto"); -const util_1 = require("util"); -const dsa_digest_js_1 = require("./dsa_digest.js"); -const node_key_js_1 = require("./node_key.js"); -const sign_js_1 = require("./sign.js"); -const get_sign_verify_key_js_1 = require("./get_sign_verify_key.js"); -const flags_js_1 = require("./flags.js"); -let oneShotVerify; -if (crypto.verify.length > 4 && flags_js_1.oneShotCallback) { - oneShotVerify = (0, util_1.promisify)(crypto.verify); -} -else { - oneShotVerify = crypto.verify; -} -const verify = async (alg, key, signature, data) => { - const keyObject = (0, get_sign_verify_key_js_1.default)(alg, key, 'verify'); - if (alg.startsWith('HS')) { - const expected = await (0, sign_js_1.default)(alg, keyObject, data); - const actual = signature; - try { - return crypto.timingSafeEqual(actual, expected); - } - catch { - return false; - } - } - const algorithm = (0, dsa_digest_js_1.default)(alg); - const keyInput = (0, node_key_js_1.default)(alg, keyObject); - try { - return await oneShotVerify(algorithm, data, keyInput, signature); - } - catch { - return false; - } -}; -exports.default = verify; diff --git a/dist/node/cjs/runtime/webcrypto.js b/dist/node/cjs/runtime/webcrypto.js deleted file mode 100644 index 8a3e72e06e..0000000000 --- a/dist/node/cjs/runtime/webcrypto.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.isCryptoKey = void 0; -const crypto = require("crypto"); -const util = require("util"); -const webcrypto = crypto.webcrypto; -exports.default = webcrypto; -exports.isCryptoKey = util.types.isCryptoKey - ? (key) => util.types.isCryptoKey(key) - : - (key) => false; diff --git a/dist/node/cjs/runtime/zlib.js b/dist/node/cjs/runtime/zlib.js deleted file mode 100644 index 7dcfddf49b..0000000000 --- a/dist/node/cjs/runtime/zlib.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.deflate = exports.inflate = void 0; -const util_1 = require("util"); -const zlib_1 = require("zlib"); -const inflateRaw = (0, util_1.promisify)(zlib_1.inflateRaw); -const deflateRaw = (0, util_1.promisify)(zlib_1.deflateRaw); -const inflate = (input) => inflateRaw(input); -exports.inflate = inflate; -const deflate = (input) => deflateRaw(input); -exports.deflate = deflate; diff --git a/dist/node/cjs/util/base64url.js b/dist/node/cjs/util/base64url.js deleted file mode 100644 index 4d383b5167..0000000000 --- a/dist/node/cjs/util/base64url.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.decode = exports.encode = void 0; -const base64url = require("../runtime/base64url.js"); -exports.encode = base64url.encode; -exports.decode = base64url.decode; diff --git a/dist/node/cjs/util/decode_jwt.js b/dist/node/cjs/util/decode_jwt.js deleted file mode 100644 index f5b6122e46..0000000000 --- a/dist/node/cjs/util/decode_jwt.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.decodeJwt = void 0; -const base64url_js_1 = require("./base64url.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const is_object_js_1 = require("../lib/is_object.js"); -const errors_js_1 = require("./errors.js"); -function decodeJwt(jwt) { - if (typeof jwt !== 'string') - throw new errors_js_1.JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string'); - const { 1: payload, length } = jwt.split('.'); - if (length === 5) - throw new errors_js_1.JWTInvalid('Only JWTs using Compact JWS serialization can be decoded'); - if (length !== 3) - throw new errors_js_1.JWTInvalid('Invalid JWT'); - if (!payload) - throw new errors_js_1.JWTInvalid('JWTs must contain a payload'); - let decoded; - try { - decoded = (0, base64url_js_1.decode)(payload); - } - catch { - throw new errors_js_1.JWTInvalid('Failed to parse the base64url encoded payload'); - } - let result; - try { - result = JSON.parse(buffer_utils_js_1.decoder.decode(decoded)); - } - catch { - throw new errors_js_1.JWTInvalid('Failed to parse the decoded payload as JSON'); - } - if (!(0, is_object_js_1.default)(result)) - throw new errors_js_1.JWTInvalid('Invalid JWT Claims Set'); - return result; -} -exports.decodeJwt = decodeJwt; diff --git a/dist/node/cjs/util/decode_protected_header.js b/dist/node/cjs/util/decode_protected_header.js deleted file mode 100644 index 601ebb7297..0000000000 --- a/dist/node/cjs/util/decode_protected_header.js +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.decodeProtectedHeader = void 0; -const base64url_js_1 = require("./base64url.js"); -const buffer_utils_js_1 = require("../lib/buffer_utils.js"); -const is_object_js_1 = require("../lib/is_object.js"); -function decodeProtectedHeader(token) { - let protectedB64u; - if (typeof token === 'string') { - const parts = token.split('.'); - if (parts.length === 3 || parts.length === 5) { - ; - [protectedB64u] = parts; - } - } - else if (typeof token === 'object' && token) { - if ('protected' in token) { - protectedB64u = token.protected; - } - else { - throw new TypeError('Token does not contain a Protected Header'); - } - } - try { - if (typeof protectedB64u !== 'string' || !protectedB64u) { - throw new Error(); - } - const result = JSON.parse(buffer_utils_js_1.decoder.decode((0, base64url_js_1.decode)(protectedB64u))); - if (!(0, is_object_js_1.default)(result)) { - throw new Error(); - } - return result; - } - catch { - throw new TypeError('Invalid Token or Protected Header formatting'); - } -} -exports.decodeProtectedHeader = decodeProtectedHeader; diff --git a/dist/node/cjs/util/errors.js b/dist/node/cjs/util/errors.js deleted file mode 100644 index 5ec68a5b12..0000000000 --- a/dist/node/cjs/util/errors.js +++ /dev/null @@ -1,166 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.JWSSignatureVerificationFailed = exports.JWKSTimeout = exports.JWKSMultipleMatchingKeys = exports.JWKSNoMatchingKey = exports.JWKSInvalid = exports.JWKInvalid = exports.JWTInvalid = exports.JWSInvalid = exports.JWEInvalid = exports.JWEDecryptionFailed = exports.JOSENotSupported = exports.JOSEAlgNotAllowed = exports.JWTExpired = exports.JWTClaimValidationFailed = exports.JOSEError = void 0; -class JOSEError extends Error { - static get code() { - return 'ERR_JOSE_GENERIC'; - } - constructor(message) { - var _a; - super(message); - this.code = 'ERR_JOSE_GENERIC'; - this.name = this.constructor.name; - (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); - } -} -exports.JOSEError = JOSEError; -class JWTClaimValidationFailed extends JOSEError { - static get code() { - return 'ERR_JWT_CLAIM_VALIDATION_FAILED'; - } - constructor(message, claim = 'unspecified', reason = 'unspecified') { - super(message); - this.code = 'ERR_JWT_CLAIM_VALIDATION_FAILED'; - this.claim = claim; - this.reason = reason; - } -} -exports.JWTClaimValidationFailed = JWTClaimValidationFailed; -class JWTExpired extends JOSEError { - static get code() { - return 'ERR_JWT_EXPIRED'; - } - constructor(message, claim = 'unspecified', reason = 'unspecified') { - super(message); - this.code = 'ERR_JWT_EXPIRED'; - this.claim = claim; - this.reason = reason; - } -} -exports.JWTExpired = JWTExpired; -class JOSEAlgNotAllowed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JOSE_ALG_NOT_ALLOWED'; - } - static get code() { - return 'ERR_JOSE_ALG_NOT_ALLOWED'; - } -} -exports.JOSEAlgNotAllowed = JOSEAlgNotAllowed; -class JOSENotSupported extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JOSE_NOT_SUPPORTED'; - } - static get code() { - return 'ERR_JOSE_NOT_SUPPORTED'; - } -} -exports.JOSENotSupported = JOSENotSupported; -class JWEDecryptionFailed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWE_DECRYPTION_FAILED'; - this.message = 'decryption operation failed'; - } - static get code() { - return 'ERR_JWE_DECRYPTION_FAILED'; - } -} -exports.JWEDecryptionFailed = JWEDecryptionFailed; -class JWEInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWE_INVALID'; - } - static get code() { - return 'ERR_JWE_INVALID'; - } -} -exports.JWEInvalid = JWEInvalid; -class JWSInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWS_INVALID'; - } - static get code() { - return 'ERR_JWS_INVALID'; - } -} -exports.JWSInvalid = JWSInvalid; -class JWTInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWT_INVALID'; - } - static get code() { - return 'ERR_JWT_INVALID'; - } -} -exports.JWTInvalid = JWTInvalid; -class JWKInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWK_INVALID'; - } - static get code() { - return 'ERR_JWK_INVALID'; - } -} -exports.JWKInvalid = JWKInvalid; -class JWKSInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_INVALID'; - } - static get code() { - return 'ERR_JWKS_INVALID'; - } -} -exports.JWKSInvalid = JWKSInvalid; -class JWKSNoMatchingKey extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_NO_MATCHING_KEY'; - this.message = 'no applicable key found in the JSON Web Key Set'; - } - static get code() { - return 'ERR_JWKS_NO_MATCHING_KEY'; - } -} -exports.JWKSNoMatchingKey = JWKSNoMatchingKey; -class JWKSMultipleMatchingKeys extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; - this.message = 'multiple matching keys found in the JSON Web Key Set'; - } - static get code() { - return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; - } -} -exports.JWKSMultipleMatchingKeys = JWKSMultipleMatchingKeys; -Symbol.asyncIterator; -class JWKSTimeout extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_TIMEOUT'; - this.message = 'request timed out'; - } - static get code() { - return 'ERR_JWKS_TIMEOUT'; - } -} -exports.JWKSTimeout = JWKSTimeout; -class JWSSignatureVerificationFailed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; - this.message = 'signature verification failed'; - } - static get code() { - return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; - } -} -exports.JWSSignatureVerificationFailed = JWSSignatureVerificationFailed; diff --git a/dist/node/esm/index.js b/dist/node/esm/index.js deleted file mode 100644 index d2ce09d71a..0000000000 --- a/dist/node/esm/index.js +++ /dev/null @@ -1,29 +0,0 @@ -export { compactDecrypt } from './jwe/compact/decrypt.js'; -export { flattenedDecrypt } from './jwe/flattened/decrypt.js'; -export { generalDecrypt } from './jwe/general/decrypt.js'; -export { GeneralEncrypt } from './jwe/general/encrypt.js'; -export { compactVerify } from './jws/compact/verify.js'; -export { flattenedVerify } from './jws/flattened/verify.js'; -export { generalVerify } from './jws/general/verify.js'; -export { jwtVerify } from './jwt/verify.js'; -export { jwtDecrypt } from './jwt/decrypt.js'; -export { CompactEncrypt } from './jwe/compact/encrypt.js'; -export { FlattenedEncrypt } from './jwe/flattened/encrypt.js'; -export { CompactSign } from './jws/compact/sign.js'; -export { FlattenedSign } from './jws/flattened/sign.js'; -export { GeneralSign } from './jws/general/sign.js'; -export { SignJWT } from './jwt/sign.js'; -export { EncryptJWT } from './jwt/encrypt.js'; -export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.js'; -export { EmbeddedJWK } from './jwk/embedded.js'; -export { createLocalJWKSet } from './jwks/local.js'; -export { createRemoteJWKSet } from './jwks/remote.js'; -export { UnsecuredJWT } from './jwt/unsecured.js'; -export { exportPKCS8, exportSPKI, exportJWK } from './key/export.js'; -export { importSPKI, importPKCS8, importX509, importJWK } from './key/import.js'; -export { decodeProtectedHeader } from './util/decode_protected_header.js'; -export { decodeJwt } from './util/decode_jwt.js'; -export * as errors from './util/errors.js'; -export { generateKeyPair } from './key/generate_key_pair.js'; -export { generateSecret } from './key/generate_secret.js'; -export * as base64url from './util/base64url.js'; diff --git a/dist/node/esm/jwe/compact/decrypt.js b/dist/node/esm/jwe/compact/decrypt.js deleted file mode 100644 index 129aeb6e39..0000000000 --- a/dist/node/esm/jwe/compact/decrypt.js +++ /dev/null @@ -1,27 +0,0 @@ -import { flattenedDecrypt } from '../flattened/decrypt.js'; -import { JWEInvalid } from '../../util/errors.js'; -import { decoder } from '../../lib/buffer_utils.js'; -export async function compactDecrypt(jwe, key, options) { - if (jwe instanceof Uint8Array) { - jwe = decoder.decode(jwe); - } - if (typeof jwe !== 'string') { - throw new JWEInvalid('Compact JWE must be a string or Uint8Array'); - } - const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.'); - if (length !== 5) { - throw new JWEInvalid('Invalid Compact JWE'); - } - const decrypted = await flattenedDecrypt({ - ciphertext, - iv: (iv || undefined), - protected: protectedHeader || undefined, - tag: (tag || undefined), - encrypted_key: encryptedKey || undefined, - }, key, options); - const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: decrypted.key }; - } - return result; -} diff --git a/dist/node/esm/jwe/compact/encrypt.js b/dist/node/esm/jwe/compact/encrypt.js deleted file mode 100644 index e689139465..0000000000 --- a/dist/node/esm/jwe/compact/encrypt.js +++ /dev/null @@ -1,26 +0,0 @@ -import { FlattenedEncrypt } from '../flattened/encrypt.js'; -export class CompactEncrypt { - constructor(plaintext) { - this._flattened = new FlattenedEncrypt(plaintext); - } - setContentEncryptionKey(cek) { - this._flattened.setContentEncryptionKey(cek); - return this; - } - setInitializationVector(iv) { - this._flattened.setInitializationVector(iv); - return this; - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - setKeyManagementParameters(parameters) { - this._flattened.setKeyManagementParameters(parameters); - return this; - } - async encrypt(key, options) { - const jwe = await this._flattened.encrypt(key, options); - return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.'); - } -} diff --git a/dist/node/esm/jwe/flattened/decrypt.js b/dist/node/esm/jwe/flattened/decrypt.js deleted file mode 100644 index e918c88954..0000000000 --- a/dist/node/esm/jwe/flattened/decrypt.js +++ /dev/null @@ -1,137 +0,0 @@ -import { decode as base64url } from '../../runtime/base64url.js'; -import decrypt from '../../runtime/decrypt.js'; -import { inflate } from '../../runtime/zlib.js'; -import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import isObject from '../../lib/is_object.js'; -import decryptKeyManagement from '../../lib/decrypt_key_management.js'; -import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; -import generateCek from '../../lib/cek.js'; -import validateCrit from '../../lib/validate_crit.js'; -import validateAlgorithms from '../../lib/validate_algorithms.js'; -export async function flattenedDecrypt(jwe, key, options) { - var _a; - if (!isObject(jwe)) { - throw new JWEInvalid('Flattened JWE must be an object'); - } - if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { - throw new JWEInvalid('JOSE Header missing'); - } - if (typeof jwe.iv !== 'string') { - throw new JWEInvalid('JWE Initialization Vector missing or incorrect type'); - } - if (typeof jwe.ciphertext !== 'string') { - throw new JWEInvalid('JWE Ciphertext missing or incorrect type'); - } - if (typeof jwe.tag !== 'string') { - throw new JWEInvalid('JWE Authentication Tag missing or incorrect type'); - } - if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { - throw new JWEInvalid('JWE Protected Header incorrect type'); - } - if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { - throw new JWEInvalid('JWE Encrypted Key incorrect type'); - } - if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { - throw new JWEInvalid('JWE AAD incorrect type'); - } - if (jwe.header !== undefined && !isObject(jwe.header)) { - throw new JWEInvalid('JWE Shared Unprotected Header incorrect type'); - } - if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) { - throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type'); - } - let parsedProt; - if (jwe.protected) { - try { - const protectedHeader = base64url(jwe.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader)); - } - catch { - throw new JWEInvalid('JWE Protected Header is invalid'); - } - } - if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) { - throw new JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...parsedProt, - ...jwe.header, - ...jwe.unprotected, - }; - validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - if (joseHeader.zip !== undefined) { - if (!parsedProt || !parsedProt.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== 'DEF') { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header'); - } - if (typeof enc !== 'string' || !enc) { - throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header'); - } - const keyManagementAlgorithms = options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms); - const contentEncryptionAlgorithms = options && - validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms); - if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { - throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); - } - let encryptedKey; - if (jwe.encrypted_key !== undefined) { - encryptedKey = base64url(jwe.encrypted_key); - } - let resolvedKey = false; - if (typeof key === 'function') { - key = await key(parsedProt, jwe); - resolvedKey = true; - } - let cek; - try { - cek = await decryptKeyManagement(alg, key, encryptedKey, joseHeader, options); - } - catch (err) { - if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { - throw err; - } - cek = generateCek(enc); - } - const iv = base64url(jwe.iv); - const tag = base64url(jwe.tag); - const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ''); - let additionalData; - if (jwe.aad !== undefined) { - additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(jwe.aad)); - } - else { - additionalData = protectedHeader; - } - let plaintext = await decrypt(enc, cek, base64url(jwe.ciphertext), iv, tag, additionalData); - if (joseHeader.zip === 'DEF') { - plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); - } - const result = { plaintext }; - if (jwe.protected !== undefined) { - result.protectedHeader = parsedProt; - } - if (jwe.aad !== undefined) { - result.additionalAuthenticatedData = base64url(jwe.aad); - } - if (jwe.unprotected !== undefined) { - result.sharedUnprotectedHeader = jwe.unprotected; - } - if (jwe.header !== undefined) { - result.unprotectedHeader = jwe.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} diff --git a/dist/node/esm/jwe/flattened/encrypt.js b/dist/node/esm/jwe/flattened/encrypt.js deleted file mode 100644 index 1e60ecd8c4..0000000000 --- a/dist/node/esm/jwe/flattened/encrypt.js +++ /dev/null @@ -1,175 +0,0 @@ -import { encode as base64url } from '../../runtime/base64url.js'; -import encrypt from '../../runtime/encrypt.js'; -import { deflate } from '../../runtime/zlib.js'; -import generateIv from '../../lib/iv.js'; -import encryptKeyManagement from '../../lib/encrypt_key_management.js'; -import { JOSENotSupported, JWEInvalid } from '../../util/errors.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; -import validateCrit from '../../lib/validate_crit.js'; -export const unprotected = Symbol(); -export class FlattenedEncrypt { - constructor(plaintext) { - if (!(plaintext instanceof Uint8Array)) { - throw new TypeError('plaintext must be an instance of Uint8Array'); - } - this._plaintext = plaintext; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once'); - } - this._keyManagementParameters = parameters; - return this; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._sharedUnprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once'); - } - this._sharedUnprotectedHeader = sharedUnprotectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once'); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once'); - } - this._iv = iv; - return this; - } - async encrypt(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { - throw new JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()'); - } - if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { - throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...this._sharedUnprotectedHeader, - }; - validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - if (joseHeader.zip !== 'DEF') { - throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); - } - } - const { alg, enc } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (typeof enc !== 'string' || !enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - let encryptedKey; - if (alg === 'dir') { - if (this._cek) { - throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption'); - } - } - else if (alg === 'ECDH-ES') { - if (this._cek) { - throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement'); - } - } - let cek; - { - let parameters; - ({ cek, encryptedKey, parameters } = await encryptKeyManagement(alg, enc, key, this._cek, this._keyManagementParameters)); - if (parameters) { - if (options && unprotected in options) { - if (!this._unprotectedHeader) { - this.setUnprotectedHeader(parameters); - } - else { - this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; - } - } - else { - if (!this._protectedHeader) { - this.setProtectedHeader(parameters); - } - else { - this._protectedHeader = { ...this._protectedHeader, ...parameters }; - } - } - } - } - this._iv || (this._iv = generateIv(enc)); - let additionalData; - let protectedHeader; - let aadMember; - if (this._protectedHeader) { - protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); - } - else { - protectedHeader = encoder.encode(''); - } - if (this._aad) { - aadMember = base64url(this._aad); - additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember)); - } - else { - additionalData = protectedHeader; - } - let ciphertext; - let tag; - if (joseHeader.zip === 'DEF') { - const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); - ({ ciphertext, tag } = await encrypt(enc, deflated, cek, this._iv, additionalData)); - } - else { - ; - ({ ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData)); - } - const jwe = { - ciphertext: base64url(ciphertext), - iv: base64url(this._iv), - tag: base64url(tag), - }; - if (encryptedKey) { - jwe.encrypted_key = base64url(encryptedKey); - } - if (aadMember) { - jwe.aad = aadMember; - } - if (this._protectedHeader) { - jwe.protected = decoder.decode(protectedHeader); - } - if (this._sharedUnprotectedHeader) { - jwe.unprotected = this._sharedUnprotectedHeader; - } - if (this._unprotectedHeader) { - jwe.header = this._unprotectedHeader; - } - return jwe; - } -} diff --git a/dist/node/esm/jwe/general/decrypt.js b/dist/node/esm/jwe/general/decrypt.js deleted file mode 100644 index 659958a8bc..0000000000 --- a/dist/node/esm/jwe/general/decrypt.js +++ /dev/null @@ -1,31 +0,0 @@ -import { flattenedDecrypt } from '../flattened/decrypt.js'; -import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.js'; -import isObject from '../../lib/is_object.js'; -export async function generalDecrypt(jwe, key, options) { - if (!isObject(jwe)) { - throw new JWEInvalid('General JWE must be an object'); - } - if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { - throw new JWEInvalid('JWE Recipients missing or incorrect type'); - } - if (!jwe.recipients.length) { - throw new JWEInvalid('JWE Recipients has no members'); - } - for (const recipient of jwe.recipients) { - try { - return await flattenedDecrypt({ - aad: jwe.aad, - ciphertext: jwe.ciphertext, - encrypted_key: recipient.encrypted_key, - header: recipient.header, - iv: jwe.iv, - protected: jwe.protected, - tag: jwe.tag, - unprotected: jwe.unprotected, - }, key, options); - } - catch { - } - } - throw new JWEDecryptionFailed(); -} diff --git a/dist/node/esm/jwe/general/encrypt.js b/dist/node/esm/jwe/general/encrypt.js deleted file mode 100644 index 3ee53dec44..0000000000 --- a/dist/node/esm/jwe/general/encrypt.js +++ /dev/null @@ -1,178 +0,0 @@ -import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.js'; -import { JWEInvalid } from '../../util/errors.js'; -import generateCek from '../../lib/cek.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import encryptKeyManagement from '../../lib/encrypt_key_management.js'; -import { encode as base64url } from '../../runtime/base64url.js'; -import validateCrit from '../../lib/validate_crit.js'; -class IndividualRecipient { - constructor(enc, key, options) { - this.parent = enc; - this.key = key; - this.options = options; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addRecipient(...args) { - return this.parent.addRecipient(...args); - } - encrypt(...args) { - return this.parent.encrypt(...args); - } - done() { - return this.parent; - } -} -export class GeneralEncrypt { - constructor(plaintext) { - this._recipients = []; - this._plaintext = plaintext; - } - addRecipient(key, options) { - const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); - this._recipients.push(recipient); - return recipient; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setSharedUnprotectedHeader(sharedUnprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setSharedUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = sharedUnprotectedHeader; - return this; - } - setAdditionalAuthenticatedData(aad) { - this._aad = aad; - return this; - } - async encrypt(options) { - var _a, _b, _c; - if (!this._recipients.length) { - throw new JWEInvalid('at least one recipient must be added'); - } - options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; - if (this._recipients.length === 1) { - const [recipient] = this._recipients; - const flattened = await new FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader) - .encrypt(recipient.key, { ...recipient.options, ...options }); - let jwe = { - ciphertext: flattened.ciphertext, - iv: flattened.iv, - recipients: [{}], - tag: flattened.tag, - }; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - if (flattened.encrypted_key) - jwe.recipients[0].encrypted_key = flattened.encrypted_key; - if (flattened.header) - jwe.recipients[0].header = flattened.header; - return jwe; - } - let enc; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { - throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - }; - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); - } - if (alg === 'dir' || alg === 'ECDH-ES') { - throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); - } - if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); - } - if (!enc) { - enc = joseHeader.enc; - } - else if (enc !== joseHeader.enc) { - throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); - } - validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader); - if (joseHeader.zip !== undefined) { - if (!this._protectedHeader || !this._protectedHeader.zip) { - throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); - } - } - } - const cek = generateCek(enc); - let jwe = { - ciphertext: '', - iv: '', - recipients: [], - tag: '', - }; - for (let i = 0; i < this._recipients.length; i++) { - const recipient = this._recipients[i]; - const target = {}; - jwe.recipients.push(target); - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - ...recipient.unprotectedHeader, - }; - const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined; - if (i === 0) { - const flattened = await new FlattenedEncrypt(this._plaintext) - .setAdditionalAuthenticatedData(this._aad) - .setContentEncryptionKey(cek) - .setProtectedHeader(this._protectedHeader) - .setSharedUnprotectedHeader(this._unprotectedHeader) - .setUnprotectedHeader(recipient.unprotectedHeader) - .setKeyManagementParameters({ p2c }) - .encrypt(recipient.key, { - ...recipient.options, - ...options, - [unprotected]: true, - }); - jwe.ciphertext = flattened.ciphertext; - jwe.iv = flattened.iv; - jwe.tag = flattened.tag; - if (flattened.aad) - jwe.aad = flattened.aad; - if (flattened.protected) - jwe.protected = flattened.protected; - if (flattened.unprotected) - jwe.unprotected = flattened.unprotected; - target.encrypted_key = flattened.encrypted_key; - if (flattened.header) - target.header = flattened.header; - continue; - } - const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || - ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || - ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); - target.encrypted_key = base64url(encryptedKey); - if (recipient.unprotectedHeader || parameters) - target.header = { ...recipient.unprotectedHeader, ...parameters }; - } - return jwe; - } -} diff --git a/dist/node/esm/jwk/embedded.js b/dist/node/esm/jwk/embedded.js deleted file mode 100644 index 58db282552..0000000000 --- a/dist/node/esm/jwk/embedded.js +++ /dev/null @@ -1,17 +0,0 @@ -import { importJWK } from '../key/import.js'; -import isObject from '../lib/is_object.js'; -import { JWSInvalid } from '../util/errors.js'; -export async function EmbeddedJWK(protectedHeader, token) { - const joseHeader = { - ...protectedHeader, - ...token.header, - }; - if (!isObject(joseHeader.jwk)) { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); - } - const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); - if (key instanceof Uint8Array || key.type !== 'public') { - throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); - } - return key; -} diff --git a/dist/node/esm/jwk/thumbprint.js b/dist/node/esm/jwk/thumbprint.js deleted file mode 100644 index 49f86b1743..0000000000 --- a/dist/node/esm/jwk/thumbprint.js +++ /dev/null @@ -1,53 +0,0 @@ -import digest from '../runtime/digest.js'; -import { encode as base64url } from '../runtime/base64url.js'; -import { JOSENotSupported, JWKInvalid } from '../util/errors.js'; -import { encoder } from '../lib/buffer_utils.js'; -import isObject from '../lib/is_object.js'; -const check = (value, description) => { - if (typeof value !== 'string' || !value) { - throw new JWKInvalid(`${description} missing or invalid`); - } -}; -export async function calculateJwkThumbprint(jwk, digestAlgorithm) { - if (!isObject(jwk)) { - throw new TypeError('JWK must be an object'); - } - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); - if (digestAlgorithm !== 'sha256' && - digestAlgorithm !== 'sha384' && - digestAlgorithm !== 'sha512') { - throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); - } - let components; - switch (jwk.kty) { - case 'EC': - check(jwk.crv, '"crv" (Curve) Parameter'); - check(jwk.x, '"x" (X Coordinate) Parameter'); - check(jwk.y, '"y" (Y Coordinate) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; - break; - case 'OKP': - check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); - check(jwk.x, '"x" (Public Key) Parameter'); - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; - break; - case 'RSA': - check(jwk.e, '"e" (Exponent) Parameter'); - check(jwk.n, '"n" (Modulus) Parameter'); - components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; - break; - case 'oct': - check(jwk.k, '"k" (Key Value) Parameter'); - components = { k: jwk.k, kty: jwk.kty }; - break; - default: - throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); - } - const data = encoder.encode(JSON.stringify(components)); - return base64url(await digest(digestAlgorithm, data)); -} -export async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { - digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); - const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); - return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; -} diff --git a/dist/node/esm/jwks/local.js b/dist/node/esm/jwks/local.js deleted file mode 100644 index bfe2130fad..0000000000 --- a/dist/node/esm/jwks/local.js +++ /dev/null @@ -1,113 +0,0 @@ -import { importJWK } from '../key/import.js'; -import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js'; -import isObject from '../lib/is_object.js'; -function getKtyFromAlg(alg) { - switch (typeof alg === 'string' && alg.slice(0, 2)) { - case 'RS': - case 'PS': - return 'RSA'; - case 'ES': - return 'EC'; - case 'Ed': - return 'OKP'; - default: - throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); - } -} -export function isJWKSLike(jwks) { - return (jwks && - typeof jwks === 'object' && - Array.isArray(jwks.keys) && - jwks.keys.every(isJWKLike)); -} -function isJWKLike(key) { - return isObject(key); -} -function clone(obj) { - if (typeof structuredClone === 'function') { - return structuredClone(obj); - } - return JSON.parse(JSON.stringify(obj)); -} -export class LocalJWKSet { - constructor(jwks) { - this._cached = new WeakMap(); - if (!isJWKSLike(jwks)) { - throw new JWKSInvalid('JSON Web Key Set malformed'); - } - this._jwks = clone(jwks); - } - async getKey(protectedHeader, token) { - const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; - const kty = getKtyFromAlg(alg); - const candidates = this._jwks.keys.filter((jwk) => { - let candidate = kty === jwk.kty; - if (candidate && typeof kid === 'string') { - candidate = kid === jwk.kid; - } - if (candidate && typeof jwk.alg === 'string') { - candidate = alg === jwk.alg; - } - if (candidate && typeof jwk.use === 'string') { - candidate = jwk.use === 'sig'; - } - if (candidate && Array.isArray(jwk.key_ops)) { - candidate = jwk.key_ops.includes('verify'); - } - if (candidate && alg === 'EdDSA') { - candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'; - } - if (candidate) { - switch (alg) { - case 'ES256': - candidate = jwk.crv === 'P-256'; - break; - case 'ES256K': - candidate = jwk.crv === 'secp256k1'; - break; - case 'ES384': - candidate = jwk.crv === 'P-384'; - break; - case 'ES512': - candidate = jwk.crv === 'P-521'; - break; - } - } - return candidate; - }); - const { 0: jwk, length } = candidates; - if (length === 0) { - throw new JWKSNoMatchingKey(); - } - else if (length !== 1) { - const error = new JWKSMultipleMatchingKeys(); - const { _cached } = this; - error[Symbol.asyncIterator] = async function* () { - for (const jwk of candidates) { - try { - yield await importWithAlgCache(_cached, jwk, alg); - } - catch { - continue; - } - } - }; - throw error; - } - return importWithAlgCache(this._cached, jwk, alg); - } -} -async function importWithAlgCache(cache, jwk, alg) { - const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); - if (cached[alg] === undefined) { - const keyObject = await importJWK({ ...jwk, ext: true }, alg); - if (keyObject.type !== 'public') { - throw new JWKSInvalid('JSON Web Key Set members must be public keys'); - } - cached[alg] = keyObject; - } - return cached[alg]; -} -export function createLocalJWKSet(jwks) { - return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); -} diff --git a/dist/node/esm/jwks/remote.js b/dist/node/esm/jwks/remote.js deleted file mode 100644 index 574ccff83b..0000000000 --- a/dist/node/esm/jwks/remote.js +++ /dev/null @@ -1,81 +0,0 @@ -import fetchJwks from '../runtime/fetch_jwks.js'; -import { isCloudflareWorkers } from '../runtime/env.js'; -import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.js'; -import { isJWKSLike, LocalJWKSet } from './local.js'; -class RemoteJWKSet extends LocalJWKSet { - constructor(url, options) { - super({ keys: [] }); - this._jwks = undefined; - if (!(url instanceof URL)) { - throw new TypeError('url must be an instance of URL'); - } - this._url = new URL(url.href); - this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; - this._timeoutDuration = - typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000; - this._cooldownDuration = - typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000; - this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000; - } - coolingDown() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cooldownDuration - : false; - } - fresh() { - return typeof this._jwksTimestamp === 'number' - ? Date.now() < this._jwksTimestamp + this._cacheMaxAge - : false; - } - async getKey(protectedHeader, token) { - if (!this._jwks || !this.fresh()) { - await this.reload(); - } - try { - return await super.getKey(protectedHeader, token); - } - catch (err) { - if (err instanceof JWKSNoMatchingKey) { - if (this.coolingDown() === false) { - await this.reload(); - return super.getKey(protectedHeader, token); - } - } - throw err; - } - } - async reload() { - if (this._pendingFetch && isCloudflareWorkers()) { - return new Promise((resolve) => { - const isDone = () => { - if (this._pendingFetch === undefined) { - resolve(); - } - else { - setTimeout(isDone, 5); - } - }; - isDone(); - }); - } - if (!this._pendingFetch) { - this._pendingFetch = fetchJwks(this._url, this._timeoutDuration, this._options) - .then((json) => { - if (!isJWKSLike(json)) { - throw new JWKSInvalid('JSON Web Key Set malformed'); - } - this._jwks = { keys: json.keys }; - this._jwksTimestamp = Date.now(); - this._pendingFetch = undefined; - }) - .catch((err) => { - this._pendingFetch = undefined; - throw err; - }); - } - await this._pendingFetch; - } -} -export function createRemoteJWKSet(url, options) { - return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); -} diff --git a/dist/node/esm/jws/compact/sign.js b/dist/node/esm/jws/compact/sign.js deleted file mode 100644 index b8e5ba0e2b..0000000000 --- a/dist/node/esm/jws/compact/sign.js +++ /dev/null @@ -1,17 +0,0 @@ -import { FlattenedSign } from '../flattened/sign.js'; -export class CompactSign { - constructor(payload) { - this._flattened = new FlattenedSign(payload); - } - setProtectedHeader(protectedHeader) { - this._flattened.setProtectedHeader(protectedHeader); - return this; - } - async sign(key, options) { - const jws = await this._flattened.sign(key, options); - if (jws.payload === undefined) { - throw new TypeError('use the flattened module for creating JWS with b64: false'); - } - return `${jws.protected}.${jws.payload}.${jws.signature}`; - } -} diff --git a/dist/node/esm/jws/compact/verify.js b/dist/node/esm/jws/compact/verify.js deleted file mode 100644 index c651ffb944..0000000000 --- a/dist/node/esm/jws/compact/verify.js +++ /dev/null @@ -1,21 +0,0 @@ -import { flattenedVerify } from '../flattened/verify.js'; -import { JWSInvalid } from '../../util/errors.js'; -import { decoder } from '../../lib/buffer_utils.js'; -export async function compactVerify(jws, key, options) { - if (jws instanceof Uint8Array) { - jws = decoder.decode(jws); - } - if (typeof jws !== 'string') { - throw new JWSInvalid('Compact JWS must be a string or Uint8Array'); - } - const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.'); - if (length !== 3) { - throw new JWSInvalid('Invalid Compact JWS'); - } - const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); - const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: verified.key }; - } - return result; -} diff --git a/dist/node/esm/jws/flattened/sign.js b/dist/node/esm/jws/flattened/sign.js deleted file mode 100644 index 76ae289654..0000000000 --- a/dist/node/esm/jws/flattened/sign.js +++ /dev/null @@ -1,81 +0,0 @@ -import { encode as base64url } from '../../runtime/base64url.js'; -import sign from '../../runtime/sign.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import { JWSInvalid } from '../../util/errors.js'; -import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; -import checkKeyType from '../../lib/check_key_type.js'; -import validateCrit from '../../lib/validate_crit.js'; -export class FlattenedSign { - constructor(payload) { - if (!(payload instanceof Uint8Array)) { - throw new TypeError('payload must be an instance of Uint8Array'); - } - this._payload = payload; - } - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this._unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this._unprotectedHeader = unprotectedHeader; - return this; - } - async sign(key, options) { - if (!this._protectedHeader && !this._unprotectedHeader) { - throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); - } - if (!isDisjoint(this._protectedHeader, this._unprotectedHeader)) { - throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...this._protectedHeader, - ...this._unprotectedHeader, - }; - const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); - let b64 = true; - if (extensions.has('b64')) { - b64 = this._protectedHeader.b64; - if (typeof b64 !== 'boolean') { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - checkKeyType(alg, key, 'sign'); - let payload = this._payload; - if (b64) { - payload = encoder.encode(base64url(payload)); - } - let protectedHeader; - if (this._protectedHeader) { - protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); - } - else { - protectedHeader = encoder.encode(''); - } - const data = concat(protectedHeader, encoder.encode('.'), payload); - const signature = await sign(alg, key, data); - const jws = { - signature: base64url(signature), - payload: '', - }; - if (b64) { - jws.payload = decoder.decode(payload); - } - if (this._unprotectedHeader) { - jws.header = this._unprotectedHeader; - } - if (this._protectedHeader) { - jws.protected = decoder.decode(protectedHeader); - } - return jws; - } -} diff --git a/dist/node/esm/jws/flattened/verify.js b/dist/node/esm/jws/flattened/verify.js deleted file mode 100644 index a6ea3c8a12..0000000000 --- a/dist/node/esm/jws/flattened/verify.js +++ /dev/null @@ -1,104 +0,0 @@ -import { decode as base64url } from '../../runtime/base64url.js'; -import verify from '../../runtime/verify.js'; -import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; -import { concat, encoder, decoder } from '../../lib/buffer_utils.js'; -import isDisjoint from '../../lib/is_disjoint.js'; -import isObject from '../../lib/is_object.js'; -import checkKeyType from '../../lib/check_key_type.js'; -import validateCrit from '../../lib/validate_crit.js'; -import validateAlgorithms from '../../lib/validate_algorithms.js'; -export async function flattenedVerify(jws, key, options) { - var _a; - if (!isObject(jws)) { - throw new JWSInvalid('Flattened JWS must be an object'); - } - if (jws.protected === undefined && jws.header === undefined) { - throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); - } - if (jws.protected !== undefined && typeof jws.protected !== 'string') { - throw new JWSInvalid('JWS Protected Header incorrect type'); - } - if (jws.payload === undefined) { - throw new JWSInvalid('JWS Payload missing'); - } - if (typeof jws.signature !== 'string') { - throw new JWSInvalid('JWS Signature missing or incorrect type'); - } - if (jws.header !== undefined && !isObject(jws.header)) { - throw new JWSInvalid('JWS Unprotected Header incorrect type'); - } - let parsedProt = {}; - if (jws.protected) { - try { - const protectedHeader = base64url(jws.protected); - parsedProt = JSON.parse(decoder.decode(protectedHeader)); - } - catch { - throw new JWSInvalid('JWS Protected Header is invalid'); - } - } - if (!isDisjoint(parsedProt, jws.header)) { - throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); - } - const joseHeader = { - ...parsedProt, - ...jws.header, - }; - const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); - let b64 = true; - if (extensions.has('b64')) { - b64 = parsedProt.b64; - if (typeof b64 !== 'boolean') { - throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); - } - } - const { alg } = joseHeader; - if (typeof alg !== 'string' || !alg) { - throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); - } - const algorithms = options && validateAlgorithms('algorithms', options.algorithms); - if (algorithms && !algorithms.has(alg)) { - throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); - } - if (b64) { - if (typeof jws.payload !== 'string') { - throw new JWSInvalid('JWS Payload must be a string'); - } - } - else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { - throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance'); - } - let resolvedKey = false; - if (typeof key === 'function') { - key = await key(parsedProt, jws); - resolvedKey = true; - } - checkKeyType(alg, key, 'verify'); - const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload); - const signature = base64url(jws.signature); - const verified = await verify(alg, key, signature, data); - if (!verified) { - throw new JWSSignatureVerificationFailed(); - } - let payload; - if (b64) { - payload = base64url(jws.payload); - } - else if (typeof jws.payload === 'string') { - payload = encoder.encode(jws.payload); - } - else { - payload = jws.payload; - } - const result = { payload }; - if (jws.protected !== undefined) { - result.protectedHeader = parsedProt; - } - if (jws.header !== undefined) { - result.unprotectedHeader = jws.header; - } - if (resolvedKey) { - return { ...result, key }; - } - return result; -} diff --git a/dist/node/esm/jws/general/sign.js b/dist/node/esm/jws/general/sign.js deleted file mode 100644 index 38d5a6d766..0000000000 --- a/dist/node/esm/jws/general/sign.js +++ /dev/null @@ -1,67 +0,0 @@ -import { FlattenedSign } from '../flattened/sign.js'; -import { JWSInvalid } from '../../util/errors.js'; -class IndividualSignature { - constructor(sig, key, options) { - this.parent = sig; - this.key = key; - this.options = options; - } - setProtectedHeader(protectedHeader) { - if (this.protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this.protectedHeader = protectedHeader; - return this; - } - setUnprotectedHeader(unprotectedHeader) { - if (this.unprotectedHeader) { - throw new TypeError('setUnprotectedHeader can only be called once'); - } - this.unprotectedHeader = unprotectedHeader; - return this; - } - addSignature(...args) { - return this.parent.addSignature(...args); - } - sign(...args) { - return this.parent.sign(...args); - } - done() { - return this.parent; - } -} -export class GeneralSign { - constructor(payload) { - this._signatures = []; - this._payload = payload; - } - addSignature(key, options) { - const signature = new IndividualSignature(this, key, options); - this._signatures.push(signature); - return signature; - } - async sign() { - if (!this._signatures.length) { - throw new JWSInvalid('at least one signature must be added'); - } - const jws = { - signatures: [], - payload: '', - }; - for (let i = 0; i < this._signatures.length; i++) { - const signature = this._signatures[i]; - const flattened = new FlattenedSign(this._payload); - flattened.setProtectedHeader(signature.protectedHeader); - flattened.setUnprotectedHeader(signature.unprotectedHeader); - const { payload, ...rest } = await flattened.sign(signature.key, signature.options); - if (i === 0) { - jws.payload = payload; - } - else if (jws.payload !== payload) { - throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)'); - } - jws.signatures.push(rest); - } - return jws; - } -} diff --git a/dist/node/esm/jws/general/verify.js b/dist/node/esm/jws/general/verify.js deleted file mode 100644 index c511b722dc..0000000000 --- a/dist/node/esm/jws/general/verify.js +++ /dev/null @@ -1,24 +0,0 @@ -import { flattenedVerify } from '../flattened/verify.js'; -import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; -import isObject from '../../lib/is_object.js'; -export async function generalVerify(jws, key, options) { - if (!isObject(jws)) { - throw new JWSInvalid('General JWS must be an object'); - } - if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { - throw new JWSInvalid('JWS Signatures missing or incorrect type'); - } - for (const signature of jws.signatures) { - try { - return await flattenedVerify({ - header: signature.header, - payload: jws.payload, - protected: signature.protected, - signature: signature.signature, - }, key, options); - } - catch { - } - } - throw new JWSSignatureVerificationFailed(); -} diff --git a/dist/node/esm/jwt/decrypt.js b/dist/node/esm/jwt/decrypt.js deleted file mode 100644 index 1ec2be28f2..0000000000 --- a/dist/node/esm/jwt/decrypt.js +++ /dev/null @@ -1,23 +0,0 @@ -import { compactDecrypt } from '../jwe/compact/decrypt.js'; -import jwtPayload from '../lib/jwt_claims_set.js'; -import { JWTClaimValidationFailed } from '../util/errors.js'; -export async function jwtDecrypt(jwt, key, options) { - const decrypted = await compactDecrypt(jwt, key, options); - const payload = jwtPayload(decrypted.protectedHeader, decrypted.plaintext, options); - const { protectedHeader } = decrypted; - if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { - throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', 'iss', 'mismatch'); - } - if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { - throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', 'sub', 'mismatch'); - } - if (protectedHeader.aud !== undefined && - JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { - throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch'); - } - const result = { payload, protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: decrypted.key }; - } - return result; -} diff --git a/dist/node/esm/jwt/encrypt.js b/dist/node/esm/jwt/encrypt.js deleted file mode 100644 index 15252957ae..0000000000 --- a/dist/node/esm/jwt/encrypt.js +++ /dev/null @@ -1,68 +0,0 @@ -import { CompactEncrypt } from '../jwe/compact/encrypt.js'; -import { encoder } from '../lib/buffer_utils.js'; -import { ProduceJWT } from './produce.js'; -export class EncryptJWT extends ProduceJWT { - setProtectedHeader(protectedHeader) { - if (this._protectedHeader) { - throw new TypeError('setProtectedHeader can only be called once'); - } - this._protectedHeader = protectedHeader; - return this; - } - setKeyManagementParameters(parameters) { - if (this._keyManagementParameters) { - throw new TypeError('setKeyManagementParameters can only be called once'); - } - this._keyManagementParameters = parameters; - return this; - } - setContentEncryptionKey(cek) { - if (this._cek) { - throw new TypeError('setContentEncryptionKey can only be called once'); - } - this._cek = cek; - return this; - } - setInitializationVector(iv) { - if (this._iv) { - throw new TypeError('setInitializationVector can only be called once'); - } - this._iv = iv; - return this; - } - replicateIssuerAsHeader() { - this._replicateIssuerAsHeader = true; - return this; - } - replicateSubjectAsHeader() { - this._replicateSubjectAsHeader = true; - return this; - } - replicateAudienceAsHeader() { - this._replicateAudienceAsHeader = true; - return this; - } - async encrypt(key, options) { - const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); - if (this._replicateIssuerAsHeader) { - this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; - } - if (this._replicateSubjectAsHeader) { - this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; - } - if (this._replicateAudienceAsHeader) { - this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; - } - enc.setProtectedHeader(this._protectedHeader); - if (this._iv) { - enc.setInitializationVector(this._iv); - } - if (this._cek) { - enc.setContentEncryptionKey(this._cek); - } - if (this._keyManagementParameters) { - enc.setKeyManagementParameters(this._keyManagementParameters); - } - return enc.encrypt(key, options); - } -} diff --git a/dist/node/esm/jwt/produce.js b/dist/node/esm/jwt/produce.js deleted file mode 100644 index 31c929a07c..0000000000 --- a/dist/node/esm/jwt/produce.js +++ /dev/null @@ -1,54 +0,0 @@ -import epoch from '../lib/epoch.js'; -import isObject from '../lib/is_object.js'; -import secs from '../lib/secs.js'; -export class ProduceJWT { - constructor(payload) { - if (!isObject(payload)) { - throw new TypeError('JWT Claims Set MUST be an object'); - } - this._payload = payload; - } - setIssuer(issuer) { - this._payload = { ...this._payload, iss: issuer }; - return this; - } - setSubject(subject) { - this._payload = { ...this._payload, sub: subject }; - return this; - } - setAudience(audience) { - this._payload = { ...this._payload, aud: audience }; - return this; - } - setJti(jwtId) { - this._payload = { ...this._payload, jti: jwtId }; - return this; - } - setNotBefore(input) { - if (typeof input === 'number') { - this._payload = { ...this._payload, nbf: input }; - } - else { - this._payload = { ...this._payload, nbf: epoch(new Date()) + secs(input) }; - } - return this; - } - setExpirationTime(input) { - if (typeof input === 'number') { - this._payload = { ...this._payload, exp: input }; - } - else { - this._payload = { ...this._payload, exp: epoch(new Date()) + secs(input) }; - } - return this; - } - setIssuedAt(input) { - if (typeof input === 'undefined') { - this._payload = { ...this._payload, iat: epoch(new Date()) }; - } - else { - this._payload = { ...this._payload, iat: input }; - } - return this; - } -} diff --git a/dist/node/esm/jwt/sign.js b/dist/node/esm/jwt/sign.js deleted file mode 100644 index 62352fbfa2..0000000000 --- a/dist/node/esm/jwt/sign.js +++ /dev/null @@ -1,21 +0,0 @@ -import { CompactSign } from '../jws/compact/sign.js'; -import { JWTInvalid } from '../util/errors.js'; -import { encoder } from '../lib/buffer_utils.js'; -import { ProduceJWT } from './produce.js'; -export class SignJWT extends ProduceJWT { - setProtectedHeader(protectedHeader) { - this._protectedHeader = protectedHeader; - return this; - } - async sign(key, options) { - var _a; - const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); - sig.setProtectedHeader(this._protectedHeader); - if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && - this._protectedHeader.crit.includes('b64') && - this._protectedHeader.b64 === false) { - throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); - } - return sig.sign(key, options); - } -} diff --git a/dist/node/esm/jwt/unsecured.js b/dist/node/esm/jwt/unsecured.js deleted file mode 100644 index 41c7c33bb5..0000000000 --- a/dist/node/esm/jwt/unsecured.js +++ /dev/null @@ -1,32 +0,0 @@ -import * as base64url from '../runtime/base64url.js'; -import { decoder } from '../lib/buffer_utils.js'; -import { JWTInvalid } from '../util/errors.js'; -import jwtPayload from '../lib/jwt_claims_set.js'; -import { ProduceJWT } from './produce.js'; -export class UnsecuredJWT extends ProduceJWT { - encode() { - const header = base64url.encode(JSON.stringify({ alg: 'none' })); - const payload = base64url.encode(JSON.stringify(this._payload)); - return `${header}.${payload}.`; - } - static decode(jwt, options) { - if (typeof jwt !== 'string') { - throw new JWTInvalid('Unsecured JWT must be a string'); - } - const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.'); - if (length !== 3 || signature !== '') { - throw new JWTInvalid('Invalid Unsecured JWT'); - } - let header; - try { - header = JSON.parse(decoder.decode(base64url.decode(encodedHeader))); - if (header.alg !== 'none') - throw new Error(); - } - catch { - throw new JWTInvalid('Invalid Unsecured JWT'); - } - const payload = jwtPayload(header, base64url.decode(encodedPayload), options); - return { payload, header }; - } -} diff --git a/dist/node/esm/jwt/verify.js b/dist/node/esm/jwt/verify.js deleted file mode 100644 index 89571c1847..0000000000 --- a/dist/node/esm/jwt/verify.js +++ /dev/null @@ -1,16 +0,0 @@ -import { compactVerify } from '../jws/compact/verify.js'; -import jwtPayload from '../lib/jwt_claims_set.js'; -import { JWTInvalid } from '../util/errors.js'; -export async function jwtVerify(jwt, key, options) { - var _a; - const verified = await compactVerify(jwt, key, options); - if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { - throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); - } - const payload = jwtPayload(verified.protectedHeader, verified.payload, options); - const result = { payload, protectedHeader: verified.protectedHeader }; - if (typeof key === 'function') { - return { ...result, key: verified.key }; - } - return result; -} diff --git a/dist/node/esm/key/export.js b/dist/node/esm/key/export.js deleted file mode 100644 index e4017047cd..0000000000 --- a/dist/node/esm/key/export.js +++ /dev/null @@ -1,12 +0,0 @@ -import { toSPKI as exportPublic } from '../runtime/asn1.js'; -import { toPKCS8 as exportPrivate } from '../runtime/asn1.js'; -import keyToJWK from '../runtime/key_to_jwk.js'; -export async function exportSPKI(key) { - return exportPublic(key); -} -export async function exportPKCS8(key) { - return exportPrivate(key); -} -export async function exportJWK(key) { - return keyToJWK(key); -} diff --git a/dist/node/esm/key/generate_key_pair.js b/dist/node/esm/key/generate_key_pair.js deleted file mode 100644 index 03b9ee54cd..0000000000 --- a/dist/node/esm/key/generate_key_pair.js +++ /dev/null @@ -1,4 +0,0 @@ -import { generateKeyPair as generate } from '../runtime/generate.js'; -export async function generateKeyPair(alg, options) { - return generate(alg, options); -} diff --git a/dist/node/esm/key/generate_secret.js b/dist/node/esm/key/generate_secret.js deleted file mode 100644 index 58f308a543..0000000000 --- a/dist/node/esm/key/generate_secret.js +++ /dev/null @@ -1,4 +0,0 @@ -import { generateSecret as generate } from '../runtime/generate.js'; -export async function generateSecret(alg, options) { - return generate(alg, options); -} diff --git a/dist/node/esm/key/import.js b/dist/node/esm/key/import.js deleted file mode 100644 index 25bb0e1659..0000000000 --- a/dist/node/esm/key/import.js +++ /dev/null @@ -1,50 +0,0 @@ -import { decode as decodeBase64URL } from '../runtime/base64url.js'; -import { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.js'; -import asKeyObject from '../runtime/jwk_to_key.js'; -import { JOSENotSupported } from '../util/errors.js'; -import isObject from '../lib/is_object.js'; -export async function importSPKI(spki, alg, options) { - if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { - throw new TypeError('"spki" must be SPKI formatted string'); - } - return fromSPKI(spki, alg, options); -} -export async function importX509(x509, alg, options) { - if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { - throw new TypeError('"x509" must be X.509 formatted string'); - } - return fromX509(x509, alg, options); -} -export async function importPKCS8(pkcs8, alg, options) { - if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { - throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); - } - return fromPKCS8(pkcs8, alg, options); -} -export async function importJWK(jwk, alg, octAsKeyObject) { - var _a; - if (!isObject(jwk)) { - throw new TypeError('JWK must be an object'); - } - alg || (alg = jwk.alg); - switch (jwk.kty) { - case 'oct': - if (typeof jwk.k !== 'string' || !jwk.k) { - throw new TypeError('missing "k" (Key Value) Parameter value'); - } - octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true); - if (octAsKeyObject) { - return asKeyObject({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); - } - return decodeBase64URL(jwk.k); - case 'RSA': - if (jwk.oth !== undefined) { - throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); - } - case 'EC': - case 'OKP': - return asKeyObject({ ...jwk, alg }); - default: - throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); - } -} diff --git a/dist/node/esm/lib/aesgcmkw.js b/dist/node/esm/lib/aesgcmkw.js deleted file mode 100644 index de3f4f91df..0000000000 --- a/dist/node/esm/lib/aesgcmkw.js +++ /dev/null @@ -1,14 +0,0 @@ -import encrypt from '../runtime/encrypt.js'; -import decrypt from '../runtime/decrypt.js'; -import generateIv from './iv.js'; -import { encode as base64url } from '../runtime/base64url.js'; -export async function wrap(alg, key, cek, iv) { - const jweAlgorithm = alg.slice(0, 7); - iv || (iv = generateIv(jweAlgorithm)); - const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0)); - return { encryptedKey, iv: base64url(iv), tag: base64url(tag) }; -} -export async function unwrap(alg, key, encryptedKey, iv, tag) { - const jweAlgorithm = alg.slice(0, 7); - return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); -} diff --git a/dist/node/esm/lib/buffer_utils.js b/dist/node/esm/lib/buffer_utils.js deleted file mode 100644 index 5a1a7b334d..0000000000 --- a/dist/node/esm/lib/buffer_utils.js +++ /dev/null @@ -1,51 +0,0 @@ -import digest from '../runtime/digest.js'; -export const encoder = new TextEncoder(); -export const decoder = new TextDecoder(); -const MAX_INT32 = 2 ** 32; -export function concat(...buffers) { - const size = buffers.reduce((acc, { length }) => acc + length, 0); - const buf = new Uint8Array(size); - let i = 0; - buffers.forEach((buffer) => { - buf.set(buffer, i); - i += buffer.length; - }); - return buf; -} -export function p2s(alg, p2sInput) { - return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); -} -function writeUInt32BE(buf, value, offset) { - if (value < 0 || value >= MAX_INT32) { - throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); - } - buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset); -} -export function uint64be(value) { - const high = Math.floor(value / MAX_INT32); - const low = value % MAX_INT32; - const buf = new Uint8Array(8); - writeUInt32BE(buf, high, 0); - writeUInt32BE(buf, low, 4); - return buf; -} -export function uint32be(value) { - const buf = new Uint8Array(4); - writeUInt32BE(buf, value); - return buf; -} -export function lengthAndInput(input) { - return concat(uint32be(input.length), input); -} -export async function concatKdf(secret, bits, value) { - const iterations = Math.ceil((bits >> 3) / 32); - const res = new Uint8Array(iterations * 32); - for (let iter = 0; iter < iterations; iter++) { - const buf = new Uint8Array(4 + secret.length + value.length); - buf.set(uint32be(iter + 1)); - buf.set(secret, 4); - buf.set(value, 4 + secret.length); - res.set(await digest('sha256', buf), iter * 32); - } - return res.slice(0, bits >> 3); -} diff --git a/dist/node/esm/lib/cek.js b/dist/node/esm/lib/cek.js deleted file mode 100644 index 34697d3ac2..0000000000 --- a/dist/node/esm/lib/cek.js +++ /dev/null @@ -1,20 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -import random from '../runtime/random.js'; -export function bitLength(alg) { - switch (alg) { - case 'A128GCM': - return 128; - case 'A192GCM': - return 192; - case 'A256GCM': - case 'A128CBC-HS256': - return 256; - case 'A192CBC-HS384': - return 384; - case 'A256CBC-HS512': - return 512; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/esm/lib/check_iv_length.js b/dist/node/esm/lib/check_iv_length.js deleted file mode 100644 index dcd28d3a9d..0000000000 --- a/dist/node/esm/lib/check_iv_length.js +++ /dev/null @@ -1,8 +0,0 @@ -import { JWEInvalid } from '../util/errors.js'; -import { bitLength } from './iv.js'; -const checkIvLength = (enc, iv) => { - if (iv.length << 3 !== bitLength(enc)) { - throw new JWEInvalid('Invalid Initialization Vector length'); - } -}; -export default checkIvLength; diff --git a/dist/node/esm/lib/check_key_type.js b/dist/node/esm/lib/check_key_type.js deleted file mode 100644 index 43f3dcbf14..0000000000 --- a/dist/node/esm/lib/check_key_type.js +++ /dev/null @@ -1,45 +0,0 @@ -import { withAlg as invalidKeyInput } from './invalid_key_input.js'; -import isKeyLike, { types } from '../runtime/is_key_like.js'; -const symmetricTypeCheck = (alg, key) => { - if (key instanceof Uint8Array) - return; - if (!isKeyLike(key)) { - throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array')); - } - if (key.type !== 'secret') { - throw new TypeError(`${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`); - } -}; -const asymmetricTypeCheck = (alg, key, usage) => { - if (!isKeyLike(key)) { - throw new TypeError(invalidKeyInput(alg, key, ...types)); - } - if (key.type === 'secret') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`); - } - if (usage === 'sign' && key.type === 'public') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`); - } - if (usage === 'decrypt' && key.type === 'public') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`); - } - if (key.algorithm && usage === 'verify' && key.type === 'private') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`); - } - if (key.algorithm && usage === 'encrypt' && key.type === 'private') { - throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`); - } -}; -const checkKeyType = (alg, key, usage) => { - const symmetric = alg.startsWith('HS') || - alg === 'dir' || - alg.startsWith('PBES2') || - /^A\d{3}(?:GCM)?KW$/.test(alg); - if (symmetric) { - symmetricTypeCheck(alg, key); - } - else { - asymmetricTypeCheck(alg, key, usage); - } -}; -export default checkKeyType; diff --git a/dist/node/esm/lib/check_p2s.js b/dist/node/esm/lib/check_p2s.js deleted file mode 100644 index a65289fa7a..0000000000 --- a/dist/node/esm/lib/check_p2s.js +++ /dev/null @@ -1,6 +0,0 @@ -import { JWEInvalid } from '../util/errors.js'; -export default function checkP2s(p2s) { - if (!(p2s instanceof Uint8Array) || p2s.length < 8) { - throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets'); - } -} diff --git a/dist/node/esm/lib/crypto_key.js b/dist/node/esm/lib/crypto_key.js deleted file mode 100644 index 4405b1915c..0000000000 --- a/dist/node/esm/lib/crypto_key.js +++ /dev/null @@ -1,158 +0,0 @@ -import { isCloudflareWorkers } from '../runtime/env.js'; -function unusable(name, prop = 'algorithm.name') { - return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); -} -function isAlgorithm(algorithm, name) { - return algorithm.name === name; -} -function getHashLength(hash) { - return parseInt(hash.name.slice(4), 10); -} -function getNamedCurve(alg) { - switch (alg) { - case 'ES256': - return 'P-256'; - case 'ES384': - return 'P-384'; - case 'ES512': - return 'P-521'; - default: - throw new Error('unreachable'); - } -} -function checkUsage(key, usages) { - if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { - let msg = 'CryptoKey does not support this operation, its usages must include '; - if (usages.length > 2) { - const last = usages.pop(); - msg += `one of ${usages.join(', ')}, or ${last}.`; - } - else if (usages.length === 2) { - msg += `one of ${usages[0]} or ${usages[1]}.`; - } - else { - msg += `${usages[0]}.`; - } - throw new TypeError(msg); - } -} -export function checkSigCryptoKey(key, alg, ...usages) { - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': { - if (!isAlgorithm(key.algorithm, 'HMAC')) - throw unusable('HMAC'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'RS256': - case 'RS384': - case 'RS512': { - if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) - throw unusable('RSASSA-PKCS1-v1_5'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'PS256': - case 'PS384': - case 'PS512': { - if (!isAlgorithm(key.algorithm, 'RSA-PSS')) - throw unusable('RSA-PSS'); - const expected = parseInt(alg.slice(2), 10); - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - case 'EdDSA': { - if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { - if (isCloudflareWorkers()) { - if (isAlgorithm(key.algorithm, 'NODE-ED25519')) - break; - throw unusable('Ed25519, Ed448, or NODE-ED25519'); - } - throw unusable('Ed25519 or Ed448'); - } - break; - } - case 'ES256': - case 'ES384': - case 'ES512': { - if (!isAlgorithm(key.algorithm, 'ECDSA')) - throw unusable('ECDSA'); - const expected = getNamedCurve(alg); - const actual = key.algorithm.namedCurve; - if (actual !== expected) - throw unusable(expected, 'algorithm.namedCurve'); - break; - } - default: - throw new TypeError('CryptoKey does not support this operation'); - } - checkUsage(key, usages); -} -export function checkEncCryptoKey(key, alg, ...usages) { - switch (alg) { - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': { - if (!isAlgorithm(key.algorithm, 'AES-GCM')) - throw unusable('AES-GCM'); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, 'algorithm.length'); - break; - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - if (!isAlgorithm(key.algorithm, 'AES-KW')) - throw unusable('AES-KW'); - const expected = parseInt(alg.slice(1, 4), 10); - const actual = key.algorithm.length; - if (actual !== expected) - throw unusable(expected, 'algorithm.length'); - break; - } - case 'ECDH': { - switch (key.algorithm.name) { - case 'ECDH': - case 'X25519': - case 'X448': - break; - default: - throw unusable('ECDH, X25519, or X448'); - } - break; - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': - if (!isAlgorithm(key.algorithm, 'PBKDF2')) - throw unusable('PBKDF2'); - break; - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) - throw unusable('RSA-OAEP'); - const expected = parseInt(alg.slice(9), 10) || 1; - const actual = getHashLength(key.algorithm.hash); - if (actual !== expected) - throw unusable(`SHA-${expected}`, 'algorithm.hash'); - break; - } - default: - throw new TypeError('CryptoKey does not support this operation'); - } - checkUsage(key, usages); -} diff --git a/dist/node/esm/lib/decrypt_key_management.js b/dist/node/esm/lib/decrypt_key_management.js deleted file mode 100644 index 87890a4fa0..0000000000 --- a/dist/node/esm/lib/decrypt_key_management.js +++ /dev/null @@ -1,98 +0,0 @@ -import { unwrap as aesKw } from '../runtime/aeskw.js'; -import * as ECDH from '../runtime/ecdhes.js'; -import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js'; -import { decrypt as rsaEs } from '../runtime/rsaes.js'; -import { decode as base64url } from '../runtime/base64url.js'; -import { JOSENotSupported, JWEInvalid } from '../util/errors.js'; -import { bitLength as cekLength } from '../lib/cek.js'; -import { importJWK } from '../key/import.js'; -import checkKeyType from './check_key_type.js'; -import isObject from './is_object.js'; -import { unwrap as aesGcmKw } from './aesgcmkw.js'; -async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { - checkKeyType(alg, key, 'decrypt'); - switch (alg) { - case 'dir': { - if (encryptedKey !== undefined) - throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); - return key; - } - case 'ECDH-ES': - if (encryptedKey !== undefined) - throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - if (!isObject(joseHeader.epk)) - throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); - if (!ECDH.ecdhAllowed(key)) - throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); - const epk = await importJWK(joseHeader.epk, alg); - let partyUInfo; - let partyVInfo; - if (joseHeader.apu !== undefined) { - if (typeof joseHeader.apu !== 'string') - throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); - partyUInfo = base64url(joseHeader.apu); - } - if (joseHeader.apv !== undefined) { - if (typeof joseHeader.apv !== 'string') - throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); - partyVInfo = base64url(joseHeader.apv); - } - const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); - if (alg === 'ECDH-ES') - return sharedSecret; - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - return aesKw(alg.slice(-6), sharedSecret, encryptedKey); - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - return rsaEs(alg, key, encryptedKey); - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - if (typeof joseHeader.p2c !== 'number') - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); - const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 10000; - if (joseHeader.p2c > p2cLimit) - throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); - if (typeof joseHeader.p2s !== 'string') - throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); - return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s)); - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - return aesKw(alg, key, encryptedKey); - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - if (encryptedKey === undefined) - throw new JWEInvalid('JWE Encrypted Key missing'); - if (typeof joseHeader.iv !== 'string') - throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); - if (typeof joseHeader.tag !== 'string') - throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); - const iv = base64url(joseHeader.iv); - const tag = base64url(joseHeader.tag); - return aesGcmKw(alg, key, encryptedKey, iv, tag); - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } -} -export default decryptKeyManagement; diff --git a/dist/node/esm/lib/encrypt_key_management.js b/dist/node/esm/lib/encrypt_key_management.js deleted file mode 100644 index eb9022c63e..0000000000 --- a/dist/node/esm/lib/encrypt_key_management.js +++ /dev/null @@ -1,87 +0,0 @@ -import { wrap as aesKw } from '../runtime/aeskw.js'; -import * as ECDH from '../runtime/ecdhes.js'; -import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js'; -import { encrypt as rsaEs } from '../runtime/rsaes.js'; -import { encode as base64url } from '../runtime/base64url.js'; -import generateCek, { bitLength as cekLength } from '../lib/cek.js'; -import { JOSENotSupported } from '../util/errors.js'; -import { exportJWK } from '../key/export.js'; -import checkKeyType from './check_key_type.js'; -import { wrap as aesGcmKw } from './aesgcmkw.js'; -async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { - let encryptedKey; - let parameters; - let cek; - checkKeyType(alg, key, 'encrypt'); - switch (alg) { - case 'dir': { - cek = key; - break; - } - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': { - if (!ECDH.ecdhAllowed(key)) { - throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); - } - const { apu, apv } = providedParameters; - let { epk: ephemeralKey } = providedParameters; - ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey); - const { x, y, crv, kty } = await exportJWK(ephemeralKey); - const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); - parameters = { epk: { x, crv, kty } }; - if (kty === 'EC') - parameters.epk.y = y; - if (apu) - parameters.apu = base64url(apu); - if (apv) - parameters.apv = base64url(apv); - if (alg === 'ECDH-ES') { - cek = sharedSecret; - break; - } - cek = providedCek || generateCek(enc); - const kwAlg = alg.slice(-6); - encryptedKey = await aesKw(kwAlg, sharedSecret, cek); - break; - } - case 'RSA1_5': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': { - cek = providedCek || generateCek(enc); - encryptedKey = await rsaEs(alg, key, cek); - break; - } - case 'PBES2-HS256+A128KW': - case 'PBES2-HS384+A192KW': - case 'PBES2-HS512+A256KW': { - cek = providedCek || generateCek(enc); - const { p2c, p2s } = providedParameters; - ({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s)); - break; - } - case 'A128KW': - case 'A192KW': - case 'A256KW': { - cek = providedCek || generateCek(enc); - encryptedKey = await aesKw(alg, key, cek); - break; - } - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': { - cek = providedCek || generateCek(enc); - const { iv } = providedParameters; - ({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv)); - break; - } - default: { - throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); - } - } - return { cek, encryptedKey, parameters }; -} -export default encryptKeyManagement; diff --git a/dist/node/esm/lib/epoch.js b/dist/node/esm/lib/epoch.js deleted file mode 100644 index e405e4b2df..0000000000 --- a/dist/node/esm/lib/epoch.js +++ /dev/null @@ -1 +0,0 @@ -export default (date) => Math.floor(date.getTime() / 1000); diff --git a/dist/node/esm/lib/invalid_key_input.js b/dist/node/esm/lib/invalid_key_input.js deleted file mode 100644 index 049e66ece0..0000000000 --- a/dist/node/esm/lib/invalid_key_input.js +++ /dev/null @@ -1,30 +0,0 @@ -function message(msg, actual, ...types) { - if (types.length > 2) { - const last = types.pop(); - msg += `one of type ${types.join(', ')}, or ${last}.`; - } - else if (types.length === 2) { - msg += `one of type ${types[0]} or ${types[1]}.`; - } - else { - msg += `of type ${types[0]}.`; - } - if (actual == null) { - msg += ` Received ${actual}`; - } - else if (typeof actual === 'function' && actual.name) { - msg += ` Received function ${actual.name}`; - } - else if (typeof actual === 'object' && actual != null) { - if (actual.constructor && actual.constructor.name) { - msg += ` Received an instance of ${actual.constructor.name}`; - } - } - return msg; -} -export default (actual, ...types) => { - return message('Key must be ', actual, ...types); -}; -export function withAlg(alg, actual, ...types) { - return message(`Key for the ${alg} algorithm must be `, actual, ...types); -} diff --git a/dist/node/esm/lib/is_disjoint.js b/dist/node/esm/lib/is_disjoint.js deleted file mode 100644 index 6f643502dc..0000000000 --- a/dist/node/esm/lib/is_disjoint.js +++ /dev/null @@ -1,22 +0,0 @@ -const isDisjoint = (...headers) => { - const sources = headers.filter(Boolean); - if (sources.length === 0 || sources.length === 1) { - return true; - } - let acc; - for (const header of sources) { - const parameters = Object.keys(header); - if (!acc || acc.size === 0) { - acc = new Set(parameters); - continue; - } - for (const parameter of parameters) { - if (acc.has(parameter)) { - return false; - } - acc.add(parameter); - } - } - return true; -}; -export default isDisjoint; diff --git a/dist/node/esm/lib/is_object.js b/dist/node/esm/lib/is_object.js deleted file mode 100644 index 4955e93225..0000000000 --- a/dist/node/esm/lib/is_object.js +++ /dev/null @@ -1,16 +0,0 @@ -function isObjectLike(value) { - return typeof value === 'object' && value !== null; -} -export default function isObject(input) { - if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { - return false; - } - if (Object.getPrototypeOf(input) === null) { - return true; - } - let proto = input; - while (Object.getPrototypeOf(proto) !== null) { - proto = Object.getPrototypeOf(proto); - } - return Object.getPrototypeOf(input) === proto; -} diff --git a/dist/node/esm/lib/iv.js b/dist/node/esm/lib/iv.js deleted file mode 100644 index cab2a12729..0000000000 --- a/dist/node/esm/lib/iv.js +++ /dev/null @@ -1,20 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -import random from '../runtime/random.js'; -export function bitLength(alg) { - switch (alg) { - case 'A128GCM': - case 'A128GCMKW': - case 'A192GCM': - case 'A192GCMKW': - case 'A256GCM': - case 'A256GCMKW': - return 96; - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return 128; - default: - throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); - } -} -export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/esm/lib/jwt_claims_set.js b/dist/node/esm/lib/jwt_claims_set.js deleted file mode 100644 index fc4193ad90..0000000000 --- a/dist/node/esm/lib/jwt_claims_set.js +++ /dev/null @@ -1,91 +0,0 @@ -import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js'; -import { decoder } from './buffer_utils.js'; -import epoch from './epoch.js'; -import secs from './secs.js'; -import isObject from './is_object.js'; -const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ''); -const checkAudiencePresence = (audPayload, audOption) => { - if (typeof audPayload === 'string') { - return audOption.includes(audPayload); - } - if (Array.isArray(audPayload)) { - return audOption.some(Set.prototype.has.bind(new Set(audPayload))); - } - return false; -}; -export default (protectedHeader, encodedPayload, options = {}) => { - const { typ } = options; - if (typ && - (typeof protectedHeader.typ !== 'string' || - normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { - throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed'); - } - let payload; - try { - payload = JSON.parse(decoder.decode(encodedPayload)); - } - catch { - } - if (!isObject(payload)) { - throw new JWTInvalid('JWT Claims Set must be a top-level JSON object'); - } - const { issuer } = options; - if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { - throw new JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed'); - } - const { subject } = options; - if (subject && payload.sub !== subject) { - throw new JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed'); - } - const { audience } = options; - if (audience && - !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) { - throw new JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed'); - } - let tolerance; - switch (typeof options.clockTolerance) { - case 'string': - tolerance = secs(options.clockTolerance); - break; - case 'number': - tolerance = options.clockTolerance; - break; - case 'undefined': - tolerance = 0; - break; - default: - throw new TypeError('Invalid clockTolerance option type'); - } - const { currentDate } = options; - const now = epoch(currentDate || new Date()); - if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { - throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid'); - } - if (payload.nbf !== undefined) { - if (typeof payload.nbf !== 'number') { - throw new JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid'); - } - if (payload.nbf > now + tolerance) { - throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', 'nbf', 'check_failed'); - } - } - if (payload.exp !== undefined) { - if (typeof payload.exp !== 'number') { - throw new JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid'); - } - if (payload.exp <= now - tolerance) { - throw new JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed'); - } - } - if (options.maxTokenAge) { - const age = now - payload.iat; - const max = typeof options.maxTokenAge === 'number' ? options.maxTokenAge : secs(options.maxTokenAge); - if (age - tolerance > max) { - throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', 'iat', 'check_failed'); - } - if (age < 0 - tolerance) { - throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed'); - } - } - return payload; -}; diff --git a/dist/node/esm/lib/secs.js b/dist/node/esm/lib/secs.js deleted file mode 100644 index cf470ed8ad..0000000000 --- a/dist/node/esm/lib/secs.js +++ /dev/null @@ -1,44 +0,0 @@ -const minute = 60; -const hour = minute * 60; -const day = hour * 24; -const week = day * 7; -const year = day * 365.25; -const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; -export default (str) => { - const matched = REGEX.exec(str); - if (!matched) { - throw new TypeError('Invalid time period format'); - } - const value = parseFloat(matched[1]); - const unit = matched[2].toLowerCase(); - switch (unit) { - case 'sec': - case 'secs': - case 'second': - case 'seconds': - case 's': - return Math.round(value); - case 'minute': - case 'minutes': - case 'min': - case 'mins': - case 'm': - return Math.round(value * minute); - case 'hour': - case 'hours': - case 'hr': - case 'hrs': - case 'h': - return Math.round(value * hour); - case 'day': - case 'days': - case 'd': - return Math.round(value * day); - case 'week': - case 'weeks': - case 'w': - return Math.round(value * week); - default: - return Math.round(value * year); - } -}; diff --git a/dist/node/esm/lib/validate_algorithms.js b/dist/node/esm/lib/validate_algorithms.js deleted file mode 100644 index a6a7918571..0000000000 --- a/dist/node/esm/lib/validate_algorithms.js +++ /dev/null @@ -1,11 +0,0 @@ -const validateAlgorithms = (option, algorithms) => { - if (algorithms !== undefined && - (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) { - throw new TypeError(`"${option}" option must be an array of strings`); - } - if (!algorithms) { - return undefined; - } - return new Set(algorithms); -}; -export default validateAlgorithms; diff --git a/dist/node/esm/lib/validate_crit.js b/dist/node/esm/lib/validate_crit.js deleted file mode 100644 index 68c69f18f5..0000000000 --- a/dist/node/esm/lib/validate_crit.js +++ /dev/null @@ -1,34 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { - if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { - throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); - } - if (!protectedHeader || protectedHeader.crit === undefined) { - return new Set(); - } - if (!Array.isArray(protectedHeader.crit) || - protectedHeader.crit.length === 0 || - protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) { - throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); - } - let recognized; - if (recognizedOption !== undefined) { - recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); - } - else { - recognized = recognizedDefault; - } - for (const parameter of protectedHeader.crit) { - if (!recognized.has(parameter)) { - throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); - } - if (joseHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" is missing`); - } - else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { - throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); - } - } - return new Set(protectedHeader.crit); -} -export default validateCrit; diff --git a/dist/node/esm/package.json b/dist/node/esm/package.json deleted file mode 100644 index 6990891ff3..0000000000 --- a/dist/node/esm/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "module"} diff --git a/dist/node/esm/runtime/aeskw.js b/dist/node/esm/runtime/aeskw.js deleted file mode 100644 index 722b8b37e5..0000000000 --- a/dist/node/esm/runtime/aeskw.js +++ /dev/null @@ -1,50 +0,0 @@ -import { Buffer } from 'buffer'; -import { KeyObject, createDecipheriv, createCipheriv, createSecretKey } from 'crypto'; -import { JOSENotSupported } from '../util/errors.js'; -import { concat } from '../lib/buffer_utils.js'; -import { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import supported from './ciphers.js'; -import { types } from './is_key_like.js'; -function checkKeySize(key, alg) { - if (key.symmetricKeySize << 3 !== parseInt(alg.slice(1, 4), 10)) { - throw new TypeError(`Invalid key size for alg: ${alg}`); - } -} -function ensureKeyObject(key, alg, usage) { - if (isKeyObject(key)) { - return key; - } - if (key instanceof Uint8Array) { - return createSecretKey(key); - } - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, usage); - return KeyObject.from(key); - } - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); -} -export const wrap = (alg, key, cek) => { - const size = parseInt(alg.slice(1, 4), 10); - const algorithm = `aes${size}-wrap`; - if (!supported(algorithm)) { - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } - const keyObject = ensureKeyObject(key, alg, 'wrapKey'); - checkKeySize(keyObject, alg); - const cipher = createCipheriv(algorithm, keyObject, Buffer.alloc(8, 0xa6)); - return concat(cipher.update(cek), cipher.final()); -}; -export const unwrap = (alg, key, encryptedKey) => { - const size = parseInt(alg.slice(1, 4), 10); - const algorithm = `aes${size}-wrap`; - if (!supported(algorithm)) { - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } - const keyObject = ensureKeyObject(key, alg, 'unwrapKey'); - checkKeySize(keyObject, alg); - const cipher = createDecipheriv(algorithm, keyObject, Buffer.alloc(8, 0xa6)); - return concat(cipher.update(encryptedKey), cipher.final()); -}; diff --git a/dist/node/esm/runtime/asn1.js b/dist/node/esm/runtime/asn1.js deleted file mode 100644 index d6f447eac0..0000000000 --- a/dist/node/esm/runtime/asn1.js +++ /dev/null @@ -1,46 +0,0 @@ -import { createPrivateKey, createPublicKey, KeyObject } from 'crypto'; -import { Buffer } from 'buffer'; -import { isCryptoKey } from './webcrypto.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -const genericExport = (keyType, keyFormat, key) => { - let keyObject; - if (isCryptoKey(key)) { - if (!key.extractable) { - throw new TypeError('CryptoKey is not extractable'); - } - keyObject = KeyObject.from(key); - } - else if (isKeyObject(key)) { - keyObject = key; - } - else { - throw new TypeError(invalidKeyInput(key, ...types)); - } - if (keyObject.type !== keyType) { - throw new TypeError(`key is not a ${keyType} key`); - } - return keyObject.export({ format: 'pem', type: keyFormat }); -}; -export const toSPKI = (key) => { - return genericExport('public', 'spki', key); -}; -export const toPKCS8 = (key) => { - return genericExport('private', 'pkcs8', key); -}; -export const fromPKCS8 = (pem) => createPrivateKey({ - key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, ''), 'base64'), - type: 'pkcs8', - format: 'der', -}); -export const fromSPKI = (pem) => createPublicKey({ - key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, ''), 'base64'), - type: 'spki', - format: 'der', -}); -export const fromX509 = (pem) => createPublicKey({ - key: pem, - type: 'spki', - format: 'pem', -}); diff --git a/dist/node/esm/runtime/asn1_sequence_decoder.js b/dist/node/esm/runtime/asn1_sequence_decoder.js deleted file mode 100644 index 61ba4c3116..0000000000 --- a/dist/node/esm/runtime/asn1_sequence_decoder.js +++ /dev/null @@ -1,44 +0,0 @@ -const tagInteger = 0x02; -const tagSequence = 0x30; -export default class Asn1SequenceDecoder { - constructor(buffer) { - if (buffer[0] !== tagSequence) { - throw new TypeError(); - } - this.buffer = buffer; - this.offset = 1; - const len = this.decodeLength(); - if (len !== buffer.length - this.offset) { - throw new TypeError(); - } - } - decodeLength() { - let length = this.buffer[this.offset++]; - if (length & 0x80) { - const nBytes = length & ~0x80; - length = 0; - for (let i = 0; i < nBytes; i++) - length = (length << 8) | this.buffer[this.offset + i]; - this.offset += nBytes; - } - return length; - } - unsignedInteger() { - if (this.buffer[this.offset++] !== tagInteger) { - throw new TypeError(); - } - let length = this.decodeLength(); - if (this.buffer[this.offset] === 0) { - this.offset++; - length--; - } - const result = this.buffer.slice(this.offset, this.offset + length); - this.offset += length; - return result; - } - end() { - if (this.offset !== this.buffer.length) { - throw new TypeError(); - } - } -} diff --git a/dist/node/esm/runtime/asn1_sequence_encoder.js b/dist/node/esm/runtime/asn1_sequence_encoder.js deleted file mode 100644 index ac672776a4..0000000000 --- a/dist/node/esm/runtime/asn1_sequence_encoder.js +++ /dev/null @@ -1,88 +0,0 @@ -import { Buffer } from 'buffer'; -import { JOSENotSupported } from '../util/errors.js'; -const tagInteger = 0x02; -const tagBitStr = 0x03; -const tagOctStr = 0x04; -const tagSequence = 0x30; -const bZero = Buffer.from([0x00]); -const bTagInteger = Buffer.from([tagInteger]); -const bTagBitStr = Buffer.from([tagBitStr]); -const bTagSequence = Buffer.from([tagSequence]); -const bTagOctStr = Buffer.from([tagOctStr]); -const encodeLength = (len) => { - if (len < 128) - return Buffer.from([len]); - const buffer = Buffer.alloc(5); - buffer.writeUInt32BE(len, 1); - let offset = 1; - while (buffer[offset] === 0) - offset++; - buffer[offset - 1] = 0x80 | (5 - offset); - return buffer.slice(offset - 1); -}; -const oids = new Map([ - ['P-256', Buffer.from('06 08 2A 86 48 CE 3D 03 01 07'.replace(/ /g, ''), 'hex')], - ['secp256k1', Buffer.from('06 05 2B 81 04 00 0A'.replace(/ /g, ''), 'hex')], - ['P-384', Buffer.from('06 05 2B 81 04 00 22'.replace(/ /g, ''), 'hex')], - ['P-521', Buffer.from('06 05 2B 81 04 00 23'.replace(/ /g, ''), 'hex')], - ['ecPublicKey', Buffer.from('06 07 2A 86 48 CE 3D 02 01'.replace(/ /g, ''), 'hex')], - ['X25519', Buffer.from('06 03 2B 65 6E'.replace(/ /g, ''), 'hex')], - ['X448', Buffer.from('06 03 2B 65 6F'.replace(/ /g, ''), 'hex')], - ['Ed25519', Buffer.from('06 03 2B 65 70'.replace(/ /g, ''), 'hex')], - ['Ed448', Buffer.from('06 03 2B 65 71'.replace(/ /g, ''), 'hex')], -]); -export default class DumbAsn1Encoder { - constructor() { - this.length = 0; - this.elements = []; - } - oidFor(oid) { - const bOid = oids.get(oid); - if (!bOid) { - throw new JOSENotSupported('Invalid or unsupported OID'); - } - this.elements.push(bOid); - this.length += bOid.length; - } - zero() { - this.elements.push(bTagInteger, Buffer.from([0x01]), bZero); - this.length += 3; - } - one() { - this.elements.push(bTagInteger, Buffer.from([0x01]), Buffer.from([0x01])); - this.length += 3; - } - unsignedInteger(integer) { - if (integer[0] & 0x80) { - const len = encodeLength(integer.length + 1); - this.elements.push(bTagInteger, len, bZero, integer); - this.length += 2 + len.length + integer.length; - } - else { - let i = 0; - while (integer[i] === 0 && (integer[i + 1] & 0x80) === 0) - i++; - const len = encodeLength(integer.length - i); - this.elements.push(bTagInteger, encodeLength(integer.length - i), integer.slice(i)); - this.length += 1 + len.length + integer.length - i; - } - } - octStr(octStr) { - const len = encodeLength(octStr.length); - this.elements.push(bTagOctStr, encodeLength(octStr.length), octStr); - this.length += 1 + len.length + octStr.length; - } - bitStr(bitS) { - const len = encodeLength(bitS.length + 1); - this.elements.push(bTagBitStr, encodeLength(bitS.length + 1), bZero, bitS); - this.length += 1 + len.length + bitS.length + 1; - } - add(seq) { - this.elements.push(seq); - this.length += seq.length; - } - end(tag = bTagSequence) { - const len = encodeLength(this.length); - return Buffer.concat([tag, len, ...this.elements], 1 + len.length + this.length); - } -} diff --git a/dist/node/esm/runtime/base64url.js b/dist/node/esm/runtime/base64url.js deleted file mode 100644 index 1579359fdf..0000000000 --- a/dist/node/esm/runtime/base64url.js +++ /dev/null @@ -1,20 +0,0 @@ -import { Buffer } from 'buffer'; -import { decoder } from '../lib/buffer_utils.js'; -let encode; -function normalize(input) { - let encoded = input; - if (encoded instanceof Uint8Array) { - encoded = decoder.decode(encoded); - } - return encoded; -} -if (Buffer.isEncoding('base64url')) { - encode = (input) => Buffer.from(input).toString('base64url'); -} -else { - encode = (input) => Buffer.from(input).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); -} -export const decodeBase64 = (input) => Buffer.from(input, 'base64'); -export const encodeBase64 = (input) => Buffer.from(input).toString('base64'); -export { encode }; -export const decode = (input) => Buffer.from(normalize(input), 'base64'); diff --git a/dist/node/esm/runtime/cbc_tag.js b/dist/node/esm/runtime/cbc_tag.js deleted file mode 100644 index fa58c38b6c..0000000000 --- a/dist/node/esm/runtime/cbc_tag.js +++ /dev/null @@ -1,8 +0,0 @@ -import { createHmac } from 'crypto'; -import { concat, uint64be } from '../lib/buffer_utils.js'; -export default function cbcTag(aad, iv, ciphertext, macSize, macKey, keySize) { - const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); - const hmac = createHmac(`sha${macSize}`, macKey); - hmac.update(macData); - return hmac.digest().slice(0, keySize >> 3); -} diff --git a/dist/node/esm/runtime/check_cek_length.js b/dist/node/esm/runtime/check_cek_length.js deleted file mode 100644 index 60884c0ea5..0000000000 --- a/dist/node/esm/runtime/check_cek_length.js +++ /dev/null @@ -1,35 +0,0 @@ -import { JWEInvalid, JOSENotSupported } from '../util/errors.js'; -import isKeyObject from './is_key_object.js'; -const checkCekLength = (enc, cek) => { - let expected; - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - expected = parseInt(enc.slice(-3), 10); - break; - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - expected = parseInt(enc.slice(1, 4), 10); - break; - default: - throw new JOSENotSupported(`Content Encryption Algorithm ${enc} is not supported either by JOSE or your javascript runtime`); - } - if (cek instanceof Uint8Array) { - const actual = cek.byteLength << 3; - if (actual !== expected) { - throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); - } - return; - } - if (isKeyObject(cek) && cek.type === 'secret') { - const actual = cek.symmetricKeySize << 3; - if (actual !== expected) { - throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); - } - return; - } - throw new TypeError('Invalid Content Encryption Key type'); -}; -export default checkCekLength; diff --git a/dist/node/esm/runtime/check_modulus_length.js b/dist/node/esm/runtime/check_modulus_length.js deleted file mode 100644 index 690f809602..0000000000 --- a/dist/node/esm/runtime/check_modulus_length.js +++ /dev/null @@ -1,48 +0,0 @@ -export const weakMap = new WeakMap(); -const getLength = (buf, index) => { - let len = buf.readUInt8(1); - if ((len & 0x80) === 0) { - if (index === 0) { - return len; - } - return getLength(buf.subarray(2 + len), index - 1); - } - const num = len & 0x7f; - len = 0; - for (let i = 0; i < num; i++) { - len <<= 8; - const j = buf.readUInt8(2 + i); - len |= j; - } - if (index === 0) { - return len; - } - return getLength(buf.subarray(2 + len), index - 1); -}; -const getLengthOfSeqIndex = (sequence, index) => { - const len = sequence.readUInt8(1); - if ((len & 0x80) === 0) { - return getLength(sequence.subarray(2), index); - } - const num = len & 0x7f; - return getLength(sequence.subarray(2 + num), index); -}; -const getModulusLength = (key) => { - var _a, _b; - if (weakMap.has(key)) { - return weakMap.get(key); - } - const modulusLength = (_b = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.modulusLength) !== null && _b !== void 0 ? _b : (getLengthOfSeqIndex(key.export({ format: 'der', type: 'pkcs1' }), key.type === 'private' ? 1 : 0) - - 1) << - 3; - weakMap.set(key, modulusLength); - return modulusLength; -}; -export const setModulusLength = (keyObject, modulusLength) => { - weakMap.set(keyObject, modulusLength); -}; -export default (key, alg) => { - if (getModulusLength(key) < 2048) { - throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); - } -}; diff --git a/dist/node/esm/runtime/ciphers.js b/dist/node/esm/runtime/ciphers.js deleted file mode 100644 index daded1d503..0000000000 --- a/dist/node/esm/runtime/ciphers.js +++ /dev/null @@ -1,6 +0,0 @@ -import { getCiphers } from 'crypto'; -let ciphers; -export default (algorithm) => { - ciphers || (ciphers = new Set(getCiphers())); - return ciphers.has(algorithm); -}; diff --git a/dist/node/esm/runtime/decrypt.js b/dist/node/esm/runtime/decrypt.js deleted file mode 100644 index 8a611d174b..0000000000 --- a/dist/node/esm/runtime/decrypt.js +++ /dev/null @@ -1,95 +0,0 @@ -import { createDecipheriv, KeyObject } from 'crypto'; -import checkIvLength from '../lib/check_iv_length.js'; -import checkCekLength from './check_cek_length.js'; -import { concat } from '../lib/buffer_utils.js'; -import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js'; -import timingSafeEqual from './timing_safe_equal.js'; -import cbcTag from './cbc_tag.js'; -import { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import supported from './ciphers.js'; -import { types } from './is_key_like.js'; -function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - if (isKeyObject(cek)) { - cek = cek.export(); - } - const encKey = cek.subarray(keySize >> 3); - const macKey = cek.subarray(0, keySize >> 3); - const macSize = parseInt(enc.slice(-3), 10); - const algorithm = `aes-${keySize}-cbc`; - if (!supported(algorithm)) { - throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - const expectedTag = cbcTag(aad, iv, ciphertext, macSize, macKey, keySize); - let macCheckPassed; - try { - macCheckPassed = timingSafeEqual(tag, expectedTag); - } - catch { - } - if (!macCheckPassed) { - throw new JWEDecryptionFailed(); - } - let plaintext; - try { - const decipher = createDecipheriv(algorithm, encKey, iv); - plaintext = concat(decipher.update(ciphertext), decipher.final()); - } - catch { - } - if (!plaintext) { - throw new JWEDecryptionFailed(); - } - return plaintext; -} -function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - const algorithm = `aes-${keySize}-gcm`; - if (!supported(algorithm)) { - throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - try { - const decipher = createDecipheriv(algorithm, cek, iv, { authTagLength: 16 }); - decipher.setAuthTag(tag); - if (aad.byteLength) { - decipher.setAAD(aad, { plaintextLength: ciphertext.length }); - } - const plaintext = decipher.update(ciphertext); - decipher.final(); - return plaintext; - } - catch { - throw new JWEDecryptionFailed(); - } -} -const decrypt = (enc, cek, ciphertext, iv, tag, aad) => { - let key; - if (isCryptoKey(cek)) { - checkEncCryptoKey(cek, enc, 'decrypt'); - key = KeyObject.from(cek); - } - else if (cek instanceof Uint8Array || isKeyObject(cek)) { - key = cek; - } - else { - throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); - } - checkCekLength(enc, key); - checkIvLength(enc, iv); - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return cbcDecrypt(enc, key, ciphertext, iv, tag, aad); - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - return gcmDecrypt(enc, key, ciphertext, iv, tag, aad); - default: - throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); - } -}; -export default decrypt; diff --git a/dist/node/esm/runtime/digest.js b/dist/node/esm/runtime/digest.js deleted file mode 100644 index 0facde6c29..0000000000 --- a/dist/node/esm/runtime/digest.js +++ /dev/null @@ -1,3 +0,0 @@ -import { createHash } from 'crypto'; -const digest = (algorithm, data) => createHash(algorithm).update(data).digest(); -export default digest; diff --git a/dist/node/esm/runtime/dsa_digest.js b/dist/node/esm/runtime/dsa_digest.js deleted file mode 100644 index ce7215bd67..0000000000 --- a/dist/node/esm/runtime/dsa_digest.js +++ /dev/null @@ -1,22 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -export default function dsaDigest(alg) { - switch (alg) { - case 'PS256': - case 'RS256': - case 'ES256': - case 'ES256K': - return 'sha256'; - case 'PS384': - case 'RS384': - case 'ES384': - return 'sha384'; - case 'PS512': - case 'RS512': - case 'ES512': - return 'sha512'; - case 'EdDSA': - return undefined; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} diff --git a/dist/node/esm/runtime/ecdhes.js b/dist/node/esm/runtime/ecdhes.js deleted file mode 100644 index d3faef4a05..0000000000 --- a/dist/node/esm/runtime/ecdhes.js +++ /dev/null @@ -1,64 +0,0 @@ -import { diffieHellman, generateKeyPair as generateKeyPairCb, KeyObject } from 'crypto'; -import { promisify } from 'util'; -import getNamedCurve from './get_named_curve.js'; -import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.js'; -import { JOSENotSupported } from '../util/errors.js'; -import { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -const generateKeyPair = promisify(generateKeyPairCb); -export async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { - let publicKey; - if (isCryptoKey(publicKee)) { - checkEncCryptoKey(publicKee, 'ECDH'); - publicKey = KeyObject.from(publicKee); - } - else if (isKeyObject(publicKee)) { - publicKey = publicKee; - } - else { - throw new TypeError(invalidKeyInput(publicKee, ...types)); - } - let privateKey; - if (isCryptoKey(privateKee)) { - checkEncCryptoKey(privateKee, 'ECDH', 'deriveBits'); - privateKey = KeyObject.from(privateKee); - } - else if (isKeyObject(privateKee)) { - privateKey = privateKee; - } - else { - throw new TypeError(invalidKeyInput(privateKee, ...types)); - } - const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); - const sharedSecret = diffieHellman({ privateKey, publicKey }); - return concatKdf(sharedSecret, keyLength, value); -} -export async function generateEpk(kee) { - let key; - if (isCryptoKey(kee)) { - key = KeyObject.from(kee); - } - else if (isKeyObject(kee)) { - key = kee; - } - else { - throw new TypeError(invalidKeyInput(kee, ...types)); - } - switch (key.asymmetricKeyType) { - case 'x25519': - return generateKeyPair('x25519'); - case 'x448': { - return generateKeyPair('x448'); - } - case 'ec': { - const namedCurve = getNamedCurve(key); - return generateKeyPair('ec', { namedCurve }); - } - default: - throw new JOSENotSupported('Invalid or unsupported EPK'); - } -} -export const ecdhAllowed = (key) => ['P-256', 'P-384', 'P-521', 'X25519', 'X448'].includes(getNamedCurve(key)); diff --git a/dist/node/esm/runtime/encrypt.js b/dist/node/esm/runtime/encrypt.js deleted file mode 100644 index 8dfb87b10c..0000000000 --- a/dist/node/esm/runtime/encrypt.js +++ /dev/null @@ -1,72 +0,0 @@ -import { createCipheriv, KeyObject } from 'crypto'; -import checkIvLength from '../lib/check_iv_length.js'; -import checkCekLength from './check_cek_length.js'; -import { concat } from '../lib/buffer_utils.js'; -import cbcTag from './cbc_tag.js'; -import { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { JOSENotSupported } from '../util/errors.js'; -import supported from './ciphers.js'; -import { types } from './is_key_like.js'; -function cbcEncrypt(enc, plaintext, cek, iv, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - if (isKeyObject(cek)) { - cek = cek.export(); - } - const encKey = cek.subarray(keySize >> 3); - const macKey = cek.subarray(0, keySize >> 3); - const algorithm = `aes-${keySize}-cbc`; - if (!supported(algorithm)) { - throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - const cipher = createCipheriv(algorithm, encKey, iv); - const ciphertext = concat(cipher.update(plaintext), cipher.final()); - const macSize = parseInt(enc.slice(-3), 10); - const tag = cbcTag(aad, iv, ciphertext, macSize, macKey, keySize); - return { ciphertext, tag }; -} -function gcmEncrypt(enc, plaintext, cek, iv, aad) { - const keySize = parseInt(enc.slice(1, 4), 10); - const algorithm = `aes-${keySize}-gcm`; - if (!supported(algorithm)) { - throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); - } - const cipher = createCipheriv(algorithm, cek, iv, { authTagLength: 16 }); - if (aad.byteLength) { - cipher.setAAD(aad, { plaintextLength: plaintext.length }); - } - const ciphertext = cipher.update(plaintext); - cipher.final(); - const tag = cipher.getAuthTag(); - return { ciphertext, tag }; -} -const encrypt = (enc, plaintext, cek, iv, aad) => { - let key; - if (isCryptoKey(cek)) { - checkEncCryptoKey(cek, enc, 'encrypt'); - key = KeyObject.from(cek); - } - else if (cek instanceof Uint8Array || isKeyObject(cek)) { - key = cek; - } - else { - throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); - } - checkCekLength(enc, key); - checkIvLength(enc, iv); - switch (enc) { - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - return cbcEncrypt(enc, plaintext, key, iv, aad); - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - return gcmEncrypt(enc, plaintext, key, iv, aad); - default: - throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); - } -}; -export default encrypt; diff --git a/dist/node/esm/runtime/env.js b/dist/node/esm/runtime/env.js deleted file mode 100644 index f55de30dc1..0000000000 --- a/dist/node/esm/runtime/env.js +++ /dev/null @@ -1,3 +0,0 @@ -export function isCloudflareWorkers() { - return false; -} diff --git a/dist/node/esm/runtime/fetch_jwks.js b/dist/node/esm/runtime/fetch_jwks.js deleted file mode 100644 index 5853424ec1..0000000000 --- a/dist/node/esm/runtime/fetch_jwks.js +++ /dev/null @@ -1,43 +0,0 @@ -import * as http from 'http'; -import * as https from 'https'; -import { once } from 'events'; -import { JOSEError, JWKSTimeout } from '../util/errors.js'; -import { concat, decoder } from '../lib/buffer_utils.js'; -const fetchJwks = async (url, timeout, options) => { - let get; - switch (url.protocol) { - case 'https:': - get = https.get; - break; - case 'http:': - get = http.get; - break; - default: - throw new TypeError('Unsupported URL protocol.'); - } - const { agent, headers } = options; - const req = get(url.href, { - agent, - timeout, - headers, - }); - const [response] = (await Promise.race([once(req, 'response'), once(req, 'timeout')])); - if (!response) { - req.destroy(); - throw new JWKSTimeout(); - } - if (response.statusCode !== 200) { - throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response'); - } - const parts = []; - for await (const part of response) { - parts.push(part); - } - try { - return JSON.parse(decoder.decode(concat(...parts))); - } - catch { - throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON'); - } -}; -export default fetchJwks; diff --git a/dist/node/esm/runtime/flags.js b/dist/node/esm/runtime/flags.js deleted file mode 100644 index 390299593f..0000000000 --- a/dist/node/esm/runtime/flags.js +++ /dev/null @@ -1,5 +0,0 @@ -const [major, minor] = process.versions.node.split('.').map((str) => parseInt(str, 10)); -export const oneShotCallback = major >= 16 || (major === 15 && minor >= 13); -export const rsaPssParams = !('electron' in process.versions) && (major >= 17 || (major === 16 && minor >= 9)); -export const jwkExport = major >= 16 || (major === 15 && minor >= 9); -export const jwkImport = major >= 16 || (major === 15 && minor >= 12); diff --git a/dist/node/esm/runtime/generate.js b/dist/node/esm/runtime/generate.js deleted file mode 100644 index 64f76962f1..0000000000 --- a/dist/node/esm/runtime/generate.js +++ /dev/null @@ -1,100 +0,0 @@ -import { createSecretKey, generateKeyPair as generateKeyPairCb } from 'crypto'; -import { promisify } from 'util'; -import random from './random.js'; -import { setModulusLength } from './check_modulus_length.js'; -import { JOSENotSupported } from '../util/errors.js'; -const generate = promisify(generateKeyPairCb); -export async function generateSecret(alg, options) { - let length; - switch (alg) { - case 'HS256': - case 'HS384': - case 'HS512': - case 'A128CBC-HS256': - case 'A192CBC-HS384': - case 'A256CBC-HS512': - length = parseInt(alg.slice(-3), 10); - break; - case 'A128KW': - case 'A192KW': - case 'A256KW': - case 'A128GCMKW': - case 'A192GCMKW': - case 'A256GCMKW': - case 'A128GCM': - case 'A192GCM': - case 'A256GCM': - length = parseInt(alg.slice(1, 4), 10); - break; - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } - return createSecretKey(random(new Uint8Array(length >> 3))); -} -export async function generateKeyPair(alg, options) { - var _a, _b; - switch (alg) { - case 'RS256': - case 'RS384': - case 'RS512': - case 'PS256': - case 'PS384': - case 'PS512': - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - case 'RSA1_5': { - const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; - if (typeof modulusLength !== 'number' || modulusLength < 2048) { - throw new JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used'); - } - const keypair = await generate('rsa', { - modulusLength, - publicExponent: 0x10001, - }); - setModulusLength(keypair.privateKey, modulusLength); - setModulusLength(keypair.publicKey, modulusLength); - return keypair; - } - case 'ES256': - return generate('ec', { namedCurve: 'P-256' }); - case 'ES256K': - return generate('ec', { namedCurve: 'secp256k1' }); - case 'ES384': - return generate('ec', { namedCurve: 'P-384' }); - case 'ES512': - return generate('ec', { namedCurve: 'P-521' }); - case 'EdDSA': { - switch (options === null || options === void 0 ? void 0 : options.crv) { - case undefined: - case 'Ed25519': - return generate('ed25519'); - case 'Ed448': - return generate('ed448'); - default: - throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are Ed25519 and Ed448'); - } - } - case 'ECDH-ES': - case 'ECDH-ES+A128KW': - case 'ECDH-ES+A192KW': - case 'ECDH-ES+A256KW': - const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256'; - switch (crv) { - case undefined: - case 'P-256': - case 'P-384': - case 'P-521': - return generate('ec', { namedCurve: crv }); - case 'X25519': - return generate('x25519'); - case 'X448': - return generate('x448'); - default: - throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448'); - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); - } -} diff --git a/dist/node/esm/runtime/get_named_curve.js b/dist/node/esm/runtime/get_named_curve.js deleted file mode 100644 index e453a6660e..0000000000 --- a/dist/node/esm/runtime/get_named_curve.js +++ /dev/null @@ -1,91 +0,0 @@ -import { Buffer } from 'buffer'; -import { createPublicKey, KeyObject } from 'crypto'; -import { JOSENotSupported } from '../util/errors.js'; -import { isCryptoKey } from './webcrypto.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -const p256 = Buffer.from([42, 134, 72, 206, 61, 3, 1, 7]); -const p384 = Buffer.from([43, 129, 4, 0, 34]); -const p521 = Buffer.from([43, 129, 4, 0, 35]); -const secp256k1 = Buffer.from([43, 129, 4, 0, 10]); -export const weakMap = new WeakMap(); -const namedCurveToJOSE = (namedCurve) => { - switch (namedCurve) { - case 'prime256v1': - return 'P-256'; - case 'secp384r1': - return 'P-384'; - case 'secp521r1': - return 'P-521'; - case 'secp256k1': - return 'secp256k1'; - default: - throw new JOSENotSupported('Unsupported key curve for this operation'); - } -}; -const getNamedCurve = (kee, raw) => { - var _a; - let key; - if (isCryptoKey(kee)) { - key = KeyObject.from(kee); - } - else if (isKeyObject(kee)) { - key = kee; - } - else { - throw new TypeError(invalidKeyInput(kee, ...types)); - } - if (key.type === 'secret') { - throw new TypeError('only "private" or "public" type keys can be used for this operation'); - } - switch (key.asymmetricKeyType) { - case 'ed25519': - case 'ed448': - return `Ed${key.asymmetricKeyType.slice(2)}`; - case 'x25519': - case 'x448': - return `X${key.asymmetricKeyType.slice(1)}`; - case 'ec': { - if (weakMap.has(key)) { - return weakMap.get(key); - } - let namedCurve = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.namedCurve; - if (!namedCurve && key.type === 'private') { - namedCurve = getNamedCurve(createPublicKey(key), true); - } - else if (!namedCurve) { - const buf = key.export({ format: 'der', type: 'spki' }); - const i = buf[1] < 128 ? 14 : 15; - const len = buf[i]; - const curveOid = buf.slice(i + 1, i + 1 + len); - if (curveOid.equals(p256)) { - namedCurve = 'prime256v1'; - } - else if (curveOid.equals(p384)) { - namedCurve = 'secp384r1'; - } - else if (curveOid.equals(p521)) { - namedCurve = 'secp521r1'; - } - else if (curveOid.equals(secp256k1)) { - namedCurve = 'secp256k1'; - } - else { - throw new JOSENotSupported('Unsupported key curve for this operation'); - } - } - if (raw) - return namedCurve; - const curve = namedCurveToJOSE(namedCurve); - weakMap.set(key, curve); - return curve; - } - default: - throw new TypeError('Invalid asymmetric key type for this operation'); - } -}; -export function setCurve(keyObject, curve) { - weakMap.set(keyObject, curve); -} -export default getNamedCurve; diff --git a/dist/node/esm/runtime/get_sign_verify_key.js b/dist/node/esm/runtime/get_sign_verify_key.js deleted file mode 100644 index 46aa2b4551..0000000000 --- a/dist/node/esm/runtime/get_sign_verify_key.js +++ /dev/null @@ -1,21 +0,0 @@ -import { KeyObject, createSecretKey } from 'crypto'; -import { isCryptoKey } from './webcrypto.js'; -import { checkSigCryptoKey } from '../lib/crypto_key.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -export default function getSignVerifyKey(alg, key, usage) { - if (key instanceof Uint8Array) { - if (!alg.startsWith('HS')) { - throw new TypeError(invalidKeyInput(key, ...types)); - } - return createSecretKey(key); - } - if (key instanceof KeyObject) { - return key; - } - if (isCryptoKey(key)) { - checkSigCryptoKey(key, alg, usage); - return KeyObject.from(key); - } - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); -} diff --git a/dist/node/esm/runtime/hmac_digest.js b/dist/node/esm/runtime/hmac_digest.js deleted file mode 100644 index 29d55c3e9c..0000000000 --- a/dist/node/esm/runtime/hmac_digest.js +++ /dev/null @@ -1,13 +0,0 @@ -import { JOSENotSupported } from '../util/errors.js'; -export default function hmacDigest(alg) { - switch (alg) { - case 'HS256': - return 'sha256'; - case 'HS384': - return 'sha384'; - case 'HS512': - return 'sha512'; - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} diff --git a/dist/node/esm/runtime/is_key_like.js b/dist/node/esm/runtime/is_key_like.js deleted file mode 100644 index af0d0a0725..0000000000 --- a/dist/node/esm/runtime/is_key_like.js +++ /dev/null @@ -1,8 +0,0 @@ -import webcrypto, { isCryptoKey } from './webcrypto.js'; -import isKeyObject from './is_key_object.js'; -export default (key) => isKeyObject(key) || isCryptoKey(key); -const types = ['KeyObject']; -if (globalThis.CryptoKey || (webcrypto === null || webcrypto === void 0 ? void 0 : webcrypto.CryptoKey)) { - types.push('CryptoKey'); -} -export { types }; diff --git a/dist/node/esm/runtime/is_key_object.js b/dist/node/esm/runtime/is_key_object.js deleted file mode 100644 index 3a28cd80eb..0000000000 --- a/dist/node/esm/runtime/is_key_object.js +++ /dev/null @@ -1,5 +0,0 @@ -import { KeyObject } from 'crypto'; -import * as util from 'util'; -export default util.types.isKeyObject - ? (obj) => util.types.isKeyObject(obj) - : (obj) => obj != null && obj instanceof KeyObject; diff --git a/dist/node/esm/runtime/jwk_to_key.js b/dist/node/esm/runtime/jwk_to_key.js deleted file mode 100644 index 8cb31d6bf9..0000000000 --- a/dist/node/esm/runtime/jwk_to_key.js +++ /dev/null @@ -1,116 +0,0 @@ -import { Buffer } from 'buffer'; -import { createPrivateKey, createPublicKey, createSecretKey } from 'crypto'; -import { decode as base64url } from './base64url.js'; -import { JOSENotSupported } from '../util/errors.js'; -import { setCurve } from './get_named_curve.js'; -import { setModulusLength } from './check_modulus_length.js'; -import Asn1SequenceEncoder from './asn1_sequence_encoder.js'; -import { jwkImport } from './flags.js'; -const parse = (jwk) => { - if (jwkImport && jwk.kty !== 'oct') { - return jwk.d - ? createPrivateKey({ format: 'jwk', key: jwk }) - : createPublicKey({ format: 'jwk', key: jwk }); - } - switch (jwk.kty) { - case 'oct': { - return createSecretKey(base64url(jwk.k)); - } - case 'RSA': { - const enc = new Asn1SequenceEncoder(); - const isPrivate = jwk.d !== undefined; - const modulus = Buffer.from(jwk.n, 'base64'); - const exponent = Buffer.from(jwk.e, 'base64'); - if (isPrivate) { - enc.zero(); - enc.unsignedInteger(modulus); - enc.unsignedInteger(exponent); - enc.unsignedInteger(Buffer.from(jwk.d, 'base64')); - enc.unsignedInteger(Buffer.from(jwk.p, 'base64')); - enc.unsignedInteger(Buffer.from(jwk.q, 'base64')); - enc.unsignedInteger(Buffer.from(jwk.dp, 'base64')); - enc.unsignedInteger(Buffer.from(jwk.dq, 'base64')); - enc.unsignedInteger(Buffer.from(jwk.qi, 'base64')); - } - else { - enc.unsignedInteger(modulus); - enc.unsignedInteger(exponent); - } - const der = enc.end(); - const createInput = { - key: der, - format: 'der', - type: 'pkcs1', - }; - const keyObject = isPrivate ? createPrivateKey(createInput) : createPublicKey(createInput); - setModulusLength(keyObject, modulus.length << 3); - return keyObject; - } - case 'EC': { - const enc = new Asn1SequenceEncoder(); - const isPrivate = jwk.d !== undefined; - const pub = Buffer.concat([ - Buffer.alloc(1, 4), - Buffer.from(jwk.x, 'base64'), - Buffer.from(jwk.y, 'base64'), - ]); - if (isPrivate) { - enc.zero(); - const enc$1 = new Asn1SequenceEncoder(); - enc$1.oidFor('ecPublicKey'); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - const enc$2 = new Asn1SequenceEncoder(); - enc$2.one(); - enc$2.octStr(Buffer.from(jwk.d, 'base64')); - const enc$3 = new Asn1SequenceEncoder(); - enc$3.bitStr(pub); - const f2 = enc$3.end(Buffer.from([0xa1])); - enc$2.add(f2); - const f = enc$2.end(); - const enc$4 = new Asn1SequenceEncoder(); - enc$4.add(f); - const f3 = enc$4.end(Buffer.from([0x04])); - enc.add(f3); - const der = enc.end(); - const keyObject = createPrivateKey({ key: der, format: 'der', type: 'pkcs8' }); - setCurve(keyObject, jwk.crv); - return keyObject; - } - const enc$1 = new Asn1SequenceEncoder(); - enc$1.oidFor('ecPublicKey'); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - enc.bitStr(pub); - const der = enc.end(); - const keyObject = createPublicKey({ key: der, format: 'der', type: 'spki' }); - setCurve(keyObject, jwk.crv); - return keyObject; - } - case 'OKP': { - const enc = new Asn1SequenceEncoder(); - const isPrivate = jwk.d !== undefined; - if (isPrivate) { - enc.zero(); - const enc$1 = new Asn1SequenceEncoder(); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - const enc$2 = new Asn1SequenceEncoder(); - enc$2.octStr(Buffer.from(jwk.d, 'base64')); - const f = enc$2.end(Buffer.from([0x04])); - enc.add(f); - const der = enc.end(); - return createPrivateKey({ key: der, format: 'der', type: 'pkcs8' }); - } - const enc$1 = new Asn1SequenceEncoder(); - enc$1.oidFor(jwk.crv); - enc.add(enc$1.end()); - enc.bitStr(Buffer.from(jwk.x, 'base64')); - const der = enc.end(); - return createPublicKey({ key: der, format: 'der', type: 'spki' }); - } - default: - throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); - } -}; -export default parse; diff --git a/dist/node/esm/runtime/key_to_jwk.js b/dist/node/esm/runtime/key_to_jwk.js deleted file mode 100644 index 755564cbb3..0000000000 --- a/dist/node/esm/runtime/key_to_jwk.js +++ /dev/null @@ -1,158 +0,0 @@ -import { KeyObject, createPublicKey } from 'crypto'; -import { encode as base64url } from './base64url.js'; -import Asn1SequenceDecoder from './asn1_sequence_decoder.js'; -import { JOSENotSupported } from '../util/errors.js'; -import getNamedCurve from './get_named_curve.js'; -import { isCryptoKey } from './webcrypto.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -import { jwkExport } from './flags.js'; -const keyToJWK = (key) => { - let keyObject; - if (isCryptoKey(key)) { - if (!key.extractable) { - throw new TypeError('CryptoKey is not extractable'); - } - keyObject = KeyObject.from(key); - } - else if (isKeyObject(key)) { - keyObject = key; - } - else if (key instanceof Uint8Array) { - return { - kty: 'oct', - k: base64url(key), - }; - } - else { - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); - } - if (jwkExport) { - if (keyObject.type !== 'secret' && - !['rsa', 'ec', 'ed25519', 'x25519', 'ed448', 'x448'].includes(keyObject.asymmetricKeyType)) { - throw new JOSENotSupported('Unsupported key asymmetricKeyType'); - } - return keyObject.export({ format: 'jwk' }); - } - switch (keyObject.type) { - case 'secret': - return { - kty: 'oct', - k: base64url(keyObject.export()), - }; - case 'private': - case 'public': { - switch (keyObject.asymmetricKeyType) { - case 'rsa': { - const der = keyObject.export({ format: 'der', type: 'pkcs1' }); - const dec = new Asn1SequenceDecoder(der); - if (keyObject.type === 'private') { - dec.unsignedInteger(); - } - const n = base64url(dec.unsignedInteger()); - const e = base64url(dec.unsignedInteger()); - let jwk; - if (keyObject.type === 'private') { - jwk = { - d: base64url(dec.unsignedInteger()), - p: base64url(dec.unsignedInteger()), - q: base64url(dec.unsignedInteger()), - dp: base64url(dec.unsignedInteger()), - dq: base64url(dec.unsignedInteger()), - qi: base64url(dec.unsignedInteger()), - }; - } - dec.end(); - return { kty: 'RSA', n, e, ...jwk }; - } - case 'ec': { - const crv = getNamedCurve(keyObject); - let len; - let offset; - let correction; - switch (crv) { - case 'secp256k1': - len = 64; - offset = 31 + 2; - correction = -1; - break; - case 'P-256': - len = 64; - offset = 34 + 2; - correction = -1; - break; - case 'P-384': - len = 96; - offset = 33 + 2; - correction = -3; - break; - case 'P-521': - len = 132; - offset = 33 + 2; - correction = -3; - break; - default: - throw new JOSENotSupported('Unsupported curve'); - } - if (keyObject.type === 'public') { - const der = keyObject.export({ type: 'spki', format: 'der' }); - return { - kty: 'EC', - crv, - x: base64url(der.subarray(-len, -len / 2)), - y: base64url(der.subarray(-len / 2)), - }; - } - const der = keyObject.export({ type: 'pkcs8', format: 'der' }); - if (der.length < 100) { - offset += correction; - } - return { - ...keyToJWK(createPublicKey(keyObject)), - d: base64url(der.subarray(offset, offset + len / 2)), - }; - } - case 'ed25519': - case 'x25519': { - const crv = getNamedCurve(keyObject); - if (keyObject.type === 'public') { - const der = keyObject.export({ type: 'spki', format: 'der' }); - return { - kty: 'OKP', - crv, - x: base64url(der.subarray(-32)), - }; - } - const der = keyObject.export({ type: 'pkcs8', format: 'der' }); - return { - ...keyToJWK(createPublicKey(keyObject)), - d: base64url(der.subarray(-32)), - }; - } - case 'ed448': - case 'x448': { - const crv = getNamedCurve(keyObject); - if (keyObject.type === 'public') { - const der = keyObject.export({ type: 'spki', format: 'der' }); - return { - kty: 'OKP', - crv, - x: base64url(der.subarray(crv === 'Ed448' ? -57 : -56)), - }; - } - const der = keyObject.export({ type: 'pkcs8', format: 'der' }); - return { - ...keyToJWK(createPublicKey(keyObject)), - d: base64url(der.subarray(crv === 'Ed448' ? -57 : -56)), - }; - } - default: - throw new JOSENotSupported('Unsupported key asymmetricKeyType'); - } - } - default: - throw new JOSENotSupported('Unsupported key type'); - } -}; -export default keyToJWK; diff --git a/dist/node/esm/runtime/node_key.js b/dist/node/esm/runtime/node_key.js deleted file mode 100644 index 3535dd8d67..0000000000 --- a/dist/node/esm/runtime/node_key.js +++ /dev/null @@ -1,75 +0,0 @@ -import { constants } from 'crypto'; -import getNamedCurve from './get_named_curve.js'; -import { JOSENotSupported } from '../util/errors.js'; -import checkModulusLength from './check_modulus_length.js'; -import { rsaPssParams } from './flags.js'; -const PSS = { - padding: constants.RSA_PKCS1_PSS_PADDING, - saltLength: constants.RSA_PSS_SALTLEN_DIGEST, -}; -const ecCurveAlgMap = new Map([ - ['ES256', 'P-256'], - ['ES256K', 'secp256k1'], - ['ES384', 'P-384'], - ['ES512', 'P-521'], -]); -export default function keyForCrypto(alg, key) { - switch (alg) { - case 'EdDSA': - if (!['ed25519', 'ed448'].includes(key.asymmetricKeyType)) { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ed25519 or ed448'); - } - return key; - case 'RS256': - case 'RS384': - case 'RS512': - if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); - } - checkModulusLength(key, alg); - return key; - case rsaPssParams && 'PS256': - case rsaPssParams && 'PS384': - case rsaPssParams && 'PS512': - if (key.asymmetricKeyType === 'rsa-pss') { - const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails; - const length = parseInt(alg.slice(-3), 10); - if (hashAlgorithm !== undefined && - (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm)) { - throw new TypeError(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${alg}`); - } - if (saltLength !== undefined && saltLength > length >> 3) { - throw new TypeError(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of "alg" ${alg}`); - } - } - else if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa or rsa-pss'); - } - checkModulusLength(key, alg); - return { key, ...PSS }; - case !rsaPssParams && 'PS256': - case !rsaPssParams && 'PS384': - case !rsaPssParams && 'PS512': - if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); - } - checkModulusLength(key, alg); - return { key, ...PSS }; - case 'ES256': - case 'ES256K': - case 'ES384': - case 'ES512': { - if (key.asymmetricKeyType !== 'ec') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ec'); - } - const actual = getNamedCurve(key); - const expected = ecCurveAlgMap.get(alg); - if (actual !== expected) { - throw new TypeError(`Invalid key curve for the algorithm, its curve must be ${expected}, got ${actual}`); - } - return { dsaEncoding: 'ieee-p1363', key }; - } - default: - throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); - } -} diff --git a/dist/node/esm/runtime/pbes2kw.js b/dist/node/esm/runtime/pbes2kw.js deleted file mode 100644 index 63122e04ef..0000000000 --- a/dist/node/esm/runtime/pbes2kw.js +++ /dev/null @@ -1,43 +0,0 @@ -import { promisify } from 'util'; -import { KeyObject, pbkdf2 as pbkdf2cb } from 'crypto'; -import random from './random.js'; -import { p2s as concatSalt } from '../lib/buffer_utils.js'; -import { encode as base64url } from './base64url.js'; -import { wrap, unwrap } from './aeskw.js'; -import checkP2s from '../lib/check_p2s.js'; -import { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -const pbkdf2 = promisify(pbkdf2cb); -function getPassword(key, alg) { - if (isKeyObject(key)) { - return key.export(); - } - if (key instanceof Uint8Array) { - return key; - } - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey'); - return KeyObject.from(key).export(); - } - throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); -} -export const encrypt = async (alg, key, cek, p2c = 2048, p2s = random(new Uint8Array(16))) => { - checkP2s(p2s); - const salt = concatSalt(alg, p2s); - const keylen = parseInt(alg.slice(13, 16), 10) >> 3; - const password = getPassword(key, alg); - const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); - const encryptedKey = await wrap(alg.slice(-6), derivedKey, cek); - return { encryptedKey, p2c, p2s: base64url(p2s) }; -}; -export const decrypt = async (alg, key, encryptedKey, p2c, p2s) => { - checkP2s(p2s); - const salt = concatSalt(alg, p2s); - const keylen = parseInt(alg.slice(13, 16), 10) >> 3; - const password = getPassword(key, alg); - const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); - return unwrap(alg.slice(-6), derivedKey, encryptedKey); -}; diff --git a/dist/node/esm/runtime/random.js b/dist/node/esm/runtime/random.js deleted file mode 100644 index 80478ea946..0000000000 --- a/dist/node/esm/runtime/random.js +++ /dev/null @@ -1 +0,0 @@ -export { randomFillSync as default } from 'crypto'; diff --git a/dist/node/esm/runtime/rsaes.js b/dist/node/esm/runtime/rsaes.js deleted file mode 100644 index 3556fe3436..0000000000 --- a/dist/node/esm/runtime/rsaes.js +++ /dev/null @@ -1,64 +0,0 @@ -import { KeyObject, publicEncrypt, constants, privateDecrypt } from 'crypto'; -import checkModulusLength from './check_modulus_length.js'; -import { isCryptoKey } from './webcrypto.js'; -import { checkEncCryptoKey } from '../lib/crypto_key.js'; -import isKeyObject from './is_key_object.js'; -import invalidKeyInput from '../lib/invalid_key_input.js'; -import { types } from './is_key_like.js'; -const checkKey = (key, alg) => { - if (key.asymmetricKeyType !== 'rsa') { - throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); - } - checkModulusLength(key, alg); -}; -const resolvePadding = (alg) => { - switch (alg) { - case 'RSA-OAEP': - case 'RSA-OAEP-256': - case 'RSA-OAEP-384': - case 'RSA-OAEP-512': - return constants.RSA_PKCS1_OAEP_PADDING; - case 'RSA1_5': - return constants.RSA_PKCS1_PADDING; - default: - return undefined; - } -}; -const resolveOaepHash = (alg) => { - switch (alg) { - case 'RSA-OAEP': - return 'sha1'; - case 'RSA-OAEP-256': - return 'sha256'; - case 'RSA-OAEP-384': - return 'sha384'; - case 'RSA-OAEP-512': - return 'sha512'; - default: - return undefined; - } -}; -function ensureKeyObject(key, alg, ...usages) { - if (isKeyObject(key)) { - return key; - } - if (isCryptoKey(key)) { - checkEncCryptoKey(key, alg, ...usages); - return KeyObject.from(key); - } - throw new TypeError(invalidKeyInput(key, ...types)); -} -export const encrypt = (alg, key, cek) => { - const padding = resolvePadding(alg); - const oaepHash = resolveOaepHash(alg); - const keyObject = ensureKeyObject(key, alg, 'wrapKey', 'encrypt'); - checkKey(keyObject, alg); - return publicEncrypt({ key: keyObject, oaepHash, padding }, cek); -}; -export const decrypt = (alg, key, encryptedKey) => { - const padding = resolvePadding(alg); - const oaepHash = resolveOaepHash(alg); - const keyObject = ensureKeyObject(key, alg, 'unwrapKey', 'decrypt'); - checkKey(keyObject, alg); - return privateDecrypt({ key: keyObject, oaepHash, padding }, encryptedKey); -}; diff --git a/dist/node/esm/runtime/sign.js b/dist/node/esm/runtime/sign.js deleted file mode 100644 index 8902d4151c..0000000000 --- a/dist/node/esm/runtime/sign.js +++ /dev/null @@ -1,23 +0,0 @@ -import * as crypto from 'crypto'; -import { promisify } from 'util'; -import nodeDigest from './dsa_digest.js'; -import hmacDigest from './hmac_digest.js'; -import nodeKey from './node_key.js'; -import getSignKey from './get_sign_verify_key.js'; -let oneShotSign; -if (crypto.sign.length > 3) { - oneShotSign = promisify(crypto.sign); -} -else { - oneShotSign = crypto.sign; -} -const sign = async (alg, key, data) => { - const keyObject = getSignKey(alg, key, 'sign'); - if (alg.startsWith('HS')) { - const hmac = crypto.createHmac(hmacDigest(alg), keyObject); - hmac.update(data); - return hmac.digest(); - } - return oneShotSign(nodeDigest(alg), data, nodeKey(alg, keyObject)); -}; -export default sign; diff --git a/dist/node/esm/runtime/timing_safe_equal.js b/dist/node/esm/runtime/timing_safe_equal.js deleted file mode 100644 index 901ae38bdd..0000000000 --- a/dist/node/esm/runtime/timing_safe_equal.js +++ /dev/null @@ -1,3 +0,0 @@ -import { timingSafeEqual as impl } from 'crypto'; -const timingSafeEqual = impl; -export default timingSafeEqual; diff --git a/dist/node/esm/runtime/verify.js b/dist/node/esm/runtime/verify.js deleted file mode 100644 index e514e1c452..0000000000 --- a/dist/node/esm/runtime/verify.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as crypto from 'crypto'; -import { promisify } from 'util'; -import nodeDigest from './dsa_digest.js'; -import nodeKey from './node_key.js'; -import sign from './sign.js'; -import getVerifyKey from './get_sign_verify_key.js'; -import { oneShotCallback } from './flags.js'; -let oneShotVerify; -if (crypto.verify.length > 4 && oneShotCallback) { - oneShotVerify = promisify(crypto.verify); -} -else { - oneShotVerify = crypto.verify; -} -const verify = async (alg, key, signature, data) => { - const keyObject = getVerifyKey(alg, key, 'verify'); - if (alg.startsWith('HS')) { - const expected = await sign(alg, keyObject, data); - const actual = signature; - try { - return crypto.timingSafeEqual(actual, expected); - } - catch { - return false; - } - } - const algorithm = nodeDigest(alg); - const keyInput = nodeKey(alg, keyObject); - try { - return await oneShotVerify(algorithm, data, keyInput, signature); - } - catch { - return false; - } -}; -export default verify; diff --git a/dist/node/esm/runtime/webcrypto.js b/dist/node/esm/runtime/webcrypto.js deleted file mode 100644 index a2fdb2a7a1..0000000000 --- a/dist/node/esm/runtime/webcrypto.js +++ /dev/null @@ -1,8 +0,0 @@ -import * as crypto from 'crypto'; -import * as util from 'util'; -const webcrypto = crypto.webcrypto; -export default webcrypto; -export const isCryptoKey = util.types.isCryptoKey - ? (key) => util.types.isCryptoKey(key) - : - (key) => false; diff --git a/dist/node/esm/runtime/zlib.js b/dist/node/esm/runtime/zlib.js deleted file mode 100644 index 8bb72cbf18..0000000000 --- a/dist/node/esm/runtime/zlib.js +++ /dev/null @@ -1,6 +0,0 @@ -import { promisify } from 'util'; -import { inflateRaw as inflateRawCb, deflateRaw as deflateRawCb } from 'zlib'; -const inflateRaw = promisify(inflateRawCb); -const deflateRaw = promisify(deflateRawCb); -export const inflate = (input) => inflateRaw(input); -export const deflate = (input) => deflateRaw(input); diff --git a/dist/node/esm/util/base64url.js b/dist/node/esm/util/base64url.js deleted file mode 100644 index 88ce7556d6..0000000000 --- a/dist/node/esm/util/base64url.js +++ /dev/null @@ -1,3 +0,0 @@ -import * as base64url from '../runtime/base64url.js'; -export const encode = base64url.encode; -export const decode = base64url.decode; diff --git a/dist/node/esm/util/decode_jwt.js b/dist/node/esm/util/decode_jwt.js deleted file mode 100644 index 0b824ed580..0000000000 --- a/dist/node/esm/util/decode_jwt.js +++ /dev/null @@ -1,32 +0,0 @@ -import { decode as base64url } from './base64url.js'; -import { decoder } from '../lib/buffer_utils.js'; -import isObject from '../lib/is_object.js'; -import { JWTInvalid } from './errors.js'; -export function decodeJwt(jwt) { - if (typeof jwt !== 'string') - throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string'); - const { 1: payload, length } = jwt.split('.'); - if (length === 5) - throw new JWTInvalid('Only JWTs using Compact JWS serialization can be decoded'); - if (length !== 3) - throw new JWTInvalid('Invalid JWT'); - if (!payload) - throw new JWTInvalid('JWTs must contain a payload'); - let decoded; - try { - decoded = base64url(payload); - } - catch { - throw new JWTInvalid('Failed to parse the base64url encoded payload'); - } - let result; - try { - result = JSON.parse(decoder.decode(decoded)); - } - catch { - throw new JWTInvalid('Failed to parse the decoded payload as JSON'); - } - if (!isObject(result)) - throw new JWTInvalid('Invalid JWT Claims Set'); - return result; -} diff --git a/dist/node/esm/util/decode_protected_header.js b/dist/node/esm/util/decode_protected_header.js deleted file mode 100644 index 04be31d8f2..0000000000 --- a/dist/node/esm/util/decode_protected_header.js +++ /dev/null @@ -1,34 +0,0 @@ -import { decode as base64url } from './base64url.js'; -import { decoder } from '../lib/buffer_utils.js'; -import isObject from '../lib/is_object.js'; -export function decodeProtectedHeader(token) { - let protectedB64u; - if (typeof token === 'string') { - const parts = token.split('.'); - if (parts.length === 3 || parts.length === 5) { - ; - [protectedB64u] = parts; - } - } - else if (typeof token === 'object' && token) { - if ('protected' in token) { - protectedB64u = token.protected; - } - else { - throw new TypeError('Token does not contain a Protected Header'); - } - } - try { - if (typeof protectedB64u !== 'string' || !protectedB64u) { - throw new Error(); - } - const result = JSON.parse(decoder.decode(base64url(protectedB64u))); - if (!isObject(result)) { - throw new Error(); - } - return result; - } - catch { - throw new TypeError('Invalid Token or Protected Header formatting'); - } -} diff --git a/dist/node/esm/util/errors.js b/dist/node/esm/util/errors.js deleted file mode 100644 index 13a36f58fa..0000000000 --- a/dist/node/esm/util/errors.js +++ /dev/null @@ -1,148 +0,0 @@ -export class JOSEError extends Error { - static get code() { - return 'ERR_JOSE_GENERIC'; - } - constructor(message) { - var _a; - super(message); - this.code = 'ERR_JOSE_GENERIC'; - this.name = this.constructor.name; - (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); - } -} -export class JWTClaimValidationFailed extends JOSEError { - static get code() { - return 'ERR_JWT_CLAIM_VALIDATION_FAILED'; - } - constructor(message, claim = 'unspecified', reason = 'unspecified') { - super(message); - this.code = 'ERR_JWT_CLAIM_VALIDATION_FAILED'; - this.claim = claim; - this.reason = reason; - } -} -export class JWTExpired extends JOSEError { - static get code() { - return 'ERR_JWT_EXPIRED'; - } - constructor(message, claim = 'unspecified', reason = 'unspecified') { - super(message); - this.code = 'ERR_JWT_EXPIRED'; - this.claim = claim; - this.reason = reason; - } -} -export class JOSEAlgNotAllowed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JOSE_ALG_NOT_ALLOWED'; - } - static get code() { - return 'ERR_JOSE_ALG_NOT_ALLOWED'; - } -} -export class JOSENotSupported extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JOSE_NOT_SUPPORTED'; - } - static get code() { - return 'ERR_JOSE_NOT_SUPPORTED'; - } -} -export class JWEDecryptionFailed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWE_DECRYPTION_FAILED'; - this.message = 'decryption operation failed'; - } - static get code() { - return 'ERR_JWE_DECRYPTION_FAILED'; - } -} -export class JWEInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWE_INVALID'; - } - static get code() { - return 'ERR_JWE_INVALID'; - } -} -export class JWSInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWS_INVALID'; - } - static get code() { - return 'ERR_JWS_INVALID'; - } -} -export class JWTInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWT_INVALID'; - } - static get code() { - return 'ERR_JWT_INVALID'; - } -} -export class JWKInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWK_INVALID'; - } - static get code() { - return 'ERR_JWK_INVALID'; - } -} -export class JWKSInvalid extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_INVALID'; - } - static get code() { - return 'ERR_JWKS_INVALID'; - } -} -export class JWKSNoMatchingKey extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_NO_MATCHING_KEY'; - this.message = 'no applicable key found in the JSON Web Key Set'; - } - static get code() { - return 'ERR_JWKS_NO_MATCHING_KEY'; - } -} -export class JWKSMultipleMatchingKeys extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; - this.message = 'multiple matching keys found in the JSON Web Key Set'; - } - static get code() { - return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; - } -} -Symbol.asyncIterator; -export class JWKSTimeout extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWKS_TIMEOUT'; - this.message = 'request timed out'; - } - static get code() { - return 'ERR_JWKS_TIMEOUT'; - } -} -export class JWSSignatureVerificationFailed extends JOSEError { - constructor() { - super(...arguments); - this.code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; - this.message = 'signature verification failed'; - } - static get code() { - return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; - } -} diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts deleted file mode 100644 index 6ce928e73a..0000000000 --- a/dist/types/index.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -export { compactDecrypt } from './jwe/compact/decrypt'; -export type { CompactDecryptGetKey } from './jwe/compact/decrypt'; -export { flattenedDecrypt } from './jwe/flattened/decrypt'; -export type { FlattenedDecryptGetKey } from './jwe/flattened/decrypt'; -export { generalDecrypt } from './jwe/general/decrypt'; -export type { GeneralDecryptGetKey } from './jwe/general/decrypt'; -export { GeneralEncrypt } from './jwe/general/encrypt'; -export type { Recipient } from './jwe/general/encrypt'; -export { compactVerify } from './jws/compact/verify'; -export type { CompactVerifyGetKey } from './jws/compact/verify'; -export { flattenedVerify } from './jws/flattened/verify'; -export type { FlattenedVerifyGetKey } from './jws/flattened/verify'; -export { generalVerify } from './jws/general/verify'; -export type { GeneralVerifyGetKey } from './jws/general/verify'; -export { jwtVerify } from './jwt/verify'; -export type { JWTVerifyOptions, JWTVerifyGetKey } from './jwt/verify'; -export { jwtDecrypt } from './jwt/decrypt'; -export type { JWTDecryptOptions, JWTDecryptGetKey } from './jwt/decrypt'; -export type { ProduceJWT } from './jwt/produce'; -export { CompactEncrypt } from './jwe/compact/encrypt'; -export { FlattenedEncrypt } from './jwe/flattened/encrypt'; -export { CompactSign } from './jws/compact/sign'; -export { FlattenedSign } from './jws/flattened/sign'; -export { GeneralSign } from './jws/general/sign'; -export type { Signature } from './jws/general/sign'; -export { SignJWT } from './jwt/sign'; -export { EncryptJWT } from './jwt/encrypt'; -export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint'; -export { EmbeddedJWK } from './jwk/embedded'; -export { createLocalJWKSet } from './jwks/local'; -export { createRemoteJWKSet } from './jwks/remote'; -export type { RemoteJWKSetOptions } from './jwks/remote'; -export { UnsecuredJWT } from './jwt/unsecured'; -export type { UnsecuredResult } from './jwt/unsecured'; -export { exportPKCS8, exportSPKI, exportJWK } from './key/export'; -export { importSPKI, importPKCS8, importX509, importJWK } from './key/import'; -export type { PEMImportOptions } from './key/import'; -export { decodeProtectedHeader } from './util/decode_protected_header'; -export { decodeJwt } from './util/decode_jwt'; -export type { ProtectedHeaderParameters } from './util/decode_protected_header'; -export * as errors from './util/errors'; -export { generateKeyPair } from './key/generate_key_pair'; -export type { GenerateKeyPairResult, GenerateKeyPairOptions } from './key/generate_key_pair'; -export { generateSecret } from './key/generate_secret'; -export type { GenerateSecretOptions } from './key/generate_secret'; -export * as base64url from './util/base64url'; -export type { KeyLike, JWK, FlattenedJWSInput, GeneralJWSInput, FlattenedJWS, GeneralJWS, JoseHeaderParameters, JWSHeaderParameters, JWEKeyManagementHeaderParameters, FlattenedJWE, GeneralJWE, JWEHeaderParameters, CritOption, DeflateOption, DecryptOptions, EncryptOptions, JWTClaimVerificationOptions, VerifyOptions, SignOptions, JWTPayload, DeflateFunction, InflateFunction, FlattenedDecryptResult, GeneralDecryptResult, CompactDecryptResult, FlattenedVerifyResult, GeneralVerifyResult, CompactVerifyResult, JWTVerifyResult, JWTDecryptResult, ResolvedKey, CompactJWEHeaderParameters, CompactJWSHeaderParameters, JWTHeaderParameters, JSONWebKeySet, } from './types'; diff --git a/dist/types/jwe/compact/decrypt.d.ts b/dist/types/jwe/compact/decrypt.d.ts deleted file mode 100644 index 0a37a97656..0000000000 --- a/dist/types/jwe/compact/decrypt.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { KeyLike, DecryptOptions, CompactJWEHeaderParameters, GetKeyFunction, FlattenedJWE, CompactDecryptResult, ResolvedKey } from '../../types'; -/** - * Interface for Compact JWE Decryption dynamic key resolution. No token components have been - * verified at the time of this function call. - */ -export interface CompactDecryptGetKey extends GetKeyFunction { -} -/** - * Decrypts a Compact JWE. - * - * @example Usage - * - * ```js - * const jwe = - * 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.nyQ19eq9ogh9wA7fFtnI2oouzy5_8b5DeLkoRMfi2yijgfTs2zEnayCEofz_qhnL-nwszabd9qUeHv0-IwvhhJJS7GUJOU3ikiIe42qcIAFme1A_Fo9CTxw4XTOy-I5qanl8So91u6hwfyN1VxAqVLsSE7_23EC-gfGEg_5znew9PyXXsOIE-K_HH7IQowRrlZ1X_bM_Liu53RzDpLDvRz59mp3S8L56YqpM8FexFGTGpEaoTcEIst375qncYt3-79IVR7gZN1RWsWgjPatfvVbnh74PglQcATSf3UUhaW0OAKn6q7r3PDx6DIKQ35bgHQg5QopuN00eIfLQL2trGw.W3grIVj5HVuAb76X.6PcuDe5D6ttWFYyv0oqqdDXfI2R8wBg1F2Q80UUA_Gv8eEimNWfxIWdLxrjzgQGSvIhxmFKuLM0.a93_Ug3uZHuczj70Zavx8Q' - * - * const { plaintext, protectedHeader } = await jose.compactDecrypt(jwe, privateKey) - * - * console.log(protectedHeader) - * console.log(new TextDecoder().decode(plaintext)) - * ``` - * - * @param jwe Compact JWE. - * @param key Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export declare function compactDecrypt(jwe: string | Uint8Array, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise; -/** - * @param jwe Compact JWE. - * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export declare function compactDecrypt(jwe: string | Uint8Array, getKey: CompactDecryptGetKey, options?: DecryptOptions): Promise; diff --git a/dist/types/jwe/compact/encrypt.d.ts b/dist/types/jwe/compact/encrypt.d.ts deleted file mode 100644 index 0f48815a78..0000000000 --- a/dist/types/jwe/compact/encrypt.d.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { KeyLike, JWEKeyManagementHeaderParameters, CompactJWEHeaderParameters, EncryptOptions } from '../../types'; -/** - * The CompactEncrypt class is a utility for creating Compact JWE strings. - * - * @example Usage - * - * ```js - * const jwe = await new jose.CompactEncrypt( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) - * .encrypt(publicKey) - * - * console.log(jwe) - * ``` - */ -export declare class CompactEncrypt { - private _flattened; - /** @param plaintext Binary representation of the plaintext to encrypt. */ - constructor(plaintext: Uint8Array); - /** - * Sets a content encryption key to use, by default a random suitable one is generated for the JWE - * enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param cek JWE Content Encryption Key. - */ - setContentEncryptionKey(cek: Uint8Array): this; - /** - * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable - * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param iv JWE Initialization Vector. - */ - setInitializationVector(iv: Uint8Array): this; - /** - * Sets the JWE Protected Header on the CompactEncrypt object. - * - * @param protectedHeader JWE Protected Header object. - */ - setProtectedHeader(protectedHeader: CompactJWEHeaderParameters): this; - /** - * Sets the JWE Key Management parameters to be used when encrypting the Content Encryption Key. - * You do not need to invoke this method, it is only really intended for test and vector - * validation purposes. - * - * @param parameters JWE Key Management parameters. - */ - setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this; - /** - * Encrypts and resolves the value of the Compact JWE string. - * - * @param key Public Key or Secret to encrypt the JWE with. - * @param options JWE Encryption options. - */ - encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise; -} diff --git a/dist/types/jwe/flattened/decrypt.d.ts b/dist/types/jwe/flattened/decrypt.d.ts deleted file mode 100644 index 016ca62bbc..0000000000 --- a/dist/types/jwe/flattened/decrypt.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { FlattenedDecryptResult, KeyLike, FlattenedJWE, JWEHeaderParameters, DecryptOptions, GetKeyFunction, ResolvedKey } from '../../types'; -/** - * Interface for Flattened JWE Decryption dynamic key resolution. No token components have been - * verified at the time of this function call. - */ -export interface FlattenedDecryptGetKey extends GetKeyFunction { -} -/** - * Decrypts a Flattened JWE. - * - * @example Usage - * - * ```js - * const jwe = { - * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', - * iv: '8Fy7A_IuoX5VXG9s', - * tag: 'W76IYV6arGRuDSaSyWrQNg', - * encrypted_key: - * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', - * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', - * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', - * } - * - * const { plaintext, protectedHeader, additionalAuthenticatedData } = - * await jose.flattenedDecrypt(jwe, privateKey) - * - * console.log(protectedHeader) - * const decoder = new TextDecoder() - * console.log(decoder.decode(plaintext)) - * console.log(decoder.decode(additionalAuthenticatedData)) - * ``` - * - * @param jwe Flattened JWE. - * @param key Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export declare function flattenedDecrypt(jwe: FlattenedJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise; -/** - * @param jwe Flattened JWE. - * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export declare function flattenedDecrypt(jwe: FlattenedJWE, getKey: FlattenedDecryptGetKey, options?: DecryptOptions): Promise; diff --git a/dist/types/jwe/flattened/encrypt.d.ts b/dist/types/jwe/flattened/encrypt.d.ts deleted file mode 100644 index d5d02fdfbb..0000000000 --- a/dist/types/jwe/flattened/encrypt.d.ts +++ /dev/null @@ -1,89 +0,0 @@ -import type { KeyLike, FlattenedJWE, JWEHeaderParameters, JWEKeyManagementHeaderParameters, EncryptOptions } from '../../types'; -/** @private */ -export declare const unprotected: unique symbol; -/** - * The FlattenedEncrypt class is a utility for creating Flattened JWE objects. - * - * @example Usage - * - * ```js - * const jwe = await new jose.FlattenedEncrypt( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) - * .setAdditionalAuthenticatedData(encoder.encode('The Fellowship of the Ring')) - * .encrypt(publicKey) - * - * console.log(jwe) - * ``` - */ -export declare class FlattenedEncrypt { - private _plaintext; - private _protectedHeader; - private _sharedUnprotectedHeader; - private _unprotectedHeader; - private _aad; - private _cek; - private _iv; - private _keyManagementParameters; - /** @param plaintext Binary representation of the plaintext to encrypt. */ - constructor(plaintext: Uint8Array); - /** - * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is - * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or - * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed - * and missing. - * - * @param parameters JWE Key Management parameters. - */ - setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this; - /** - * Sets the JWE Protected Header on the FlattenedEncrypt object. - * - * @param protectedHeader JWE Protected Header. - */ - setProtectedHeader(protectedHeader: JWEHeaderParameters): this; - /** - * Sets the JWE Shared Unprotected Header on the FlattenedEncrypt object. - * - * @param sharedUnprotectedHeader JWE Shared Unprotected Header. - */ - setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters): this; - /** - * Sets the JWE Per-Recipient Unprotected Header on the FlattenedEncrypt object. - * - * @param unprotectedHeader JWE Per-Recipient Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters): this; - /** - * Sets the Additional Authenticated Data on the FlattenedEncrypt object. - * - * @param aad Additional Authenticated Data. - */ - setAdditionalAuthenticatedData(aad: Uint8Array): this; - /** - * Sets a content encryption key to use, by default a random suitable one is generated for the JWE - * enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param cek JWE Content Encryption Key. - */ - setContentEncryptionKey(cek: Uint8Array): this; - /** - * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable - * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param iv JWE Initialization Vector. - */ - setInitializationVector(iv: Uint8Array): this; - /** - * Encrypts and resolves the value of the Flattened JWE object. - * - * @param key Public Key or Secret to encrypt the JWE with. - * @param options JWE Encryption options. - */ - encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise; -} diff --git a/dist/types/jwe/general/decrypt.d.ts b/dist/types/jwe/general/decrypt.d.ts deleted file mode 100644 index d6efd0ff51..0000000000 --- a/dist/types/jwe/general/decrypt.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { KeyLike, DecryptOptions, JWEHeaderParameters, GetKeyFunction, FlattenedJWE, GeneralJWE, GeneralDecryptResult, ResolvedKey } from '../../types'; -/** - * Interface for General JWE Decryption dynamic key resolution. No token components have been - * verified at the time of this function call. - */ -export interface GeneralDecryptGetKey extends GetKeyFunction { -} -/** - * Decrypts a General JWE. - * - * @example Usage - * - * ```js - * const jwe = { - * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', - * iv: '8Fy7A_IuoX5VXG9s', - * tag: 'W76IYV6arGRuDSaSyWrQNg', - * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', - * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', - * recipients: [ - * { - * encrypted_key: - * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', - * }, - * ], - * } - * - * const { plaintext, protectedHeader, additionalAuthenticatedData } = - * await jose.generalDecrypt(jwe, privateKey) - * - * console.log(protectedHeader) - * const decoder = new TextDecoder() - * console.log(decoder.decode(plaintext)) - * console.log(decoder.decode(additionalAuthenticatedData)) - * ``` - * - * @param jwe General JWE. - * @param key Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export declare function generalDecrypt(jwe: GeneralJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise; -/** - * @param jwe General JWE. - * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. - * @param options JWE Decryption options. - */ -export declare function generalDecrypt(jwe: GeneralJWE, getKey: GeneralDecryptGetKey, options?: DecryptOptions): Promise; diff --git a/dist/types/jwe/general/encrypt.d.ts b/dist/types/jwe/general/encrypt.d.ts deleted file mode 100644 index 70dee92e94..0000000000 --- a/dist/types/jwe/general/encrypt.d.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { KeyLike, GeneralJWE, JWEHeaderParameters, CritOption, DeflateOption } from '../../types'; -export interface Recipient { - /** - * Sets the JWE Per-Recipient Unprotected Header on the Recipient object. - * - * @param unprotectedHeader JWE Per-Recipient Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters): Recipient; - /** A shorthand for calling addRecipient() on the enclosing GeneralEncrypt instance */ - addRecipient(...args: Parameters): Recipient; - /** A shorthand for calling encrypt() on the enclosing GeneralEncrypt instance */ - encrypt(...args: Parameters): Promise; - /** Returns the enclosing GeneralEncrypt */ - done(): GeneralEncrypt; -} -/** - * The GeneralEncrypt class is a utility for creating General JWE objects. - * - * @example Usage - * - * ```js - * const jwe = await new jose.GeneralEncrypt( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ enc: 'A256GCM' }) - * .addRecipient(ecPublicKey) - * .setUnprotectedHeader({ alg: 'ECDH-ES+A256KW' }) - * .addRecipient(rsaPublicKey) - * .setUnprotectedHeader({ alg: 'RSA-OAEP-384' }) - * .encrypt() - * - * console.log(jwe) - * ``` - */ -export declare class GeneralEncrypt { - private _plaintext; - private _recipients; - private _protectedHeader; - private _unprotectedHeader; - private _aad; - /** @param plaintext Binary representation of the plaintext to encrypt. */ - constructor(plaintext: Uint8Array); - /** - * Adds an additional recipient for the General JWE object. - * - * @param key Public Key or Secret to encrypt the Content Encryption Key for the recipient with. - * @param options JWE Encryption options. - */ - addRecipient(key: KeyLike | Uint8Array, options?: CritOption): Recipient; - /** - * Sets the JWE Protected Header on the GeneralEncrypt object. - * - * @param protectedHeader JWE Protected Header object. - */ - setProtectedHeader(protectedHeader: JWEHeaderParameters): this; - /** - * Sets the JWE Shared Unprotected Header on the GeneralEncrypt object. - * - * @param sharedUnprotectedHeader JWE Shared Unprotected Header object. - */ - setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters): this; - /** - * Sets the Additional Authenticated Data on the GeneralEncrypt object. - * - * @param aad Additional Authenticated Data. - */ - setAdditionalAuthenticatedData(aad: Uint8Array): this; - /** - * Encrypts and resolves the value of the General JWE object. - * - * @param options JWE Encryption options. - */ - encrypt(options?: DeflateOption): Promise; -} diff --git a/dist/types/jwk/embedded.d.ts b/dist/types/jwk/embedded.d.ts deleted file mode 100644 index 6f6e160729..0000000000 --- a/dist/types/jwk/embedded.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { FlattenedJWSInput, JWSHeaderParameters } from '../types'; -/** - * EmbeddedJWK is an implementation of a GetKeyFunction intended to be used with the JWS/JWT verify - * operations whenever you need to opt-in to verify signatures with a public key embedded in the - * token's "jwk" (JSON Web Key) Header Parameter. It is recommended to combine this with the verify - * function's `algorithms` option to define accepted JWS "alg" (Algorithm) Header Parameter values. - * - * @example Usage - * - * ```js - * const jwt = - * 'eyJqd2siOnsiY3J2IjoiUC0yNTYiLCJ4IjoiVU05ZzVuS25aWFlvdldBbE03NmNMejl2VG96UmpfX0NIVV9kT2wtZ09vRSIsInkiOiJkczhhZVF3MWwyY0RDQTdiQ2tPTnZ3REtwWEFidFhqdnFDbGVZSDhXc19VIiwia3R5IjoiRUMifSwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSIsImlhdCI6MTYwNDU4MDc5NH0.60boak3_dErnW47ZPty1C0nrjeVq86EN_eK0GOq6K8w2OA0thKoBxFK4j-NuU9yZ_A9UKGxPT_G87DladBaV9g' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, jose.EmbeddedJWK, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - */ -export declare function EmbeddedJWK(protectedHeader: JWSHeaderParameters, token: FlattenedJWSInput): Promise; diff --git a/dist/types/jwk/thumbprint.d.ts b/dist/types/jwk/thumbprint.d.ts deleted file mode 100644 index 5122dcc3db..0000000000 --- a/dist/types/jwk/thumbprint.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { JWK } from '../types'; -/** - * Calculates a base64url-encoded JSON Web Key (JWK) Thumbprint - * - * @example Usage - * - * ```js - * const thumbprint = await jose.calculateJwkThumbprint({ - * kty: 'EC', - * crv: 'P-256', - * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', - * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', - * }) - * - * console.log(thumbprint) - * // 'w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' - * ``` - * - * @param jwk JSON Web Key. - * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is - * "sha256". - * @see [RFC7638](https://www.rfc-editor.org/rfc/rfc7638) - */ -export declare function calculateJwkThumbprint(jwk: JWK, digestAlgorithm?: 'sha256' | 'sha384' | 'sha512'): Promise; -/** - * Calculates a JSON Web Key (JWK) Thumbprint URI - * - * @example Usage - * - * ```js - * const thumbprintUri = await jose.calculateJwkThumbprintUri({ - * kty: 'EC', - * crv: 'P-256', - * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', - * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', - * }) - * - * console.log(thumbprint) - * // 'urn:ietf:params:oauth:jwk-thumbprint:sha-256:w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' - * ``` - * - * @param jwk JSON Web Key. - * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is - * "sha256". - * @see [RFC9278](https://www.rfc-editor.org/rfc/rfc9278) - */ -export declare function calculateJwkThumbprintUri(jwk: JWK, digestAlgorithm?: 'sha256' | 'sha384' | 'sha512'): Promise; diff --git a/dist/types/jwks/local.d.ts b/dist/types/jwks/local.d.ts deleted file mode 100644 index 79c722c2dd..0000000000 --- a/dist/types/jwks/local.d.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { KeyLike, JWSHeaderParameters, JSONWebKeySet, FlattenedJWSInput } from '../types'; -/** @private */ -export declare function isJWKSLike(jwks: unknown): jwks is JSONWebKeySet; -/** @private */ -export declare class LocalJWKSet { - protected _jwks?: JSONWebKeySet; - private _cached; - constructor(jwks: unknown); - getKey(protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise; -} -/** - * Returns a function that resolves to a key object from a locally stored, or otherwise available, - * JSON Web Key Set. - * - * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), - * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if - * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key - * Operations) Parameters (if they are present on the JWK). - * - * Only a single public key must match the selection process. As shown in the example below when - * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt - * verification in an iterative manner. - * - * @example Usage - * - * ```js - * const JWKS = jose.createLocalJWKSet({ - * keys: [ - * { - * kty: 'RSA', - * e: 'AQAB', - * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', - * alg: 'PS256', - * }, - * { - * crv: 'P-256', - * kty: 'EC', - * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', - * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', - * alg: 'ES256', - * }, - * ], - * }) - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Opting-in to multiple JWKS matches using `createLocalJWKSet` - * - * ```js - * const options = { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * } - * const { payload, protectedHeader } = await jose - * .jwtVerify(jwt, JWKS, options) - * .catch(async (error) => { - * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { - * for await (const publicKey of error) { - * try { - * return await jose.jwtVerify(jwt, publicKey, options) - * } catch (innerError) { - * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { - * continue - * } - * throw innerError - * } - * } - * throw new jose.errors.JWSSignatureVerificationFailed() - * } - * - * throw error - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwks JSON Web Key Set formatted object. - */ -export declare function createLocalJWKSet(jwks: JSONWebKeySet): (protectedHeader?: JWSHeaderParameters | undefined, token?: FlattenedJWSInput | undefined) => Promise; diff --git a/dist/types/jwks/remote.d.ts b/dist/types/jwks/remote.d.ts deleted file mode 100644 index a948dd9f91..0000000000 --- a/dist/types/jwks/remote.d.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { KeyLike, JWSHeaderParameters, FlattenedJWSInput } from '../types'; -/** Options for the remote JSON Web Key Set. */ -export interface RemoteJWKSetOptions { - /** - * Timeout (in milliseconds) for the HTTP request. When reached the request will be aborted and - * the verification will fail. Default is 5000 (5 seconds). - */ - timeoutDuration?: number; - /** - * Duration (in milliseconds) for which no more HTTP requests will be triggered after a previous - * successful fetch. Default is 30000 (30 seconds). - */ - cooldownDuration?: number; - /** - * Maximum time (in milliseconds) between successful HTTP requests. Default is 600000 (10 - * minutes). - */ - cacheMaxAge?: number | typeof Infinity; - /** - * An instance of [http.Agent](https://nodejs.org/api/http.html#class-httpagent) or - * [https.Agent](https://nodejs.org/api/https.html#class-httpsagent) to pass to the - * [http.get](https://nodejs.org/api/http.html#httpgetoptions-callback) or - * [https.get](https://nodejs.org/api/https.html#httpsgetoptions-callback) method's options. Use - * when behind an http(s) proxy. This is a Node.js runtime specific option, it is ignored when - * used outside of Node.js runtime. - */ - agent?: any; - /** Optional headers to be sent with the HTTP request. */ - headers?: Record; -} -/** - * Returns a function that resolves to a key object downloaded from a remote endpoint returning a - * JSON Web Key Set, that is, for example, an OAuth 2.0 or OIDC jwks_uri. The JSON Web Key Set is - * fetched when no key matches the selection process but only as frequently as the - * `cooldownDuration` option allows to prevent abuse. - * - * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), - * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if - * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key - * Operations) Parameters (if they are present on the JWK). - * - * Only a single public key must match the selection process. As shown in the example below when - * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt - * verification in an iterative manner. - * - * @example Usage - * - * ```js - * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Opting-in to multiple JWKS matches using `createRemoteJWKSet` - * - * ```js - * const options = { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * } - * const { payload, protectedHeader } = await jose - * .jwtVerify(jwt, JWKS, options) - * .catch(async (error) => { - * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { - * for await (const publicKey of error) { - * try { - * return await jose.jwtVerify(jwt, publicKey, options) - * } catch (innerError) { - * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { - * continue - * } - * throw innerError - * } - * } - * throw new jose.errors.JWSSignatureVerificationFailed() - * } - * - * throw error - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param url URL to fetch the JSON Web Key Set from. - * @param options Options for the remote JSON Web Key Set. - */ -export declare function createRemoteJWKSet(url: URL, options?: RemoteJWKSetOptions): (protectedHeader?: JWSHeaderParameters | undefined, token?: FlattenedJWSInput | undefined) => Promise; diff --git a/dist/types/jws/compact/sign.d.ts b/dist/types/jws/compact/sign.d.ts deleted file mode 100644 index 1edb1790d7..0000000000 --- a/dist/types/jws/compact/sign.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { CompactJWSHeaderParameters, KeyLike, SignOptions } from '../../types'; -/** - * The CompactSign class is a utility for creating Compact JWS strings. - * - * @example Usage - * - * ```js - * const jws = await new jose.CompactSign( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'ES256' }) - * .sign(privateKey) - * - * console.log(jws) - * ``` - */ -export declare class CompactSign { - private _flattened; - /** @param payload Binary representation of the payload to sign. */ - constructor(payload: Uint8Array); - /** - * Sets the JWS Protected Header on the Sign object. - * - * @param protectedHeader JWS Protected Header. - */ - setProtectedHeader(protectedHeader: CompactJWSHeaderParameters): this; - /** - * Signs and resolves the value of the Compact JWS string. - * - * @param key Private Key or Secret to sign the JWS with. - * @param options JWS Sign options. - */ - sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise; -} diff --git a/dist/types/jws/compact/verify.d.ts b/dist/types/jws/compact/verify.d.ts deleted file mode 100644 index e164c10447..0000000000 --- a/dist/types/jws/compact/verify.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { CompactVerifyResult, FlattenedJWSInput, GetKeyFunction, CompactJWSHeaderParameters, KeyLike, VerifyOptions, ResolvedKey } from '../../types'; -/** - * Interface for Compact JWS Verification dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface CompactVerifyGetKey extends GetKeyFunction { -} -/** - * Verifies the signature and format of and afterwards decodes the Compact JWS. - * - * @example Usage - * - * ```js - * const jws = - * 'eyJhbGciOiJFUzI1NiJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4.kkAs_gPPxWMI3rHuVlxHaTPfDWDoqdI8jSvuSmqV-8IHIWXg9mcAeC9ggV-45ZHRbiRJ3obUIFo1rHphPA5URg' - * - * const { payload, protectedHeader } = await jose.compactVerify(jws, publicKey) - * - * console.log(protectedHeader) - * console.log(new TextDecoder().decode(payload)) - * ``` - * - * @param jws Compact JWS. - * @param key Key to verify the JWS with. - * @param options JWS Verify options. - */ -export declare function compactVerify(jws: string | Uint8Array, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise; -/** - * @param jws Compact JWS. - * @param getKey Function resolving a key to verify the JWS with. - * @param options JWS Verify options. - */ -export declare function compactVerify(jws: string | Uint8Array, getKey: CompactVerifyGetKey, options?: VerifyOptions): Promise; diff --git a/dist/types/jws/flattened/sign.d.ts b/dist/types/jws/flattened/sign.d.ts deleted file mode 100644 index b719e7e1ef..0000000000 --- a/dist/types/jws/flattened/sign.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { KeyLike, FlattenedJWS, JWSHeaderParameters, SignOptions } from '../../types'; -/** - * The FlattenedSign class is a utility for creating Flattened JWS objects. - * - * @example Usage - * - * ```js - * const jws = await new jose.FlattenedSign( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .setProtectedHeader({ alg: 'ES256' }) - * .sign(privateKey) - * - * console.log(jws) - * ``` - */ -export declare class FlattenedSign { - private _payload; - private _protectedHeader; - private _unprotectedHeader; - /** @param payload Binary representation of the payload to sign. */ - constructor(payload: Uint8Array); - /** - * Sets the JWS Protected Header on the FlattenedSign object. - * - * @param protectedHeader JWS Protected Header. - */ - setProtectedHeader(protectedHeader: JWSHeaderParameters): this; - /** - * Sets the JWS Unprotected Header on the FlattenedSign object. - * - * @param unprotectedHeader JWS Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters): this; - /** - * Signs and resolves the value of the Flattened JWS object. - * - * @param key Private Key or Secret to sign the JWS with. - * @param options JWS Sign options. - */ - sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise; -} diff --git a/dist/types/jws/flattened/verify.d.ts b/dist/types/jws/flattened/verify.d.ts deleted file mode 100644 index b4b7d65d64..0000000000 --- a/dist/types/jws/flattened/verify.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { FlattenedVerifyResult, KeyLike, FlattenedJWSInput, JWSHeaderParameters, VerifyOptions, GetKeyFunction, ResolvedKey } from '../../types'; -/** - * Interface for Flattened JWS Verification dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface FlattenedVerifyGetKey extends GetKeyFunction { -} -/** - * Verifies the signature and format of and afterwards decodes the Flattened JWS. - * - * @example Usage - * - * ```js - * const decoder = new TextDecoder() - * const jws = { - * signature: - * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', - * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', - * protected: 'eyJhbGciOiJFUzI1NiJ9', - * } - * - * const { payload, protectedHeader } = await jose.flattenedVerify(jws, publicKey) - * - * console.log(protectedHeader) - * console.log(decoder.decode(payload)) - * ``` - * - * @param jws Flattened JWS. - * @param key Key to verify the JWS with. - * @param options JWS Verify options. - */ -export declare function flattenedVerify(jws: FlattenedJWSInput, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise; -/** - * @param jws Flattened JWS. - * @param getKey Function resolving a key to verify the JWS with. - * @param options JWS Verify options. - */ -export declare function flattenedVerify(jws: FlattenedJWSInput, getKey: FlattenedVerifyGetKey, options?: VerifyOptions): Promise; diff --git a/dist/types/jws/general/sign.d.ts b/dist/types/jws/general/sign.d.ts deleted file mode 100644 index 59a765cfef..0000000000 --- a/dist/types/jws/general/sign.d.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { KeyLike, GeneralJWS, JWSHeaderParameters, SignOptions } from '../../types'; -export interface Signature { - /** - * Sets the JWS Protected Header on the Signature object. - * - * @param protectedHeader JWS Protected Header. - */ - setProtectedHeader(protectedHeader: JWSHeaderParameters): Signature; - /** - * Sets the JWS Unprotected Header on the Signature object. - * - * @param unprotectedHeader JWS Unprotected Header. - */ - setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters): Signature; - /** A shorthand for calling addSignature() on the enclosing GeneralSign instance */ - addSignature(...args: Parameters): Signature; - /** A shorthand for calling encrypt() on the enclosing GeneralSign instance */ - sign(...args: Parameters): Promise; - /** Returns the enclosing GeneralSign */ - done(): GeneralSign; -} -/** - * The GeneralSign class is a utility for creating General JWS objects. - * - * @example Usage - * - * ```js - * const jws = await new jose.GeneralSign( - * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), - * ) - * .addSignature(ecPrivateKey) - * .setProtectedHeader({ alg: 'ES256' }) - * .addSignature(rsaPrivateKey) - * .setProtectedHeader({ alg: 'PS256' }) - * .sign() - * - * console.log(jws) - * ``` - */ -export declare class GeneralSign { - private _payload; - private _signatures; - /** @param payload Binary representation of the payload to sign. */ - constructor(payload: Uint8Array); - /** - * Adds an additional signature for the General JWS object. - * - * @param key Private Key or Secret to sign the individual JWS signature with. - * @param options JWS Sign options. - */ - addSignature(key: KeyLike | Uint8Array, options?: SignOptions): Signature; - /** Signs and resolves the value of the General JWS object. */ - sign(): Promise; -} diff --git a/dist/types/jws/general/verify.d.ts b/dist/types/jws/general/verify.d.ts deleted file mode 100644 index 3795656add..0000000000 --- a/dist/types/jws/general/verify.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { GeneralJWSInput, GeneralVerifyResult, FlattenedJWSInput, GetKeyFunction, JWSHeaderParameters, KeyLike, VerifyOptions, ResolvedKey } from '../../types'; -/** - * Interface for General JWS Verification dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface GeneralVerifyGetKey extends GetKeyFunction { -} -/** - * Verifies the signature and format of and afterwards decodes the General JWS. - * - * @example Usage - * - * ```js - * const jws = { - * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', - * signatures: [ - * { - * signature: - * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', - * protected: 'eyJhbGciOiJFUzI1NiJ9', - * }, - * ], - * } - * - * const { payload, protectedHeader } = await jose.generalVerify(jws, publicKey) - * - * console.log(protectedHeader) - * console.log(new TextDecoder().decode(payload)) - * ``` - * - * @param jws General JWS. - * @param key Key to verify the JWS with. - * @param options JWS Verify options. - */ -export declare function generalVerify(jws: GeneralJWSInput, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise; -/** - * @param jws General JWS. - * @param getKey Function resolving a key to verify the JWS with. - * @param options JWS Verify options. - */ -export declare function generalVerify(jws: GeneralJWSInput, getKey: GeneralVerifyGetKey, options?: VerifyOptions): Promise; diff --git a/dist/types/jwt/decrypt.d.ts b/dist/types/jwt/decrypt.d.ts deleted file mode 100644 index f1d5d4c44e..0000000000 --- a/dist/types/jwt/decrypt.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { KeyLike, DecryptOptions, JWTClaimVerificationOptions, GetKeyFunction, CompactJWEHeaderParameters, FlattenedJWE, JWTDecryptResult, ResolvedKey } from '../types'; -/** Combination of JWE Decryption options and JWT Claims Set verification options. */ -export interface JWTDecryptOptions extends DecryptOptions, JWTClaimVerificationOptions { -} -/** - * Interface for JWT Decryption dynamic key resolution. No token components have been verified at - * the time of this function call. - */ -export interface JWTDecryptGetKey extends GetKeyFunction { -} -/** - * Verifies the JWT format (to be a JWE Compact format), decrypts the ciphertext, validates the JWT - * Claims Set. - * - * @example Usage - * - * ```js - * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') - * const jwt = - * 'eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..MB66qstZBPxAXKdsjet_lA.WHbtJTl4taHp7otOHLq3hBvv0yNPsPEKHYInmCPdDDeyV1kU-f-tGEiU4FxlSqkqAT2hVs8_wMNiQFAzPU1PUgIqWCPsBrPP3TtxYsrtwagpn4SvCsUsx0Mhw9ZhliAO8CLmCBQkqr_T9AcYsz5uZw.7nX9m7BGUu_u1p1qFHzyIg' - * - * const { payload, protectedHeader } = await jose.jwtDecrypt(jwt, secret, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwt JSON Web Token value (encoded as JWE). - * @param key Private Key or Secret to decrypt and verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export declare function jwtDecrypt(jwt: string | Uint8Array, key: KeyLike | Uint8Array, options?: JWTDecryptOptions): Promise; -/** - * @param jwt JSON Web Token value (encoded as JWE). - * @param getKey Function resolving Private Key or Secret to decrypt and verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export declare function jwtDecrypt(jwt: string | Uint8Array, getKey: JWTDecryptGetKey, options?: JWTDecryptOptions): Promise; diff --git a/dist/types/jwt/encrypt.d.ts b/dist/types/jwt/encrypt.d.ts deleted file mode 100644 index d25808a8a8..0000000000 --- a/dist/types/jwt/encrypt.d.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { EncryptOptions, CompactJWEHeaderParameters, JWEKeyManagementHeaderParameters, KeyLike } from '../types'; -import { ProduceJWT } from './produce'; -/** - * The EncryptJWT class is a utility for creating Compact JWE formatted JWT strings. - * - * @example Usage - * - * ```js - * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') - * const jwt = await new jose.EncryptJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg: 'dir', enc: 'A128CBC-HS256' }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .encrypt(secret) - * - * console.log(jwt) - * ``` - */ -export declare class EncryptJWT extends ProduceJWT { - private _cek; - private _iv; - private _keyManagementParameters; - private _protectedHeader; - private _replicateIssuerAsHeader; - private _replicateSubjectAsHeader; - private _replicateAudienceAsHeader; - /** - * Sets the JWE Protected Header on the EncryptJWT object. - * - * @param protectedHeader JWE Protected Header. Must contain an "alg" (JWE Algorithm) and "enc" - * (JWE Encryption Algorithm) properties. - */ - setProtectedHeader(protectedHeader: CompactJWEHeaderParameters): this; - /** - * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is - * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or - * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed - * and missing. - * - * @param parameters JWE Key Management parameters. - */ - setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this; - /** - * Sets a content encryption key to use, by default a random suitable one is generated for the JWE - * enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param cek JWE Content Encryption Key. - */ - setContentEncryptionKey(cek: Uint8Array): this; - /** - * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable - * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. - * - * @deprecated You should not use this method. It is only really intended for test and vector - * validation purposes. - * @param iv JWE Initialization Vector. - */ - setInitializationVector(iv: Uint8Array): this; - /** - * Replicates the "iss" (Issuer) Claim as a JWE Protected Header Parameter as per - * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). - */ - replicateIssuerAsHeader(): this; - /** - * Replicates the "sub" (Subject) Claim as a JWE Protected Header Parameter as per - * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). - */ - replicateSubjectAsHeader(): this; - /** - * Replicates the "aud" (Audience) Claim as a JWE Protected Header Parameter as per - * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). - */ - replicateAudienceAsHeader(): this; - /** - * Encrypts and returns the JWT. - * - * @param key Public Key or Secret to encrypt the JWT with. - * @param options JWE Encryption options. - */ - encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise; -} diff --git a/dist/types/jwt/produce.d.ts b/dist/types/jwt/produce.d.ts deleted file mode 100644 index 5563a062e5..0000000000 --- a/dist/types/jwt/produce.d.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { JWTPayload } from '../types'; -/** Generic class for JWT producing. */ -export declare class ProduceJWT { - protected _payload: JWTPayload; - /** @param payload The JWT Claims Set object. */ - constructor(payload: JWTPayload); - /** - * Set "iss" (Issuer) Claim. - * - * @param issuer "Issuer" Claim value to set on the JWT Claims Set. - */ - setIssuer(issuer: string): this; - /** - * Set "sub" (Subject) Claim. - * - * @param subject "sub" (Subject) Claim value to set on the JWT Claims Set. - */ - setSubject(subject: string): this; - /** - * Set "aud" (Audience) Claim. - * - * @param audience "aud" (Audience) Claim value to set on the JWT Claims Set. - */ - setAudience(audience: string | string[]): this; - /** - * Set "jti" (JWT ID) Claim. - * - * @param jwtId "jti" (JWT ID) Claim value to set on the JWT Claims Set. - */ - setJti(jwtId: string): this; - /** - * Set "nbf" (Not Before) Claim. - * - * @param input "nbf" (Not Before) Claim value to set on the JWT Claims Set. When number is passed - * that is used as a value, when string is passed it is resolved to a time span and added to the - * current timestamp. - */ - setNotBefore(input: number | string): this; - /** - * Set "exp" (Expiration Time) Claim. - * - * @param input "exp" (Expiration Time) Claim value to set on the JWT Claims Set. When number is - * passed that is used as a value, when string is passed it is resolved to a time span and added - * to the current timestamp. - */ - setExpirationTime(input: number | string): this; - /** - * Set "iat" (Issued At) Claim. - * - * @param input "iat" (Issued At) Claim value to set on the JWT Claims Set. Default is current - * timestamp. - */ - setIssuedAt(input?: number): this; -} diff --git a/dist/types/jwt/sign.d.ts b/dist/types/jwt/sign.d.ts deleted file mode 100644 index 976ee16754..0000000000 --- a/dist/types/jwt/sign.d.ts +++ /dev/null @@ -1,113 +0,0 @@ -import type { JWTHeaderParameters, KeyLike, SignOptions } from '../types'; -import { ProduceJWT } from './produce'; -/** - * The SignJWT class is a utility for creating Compact JWS formatted JWT strings. - * - * @example Usage with a symmetric secret - * - * ```js - * const secret = new TextEncoder().encode( - * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', - * ) - * const alg = 'HS256' - * - * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .sign(secret) - * - * console.log(jwt) - * ``` - * - * @example Usage with a private PKCS#8 encoded RSA key - * - * ```js - * const alg = 'RS256' - * const pkcs8 = `-----BEGIN PRIVATE KEY----- - * MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCFg4UrY5xtulv - * /NXKmL1J4qI1SopAfTNMo3X7p+kJO7plqUYjzaztcre1qfh0m33Sm1Q8oPbO/GpP - * MU1/HgcceytgJ/b4UwufVVMl9BrMDYG8moDBylbVupFQS3Ly1L9i/iFG9Z9A9xzY - * Zzf799A45bnvNXL6s2glzvjiRvfQ2NDF0anTcnZLcYtC7ugq1IMM+ihAcPfw8Qw2 - * chN/SmP4qAM+PKaQwagmU7doqmmyN9u38AfoYZ1GCFhEs5TBBT6H6h9YdHeVtiIq - * 1c+fl03biSIfLrV7dUBD39gBmXBcL/30Ya3D82mCEUC4zg/UkOfQOmkmV3Lc8YUL - * QZ8EJkBLAgMBAAECggEAVuVE/KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34ls - * VOPK0XDegZkhAybMZHjRhp+gwVxX5ChC+J3cUpOBH5FNxElgW6HizD2Jcq6t6LoL - * YgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG/qJV1K00/Ly1G1QKoBffEs - * +v4fAMJrCbUdCz1qWto+PU+HLMEo+krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq/ - * aAP4a1SXmo+j0cvRU4W5Fj0RVwNesIpetX2ZFz4p/JmB5sWFEj/fC7h5z2lq+6Bm - * e2T3BHtXkIxoBW0/pYVnASC8P2puO5FnVxDmWuHDYQKBgQDTuuBd3+0tSFVEX+DU - * 5qpFmHm5nyGItZRJTS+71yg5pBxq1KqNCUjAtbxR0q//fwauakh+BwRVCPOrqsUG - * jBSb3NYE70Srp6elqxgkE54PwQx4Mr6exJPnseM9U4K+hULllf5yjM9edreJE1nV - * NVgFjeyafQhrHKwgr7PERJ/ikwKBgQDqqsT1M+EJLmI1HtCspOG6cu7q3gf/wKRh - * E8tu84i3YyBnI8uJkKy92RNVI5fvpBARe3tjSdM25rr2rcrcmF/5g6Q9ImxZPGCt - * 86eOgO9ErNtbc4TEgybsP319UE4O41aKeNiBTAZKoYCxv/dMqG0j4avmWzd+foHq - * gSNUvR2maQKBgQCYeqOsV2B6VPY7KIVFLd0AA9/dwvEmgAYLiA/RShDI+hwQ/5jX - * uxDu37KAhqeC65sHLrmIMUt4Zdr+DRyZK3aIDNEAesPMjw/X6lCXYp1ZISD2yyym - * MFGH8X8CIkstI9Faf9vf6PJKSFrC1/HA7wq17VCwrUzLvrljTMW8meM/CwKBgCpo - * 2leGHLFQFKeM/iF1WuYbR1pi7gcmhY6VyTowARFDdOOu8GXYI5/bz0afvCGvAMho - * DJCREv7lC/zww6zCTPYG+HOj+PjXlJFba3ixjIxYwPvyEJiDK1Ge18sB7Fl8dHNq - * C5ayaqCqN1voWYUdGzxU2IA1E/5kVo5O8FesJeOhAoGBAImJbZFf+D5kA32Xxhac - * 59lLWBCsocvvbd1cvDMNlRywAAyhsCb1SuX4nEAK9mrSBdfmoF2Nm3eilfsOds0f - * K5mX069IKG82CMqh3Mzptd7e7lyb9lsoGO0BAtjho3cWtha/UZ70vfaMzGuZ6JmQ - * ak6k+8+UFd93M4z0Qo74OhXB - * -----END PRIVATE KEY-----` - * const privateKey = await jose.importPKCS8(pkcs8, alg) - * - * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .sign(privateKey) - * - * console.log(jwt) - * ``` - * - * @example Usage with a private JWK encoded RSA key - * - * ```js - * const alg = 'RS256' - * const jwk = { - * kty: 'RSA', - * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', - * e: 'AQAB', - * d: 'VuVE_KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34lsVOPK0XDegZkhAybMZHjRhp-gwVxX5ChC-J3cUpOBH5FNxElgW6HizD2Jcq6t6LoLYgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG_qJV1K00_Ly1G1QKoBffEs-v4fAMJrCbUdCz1qWto-PU-HLMEo-krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq_aAP4a1SXmo-j0cvRU4W5Fj0RVwNesIpetX2ZFz4p_JmB5sWFEj_fC7h5z2lq-6Bme2T3BHtXkIxoBW0_pYVnASC8P2puO5FnVxDmWuHDYQ', - * p: '07rgXd_tLUhVRF_g1OaqRZh5uZ8hiLWUSU0vu9coOaQcatSqjQlIwLW8UdKv_38GrmpIfgcEVQjzq6rFBowUm9zWBO9Eq6enpasYJBOeD8EMeDK-nsST57HjPVOCvoVC5ZX-cozPXna3iRNZ1TVYBY3smn0IaxysIK-zxESf4pM', - * q: '6qrE9TPhCS5iNR7QrKThunLu6t4H_8CkYRPLbvOIt2MgZyPLiZCsvdkTVSOX76QQEXt7Y0nTNua69q3K3Jhf-YOkPSJsWTxgrfOnjoDvRKzbW3OExIMm7D99fVBODuNWinjYgUwGSqGAsb_3TKhtI-Gr5ls3fn6B6oEjVL0dpmk', - * dp: 'mHqjrFdgelT2OyiFRS3dAAPf3cLxJoAGC4gP0UoQyPocEP-Y17sQ7t-ygIanguubBy65iDFLeGXa_g0cmSt2iAzRAHrDzI8P1-pQl2KdWSEg9ssspjBRh_F_AiJLLSPRWn_b3-jySkhawtfxwO8Kte1QsK1My765Y0zFvJnjPws', - * dq: 'KmjaV4YcsVAUp4z-IXVa5htHWmLuByaFjpXJOjABEUN0467wZdgjn9vPRp-8Ia8AyGgMkJES_uUL_PDDrMJM9gb4c6P4-NeUkVtreLGMjFjA-_IQmIMrUZ7XywHsWXx0c2oLlrJqoKo3W-hZhR0bPFTYgDUT_mRWjk7wV6wl46E', - * qi: 'iYltkV_4PmQDfZfGFpzn2UtYEKyhy-9t3Vy8Mw2VHLAADKGwJvVK5ficQAr2atIF1-agXY2bd6KV-w52zR8rmZfTr0gobzYIyqHczOm13t7uXJv2WygY7QEC2OGjdxa2Fr9RnvS99ozMa5nomZBqTqT7z5QV33czjPRCjvg6FcE', - * } - * const privateKey = await jose.importJWK(jwk, alg) - * - * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) - * .setProtectedHeader({ alg }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .sign(privateKey) - * - * console.log(jwt) - * ``` - */ -export declare class SignJWT extends ProduceJWT { - private _protectedHeader; - /** - * Sets the JWS Protected Header on the SignJWT object. - * - * @param protectedHeader JWS Protected Header. Must contain an "alg" (JWS Algorithm) property. - */ - setProtectedHeader(protectedHeader: JWTHeaderParameters): this; - /** - * Signs and returns the JWT. - * - * @param key Private Key or Secret to sign the JWT with. - * @param options JWT Sign options. - */ - sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise; -} diff --git a/dist/types/jwt/unsecured.d.ts b/dist/types/jwt/unsecured.d.ts deleted file mode 100644 index 767ea18461..0000000000 --- a/dist/types/jwt/unsecured.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { JWSHeaderParameters, JWTClaimVerificationOptions, JWTPayload } from '../types'; -import { ProduceJWT } from './produce'; -export interface UnsecuredResult { - payload: JWTPayload; - header: JWSHeaderParameters; -} -/** - * The UnsecuredJWT class is a utility for dealing with `{ "alg": "none" }` Unsecured JWTs. - * - * @example Encoding - * - * ```js - * const unsecuredJwt = new jose.UnsecuredJWT({ 'urn:example:claim': true }) - * .setIssuedAt() - * .setIssuer('urn:example:issuer') - * .setAudience('urn:example:audience') - * .setExpirationTime('2h') - * .encode() - * - * console.log(unsecuredJwt) - * ``` - * - * @example Decoding - * - * ```js - * const payload = jose.UnsecuredJWT.decode(jwt, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(payload) - * ``` - */ -export declare class UnsecuredJWT extends ProduceJWT { - /** Encodes the Unsecured JWT. */ - encode(): string; - /** - * Decodes an unsecured JWT. - * - * @param jwt Unsecured JWT to decode the payload of. - * @param options JWT Claims Set validation options. - */ - static decode(jwt: string, options?: JWTClaimVerificationOptions): UnsecuredResult; -} diff --git a/dist/types/jwt/verify.d.ts b/dist/types/jwt/verify.d.ts deleted file mode 100644 index 50b0cbafd3..0000000000 --- a/dist/types/jwt/verify.d.ts +++ /dev/null @@ -1,108 +0,0 @@ -import type { KeyLike, VerifyOptions, JWTClaimVerificationOptions, JWTHeaderParameters, GetKeyFunction, FlattenedJWSInput, JWTVerifyResult, ResolvedKey } from '../types'; -/** Combination of JWS Verification options and JWT Claims Set verification options. */ -export interface JWTVerifyOptions extends VerifyOptions, JWTClaimVerificationOptions { -} -/** - * Interface for JWT Verification dynamic key resolution. No token components have been verified at - * the time of this function call. - * - * See - * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) - * to verify using a remote JSON Web Key Set. - */ -export interface JWTVerifyGetKey extends GetKeyFunction { -} -/** - * Verifies the JWT format (to be a JWS Compact format), verifies the JWS signature, validates the - * JWT Claims Set. - * - * @example Usage with a symmetric secret - * - * ```js - * const secret = new TextEncoder().encode( - * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', - * ) - * const jwt = - * 'eyJhbGciOiJIUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2MjMxLCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.C4iSlLfAUMBq--wnC6VqD9gEOhwpRZpoRarE0m7KEnI' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, secret, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Usage with a public SPKI encoded RSA key - * - * ```js - * const alg = 'RS256' - * const spki = `-----BEGIN PUBLIC KEY----- - * MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwhYOFK2Ocbbpb/zVypi9 - * SeKiNUqKQH0zTKN1+6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4H - * HHsrYCf2+FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS/Yv4hRvWfQPcc2Gc3+/fQ - * OOW57zVy+rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj - * +KgDPjymkMGoJlO3aKppsjfbt/AH6GGdRghYRLOUwQU+h+ofWHR3lbYiKtXPn5dN - * 24kiHy61e3VAQ9/YAZlwXC/99GGtw/NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZA - * SwIDAQAB - * -----END PUBLIC KEY-----` - * const publicKey = await jose.importSPKI(spki, alg) - * const jwt = - * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @example Usage with a public JWK encoded RSA key - * - * ```js - * const alg = 'RS256' - * const jwk = { - * kty: 'RSA', - * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', - * e: 'AQAB', - * } - * const publicKey = await jose.importJWK(jwk, alg) - * const jwt = - * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwt JSON Web Token value (encoded as JWS). - * @param key Key to verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export declare function jwtVerify(jwt: string | Uint8Array, key: KeyLike | Uint8Array, options?: JWTVerifyOptions): Promise; -/** - * @example Usage with a public JSON Web Key Set hosted on a remote URL - * - * ```js - * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) - * - * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { - * issuer: 'urn:example:issuer', - * audience: 'urn:example:audience', - * }) - * console.log(protectedHeader) - * console.log(payload) - * ``` - * - * @param jwt JSON Web Token value (encoded as JWS). - * @param getKey Function resolving a key to verify the JWT with. - * @param options JWT Decryption and JWT Claims Set validation options. - */ -export declare function jwtVerify(jwt: string | Uint8Array, getKey: JWTVerifyGetKey, options?: JWTVerifyOptions): Promise; diff --git a/dist/types/key/export.d.ts b/dist/types/key/export.d.ts deleted file mode 100644 index 5d745e446f..0000000000 --- a/dist/types/key/export.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { JWK, KeyLike } from '../types'; -/** - * Exports a runtime-specific public key representation (KeyObject or CryptoKey) to a PEM-encoded - * SPKI string format. - * - * @example Usage - * - * ```js - * const spkiPem = await jose.exportSPKI(publicKey) - * - * console.log(spkiPem) - * ``` - * - * @param key Key representation to transform to a PEM-encoded SPKI string format. - */ -export declare function exportSPKI(key: KeyLike): Promise; -/** - * Exports a runtime-specific private key representation (KeyObject or CryptoKey) to a PEM-encoded - * PKCS8 string format. - * - * @example Usage - * - * ```js - * const pkcs8Pem = await jose.exportPKCS8(privateKey) - * - * console.log(pkcs8Pem) - * ``` - * - * @param key Key representation to transform to a PEM-encoded PKCS8 string format. - */ -export declare function exportPKCS8(key: KeyLike): Promise; -/** - * Exports a runtime-specific key representation (KeyLike) to a JWK. - * - * @example Usage - * - * ```js - * const privateJwk = await jose.exportJWK(privateKey) - * const publicJwk = await jose.exportJWK(publicKey) - * - * console.log(privateJwk) - * console.log(publicJwk) - * ``` - * - * @param key Key representation to export as JWK. - */ -export declare function exportJWK(key: KeyLike | Uint8Array): Promise; diff --git a/dist/types/key/generate_key_pair.d.ts b/dist/types/key/generate_key_pair.d.ts deleted file mode 100644 index 13b87f27a0..0000000000 --- a/dist/types/key/generate_key_pair.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { KeyLike } from '../types'; -export interface GenerateKeyPairResult { - /** The generated Private Key. */ - privateKey: KeyLike; - /** Public Key corresponding to the generated Private Key. */ - publicKey: KeyLike; -} -export interface GenerateKeyPairOptions { - /** - * The EC "crv" (Curve) or OKP "crv" (Subtype of Key Pair) value to generate. The curve must be - * both supported on the runtime as well as applicable for the given JWA algorithm identifier. - */ - crv?: string; - /** - * A hint for RSA algorithms to generate an RSA key of a given `modulusLength` (Key size in bits). - * JOSE requires 2048 bits or larger. Default is 2048. - */ - modulusLength?: number; - /** - * (Only effective in Web Crypto API runtimes) The value to use as - * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) - * `extractable` argument. Default is false. - */ - extractable?: boolean; -} -/** - * Generates a private and a public key for a given JWA algorithm identifier. This can only generate - * asymmetric key pairs. For symmetric secrets use the `generateSecret` function. - * - * Note: Under Web Crypto API runtime the `privateKey` is generated with `extractable` set to - * `false` by default. - * - * @example Usage - * - * ```js - * const { publicKey, privateKey } = await jose.generateKeyPair('PS256') - * console.log(publicKey) - * console.log(privateKey) - * ``` - * - * @param alg JWA Algorithm Identifier to be used with the generated key pair. - * @param options Additional options passed down to the key pair generation. - */ -export declare function generateKeyPair(alg: string, options?: GenerateKeyPairOptions): Promise; diff --git a/dist/types/key/generate_secret.d.ts b/dist/types/key/generate_secret.d.ts deleted file mode 100644 index 31898091c9..0000000000 --- a/dist/types/key/generate_secret.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { KeyLike } from '../types'; -export interface GenerateSecretOptions { - /** - * (Only effective in Web Crypto API runtimes) The value to use as - * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) - * `extractable` argument. Default is false. - */ - extractable?: boolean; -} -/** - * Generates a symmetric secret key for a given JWA algorithm identifier. - * - * Note: Under Web Crypto API runtime the secret key is generated with `extractable` set to `false` - * by default. - * - * @example Usage - * - * ```js - * const secret = await jose.generateSecret('HS256') - * console.log(secret) - * ``` - * - * @param alg JWA Algorithm Identifier to be used with the generated secret. - * @param options Additional options passed down to the secret generation. - */ -export declare function generateSecret(alg: string, options?: GenerateSecretOptions): Promise; diff --git a/dist/types/key/import.d.ts b/dist/types/key/import.d.ts deleted file mode 100644 index 8bb9c25197..0000000000 --- a/dist/types/key/import.d.ts +++ /dev/null @@ -1,119 +0,0 @@ -import type { JWK, KeyLike } from '../types'; -export interface PEMImportOptions { - /** - * (Only effective in Web Crypto API runtimes) The value to use as - * [SubtleCrypto.importKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) - * `extractable` argument. Default is false. - */ - extractable?: boolean; -} -/** - * Imports a PEM-encoded SPKI string as a runtime-specific public key representation (KeyObject or - * CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to learn - * about key to algorithm requirements and mapping. - * - * @example Usage - * - * ```js - * const algorithm = 'ES256' - * const spki = `-----BEGIN PUBLIC KEY----- - * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM - * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== - * -----END PUBLIC KEY-----` - * const ecPublicKey = await jose.importSPKI(spki, algorithm) - * ``` - * - * @param pem PEM-encoded SPKI string - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key, its presence is only enforced in Web Crypto API runtimes. - */ -export declare function importSPKI(spki: string, alg: string, options?: PEMImportOptions): Promise; -/** - * Imports the SPKI from an X.509 string certificate as a runtime-specific public key representation - * (KeyObject or CryptoKey). See [Algorithm Key - * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm - * requirements and mapping. - * - * @example Usage - * - * ```js - * const algorithm = 'ES256' - * const x509 = `-----BEGIN CERTIFICATE----- - * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np - * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw - * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN - * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI - * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 - * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA - * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh - * v+A1QWZMuTWqYt+uh/YSRNDn - * -----END CERTIFICATE-----` - * const ecPublicKey = await jose.importX509(x509, algorithm) - * ``` - * - * @param pem X.509 certificate string - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key, its presence is only enforced in Web Crypto API runtimes. - */ -export declare function importX509(x509: string, alg: string, options?: PEMImportOptions): Promise; -/** - * Imports a PEM-encoded PKCS#8 string as a runtime-specific private key representation (KeyObject - * or CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to - * learn about key to algorithm requirements and mapping. Encrypted keys are not supported. - * - * @example Usage - * - * ```js - * const algorithm = 'ES256' - * const pkcs8 = `-----BEGIN PRIVATE KEY----- - * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN - * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg - * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa - * -----END PRIVATE KEY-----` - * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) - * ``` - * - * @param pem PEM-encoded PKCS#8 string - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key, its presence is only enforced in Web Crypto API runtimes. - */ -export declare function importPKCS8(pkcs8: string, alg: string, options?: PEMImportOptions): Promise; -/** - * Imports a JWK to a runtime-specific key representation (KeyLike). Either JWK "alg" (Algorithm) - * Parameter must be present or the optional "alg" argument. When running on a runtime using [Web - * Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) the jwk parameters "use", "key_ops", and - * "ext" are also used in the resulting `CryptoKey`. See [Algorithm Key - * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm - * requirements and mapping. - * - * @example Usage - * - * ```js - * const ecPublicKey = await jose.importJWK( - * { - * crv: 'P-256', - * kty: 'EC', - * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', - * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', - * }, - * 'ES256', - * ) - * - * const rsaPublicKey = await jose.importJWK( - * { - * kty: 'RSA', - * e: 'AQAB', - * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', - * }, - * 'PS256', - * ) - * ``` - * - * @param jwk JSON Web Key. - * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used - * with the imported key. Default is the "alg" property on the JWK, its presence is only enforced - * in Web Crypto API runtimes. - * @param octAsKeyObject Forces a symmetric key to be imported to a KeyObject or CryptoKey. Default - * is true unless JWK "ext" (Extractable) is true. - */ -export declare function importJWK(jwk: JWK, alg?: string, octAsKeyObject?: boolean): Promise; diff --git a/dist/types/types.d.ts b/dist/types/types.d.ts deleted file mode 100644 index 3310685b47..0000000000 --- a/dist/types/types.d.ts +++ /dev/null @@ -1,628 +0,0 @@ -/** - * KeyLike are runtime-specific classes representing asymmetric keys or symmetric secrets. These are - * instances of [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) and - * additionally [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) in Node.js runtime. - * [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) - * instances are also accepted as symmetric secret representation only. - * - * [Key Import Functions](../modules/key_import.md#readme) can be used to import PEM, or JWK - * formatted asymmetric keys and certificates to these runtime-specific representations. - * - * In Node.js the [Buffer](https://nodejs.org/api/buffer.html#buffer) class is a subclass of - * Uint8Array and so Buffer can be provided for symmetric secrets as well. - * - * [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) is a representation of a - * key/secret available in the Node.js runtime. In addition to the import functions of this library - * you may use the runtime APIs - * [crypto.createPublicKey](https://nodejs.org/api/crypto.html#cryptocreatepublickeykey), - * [crypto.createPrivateKey](https://nodejs.org/api/crypto.html#cryptocreateprivatekeykey), and - * [crypto.createSecretKey](https://nodejs.org/api/crypto.html#cryptocreatesecretkeykey-encoding) to - * obtain a KeyObject from your existing key material. - * - * [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) is a representation of a - * key/secret available in the Browser and Web-interoperable runtimes. In addition to the import - * functions of this library you may use the - * [SubtleCrypto.importKey](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) - * API to obtain a CryptoKey from your existing key material. - * - * @example Import a PEM-encoded SPKI Public Key - * - * ```js - * const algorithm = 'ES256' - * const spki = `-----BEGIN PUBLIC KEY----- - * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM - * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== - * -----END PUBLIC KEY-----` - * const ecPublicKey = await jose.importSPKI(spki, algorithm) - * ``` - * - * @example Import SPKI from an X.509 Certificate - * - * ```js - * const algorithm = 'ES256' - * const x509 = `-----BEGIN CERTIFICATE----- - * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np - * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw - * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN - * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI - * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 - * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA - * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh - * v+A1QWZMuTWqYt+uh/YSRNDn - * -----END CERTIFICATE-----` - * const ecPublicKey = await jose.importX509(x509, algorithm) - * ``` - * - * @example Import a PEM-encoded PKCS8 Private Key - * - * ```js - * const algorithm = 'ES256' - * const pkcs8 = `-----BEGIN PRIVATE KEY----- - * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN - * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg - * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa - * -----END PRIVATE KEY-----` - * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) - * ``` - * - * @example Import a JSON Web Key (JWK) - * - * ```js - * const ecPublicKey = await jose.importJWK( - * { - * crv: 'P-256', - * kty: 'EC', - * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', - * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', - * }, - * 'ES256', - * ) - * - * const rsaPublicKey = await jose.importJWK( - * { - * kty: 'RSA', - * e: 'AQAB', - * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', - * }, - * 'PS256', - * ) - * ``` - */ -export type KeyLike = { type: string } - -/** - * JSON Web Key ([JWK](https://www.rfc-editor.org/rfc/rfc7517)). "RSA", "EC", "OKP", and "oct" key - * types are supported. - */ -export interface JWK { - /** JWK "alg" (Algorithm) Parameter. */ - alg?: string - crv?: string - d?: string - dp?: string - dq?: string - e?: string - /** JWK "ext" (Extractable) Parameter. */ - ext?: boolean - k?: string - /** JWK "key_ops" (Key Operations) Parameter. */ - key_ops?: string[] - /** JWK "kid" (Key ID) Parameter. */ - kid?: string - /** JWK "kty" (Key Type) Parameter. */ - kty?: string - n?: string - oth?: Array<{ - d?: string - r?: string - t?: string - }> - p?: string - q?: string - qi?: string - /** JWK "use" (Public Key Use) Parameter. */ - use?: string - x?: string - y?: string - /** JWK "x5c" (X.509 Certificate Chain) Parameter. */ - x5c?: string[] - /** JWK "x5t" (X.509 Certificate SHA-1 Thumbprint) Parameter. */ - x5t?: string - /** "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Parameter. */ - 'x5t#S256'?: string - /** JWK "x5u" (X.509 URL) Parameter. */ - x5u?: string - - [propName: string]: unknown -} - -/** - * Generic Interface for consuming operations dynamic key resolution. No token components have been - * verified at the time of this function call. - * - * If you cannot match a key suitable for the token, throw an error instead. - * - * @param protectedHeader JWE or JWS Protected Header. - * @param token The consumed JWE or JWS token. - */ -export interface GetKeyFunction { - (protectedHeader: T, token: T2): Promise | KeyLike | Uint8Array -} - -/** - * Flattened JWS definition for verify function inputs, allows payload as Uint8Array for detached - * signature validation. - */ -export interface FlattenedJWSInput { - /** - * The "header" member MUST be present and contain the value JWS Unprotected Header when the JWS - * Unprotected Header value is non- empty; otherwise, it MUST be absent. This value is represented - * as an unencoded JSON object, rather than as a string. These Header Parameter values are not - * integrity protected. - */ - header?: JWSHeaderParameters - - /** - * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 - * "b64": false is used the value passed may also be a Uint8Array. - */ - payload: string | Uint8Array - - /** - * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWS Protected - * Header)) when the JWS Protected Header value is non-empty; otherwise, it MUST be absent. These - * Header Parameter values are integrity protected. - */ - protected?: string - - /** The "signature" member MUST be present and contain the value BASE64URL(JWS Signature). */ - signature: string -} - -/** - * General JWS definition for verify function inputs, allows payload as Uint8Array for detached - * signature validation. - */ -export interface GeneralJWSInput { - /** - * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 - * "b64": false is used the value passed may also be a Uint8Array. - */ - payload: string | Uint8Array - - /** - * The "signatures" member value MUST be an array of JSON objects. Each object represents a - * signature or MAC over the JWS Payload and the JWS Protected Header. - */ - signatures: Omit[] -} - -/** - * Flattened JWS definition. Payload is returned as an empty string when JWS Unencoded Payload - * Option [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. - */ -export interface FlattenedJWS extends Partial { - payload: string - signature: string -} - -/** - * General JWS definition. Payload is returned as an empty string when JWS Unencoded Payload Option - * [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. - */ -export interface GeneralJWS { - payload: string - signatures: Omit[] -} - -export interface JoseHeaderParameters { - /** "kid" (Key ID) Header Parameter. */ - kid?: string - - /** "x5t" (X.509 Certificate SHA-1 Thumbprint) Header Parameter. */ - x5t?: string - - /** "x5c" (X.509 Certificate Chain) Header Parameter. */ - x5c?: string[] - - /** "x5u" (X.509 URL) Header Parameter. */ - x5u?: string - - /** "jku" (JWK Set URL) Header Parameter. */ - jku?: string - - /** "jwk" (JSON Web Key) Header Parameter. */ - jwk?: Pick - - /** "typ" (Type) Header Parameter. */ - typ?: string - - /** "cty" (Content Type) Header Parameter. */ - cty?: string -} - -/** Recognized JWS Header Parameters, any other Header Members may also be present. */ -export interface JWSHeaderParameters extends JoseHeaderParameters { - /** JWS "alg" (Algorithm) Header Parameter. */ - alg?: string - - /** - * This JWS Extension Header Parameter modifies the JWS Payload representation and the JWS Signing - * Input computation as per [RFC7797](https://www.rfc-editor.org/rfc/rfc7797). - */ - b64?: boolean - - /** JWS "crit" (Critical) Header Parameter. */ - crit?: string[] - - /** Any other JWS Header member. */ - [propName: string]: unknown -} - -/** Recognized JWE Key Management-related Header Parameters. */ -export interface JWEKeyManagementHeaderParameters { - apu?: Uint8Array - apv?: Uint8Array - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - p2c?: number - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - p2s?: Uint8Array - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - iv?: Uint8Array - /** - * @deprecated You should not use this parameter. It is only really intended for test and vector - * validation purposes. - */ - epk?: KeyLike -} - -/** Flattened JWE definition. */ -export interface FlattenedJWE { - /** - * The "aad" member MUST be present and contain the value BASE64URL(JWE AAD)) when the JWE AAD - * value is non-empty; otherwise, it MUST be absent. A JWE AAD value can be included to supply a - * base64url-encoded value to be integrity protected but not encrypted. - */ - aad?: string - - /** The "ciphertext" member MUST be present and contain the value BASE64URL(JWE Ciphertext). */ - ciphertext: string - - /** - * The "encrypted_key" member MUST be present and contain the value BASE64URL(JWE Encrypted Key) - * when the JWE Encrypted Key value is non-empty; otherwise, it MUST be absent. - */ - encrypted_key?: string - - /** - * The "header" member MUST be present and contain the value JWE Per- Recipient Unprotected Header - * when the JWE Per-Recipient Unprotected Header value is non-empty; otherwise, it MUST be absent. - * This value is represented as an unencoded JSON object, rather than as a string. These Header - * Parameter values are not integrity protected. - */ - header?: JWEHeaderParameters - - /** - * The "iv" member MUST be present and contain the value BASE64URL(JWE Initialization Vector) when - * the JWE Initialization Vector value is non-empty; otherwise, it MUST be absent. - */ - iv: string - - /** - * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWE Protected - * Header)) when the JWE Protected Header value is non-empty; otherwise, it MUST be absent. These - * Header Parameter values are integrity protected. - */ - protected?: string - - /** - * The "tag" member MUST be present and contain the value BASE64URL(JWE Authentication Tag) when - * the JWE Authentication Tag value is non-empty; otherwise, it MUST be absent. - */ - tag: string - - /** - * The "unprotected" member MUST be present and contain the value JWE Shared Unprotected Header - * when the JWE Shared Unprotected Header value is non-empty; otherwise, it MUST be absent. This - * value is represented as an unencoded JSON object, rather than as a string. These Header - * Parameter values are not integrity protected. - */ - unprotected?: JWEHeaderParameters -} - -export interface GeneralJWE extends Omit { - recipients: Pick[] -} - -/** Recognized JWE Header Parameters, any other Header members may also be present. */ -export interface JWEHeaderParameters extends JoseHeaderParameters { - /** JWE "alg" (Algorithm) Header Parameter. */ - alg?: string - - /** JWE "enc" (Encryption Algorithm) Header Parameter. */ - enc?: string - - /** JWE "crit" (Critical) Header Parameter. */ - crit?: string[] - - /** JWE "zip" (Compression Algorithm) Header Parameter. */ - zip?: string - - /** Any other JWE Header member. */ - [propName: string]: unknown -} - -/** Shared Interface with a "crit" property for all sign, verify, encrypt and decrypt operations. */ -export interface CritOption { - /** - * An object with keys representing recognized "crit" (Critical) Header Parameter names. The value - * for those is either `true` or `false`. `true` when the Header Parameter MUST be integrity - * protected, `false` when it's irrelevant. - * - * This makes the "Extension Header Parameter "..." is not recognized" error go away. - * - * Use this when a given JWS/JWT/JWE profile requires the use of proprietary non-registered "crit" - * (Critical) Header Parameters. This will only make sure the Header Parameter is syntactically - * correct when provided and that it is optionally integrity protected. It will not process the - * Header Parameter in any way or reject the operation if it is missing. You MUST still verify the - * Header Parameter was present and process it according to the profile's validation steps after - * the operation succeeds. - * - * The JWS extension Header Parameter `b64` is always recognized and processed properly. No other - * registered Header Parameters that need this kind of default built-in treatment are currently - * available. - */ - crit?: { - [propName: string]: boolean - } -} - -/** JWE Decryption options. */ -export interface DecryptOptions extends CritOption { - /** A list of accepted JWE "alg" (Algorithm) Header Parameter values. */ - keyManagementAlgorithms?: string[] - - /** - * A list of accepted JWE "enc" (Encryption Algorithm) Header Parameter values. By default all - * "enc" (Encryption Algorithm) values applicable for the used key/secret are allowed. - */ - contentEncryptionAlgorithms?: string[] - - /** - * In a browser runtime you have to provide an implementation for Inflate Raw when you expect JWEs - * with compressed plaintext. - */ - inflateRaw?: InflateFunction - - /** - * (PBES2 Key Management Algorithms only) Maximum allowed "p2c" (PBES2 Count) Header Parameter - * value. The PBKDF2 iteration count defines the algorithm's computational expense. By default - * this value is set to 10000. - */ - maxPBES2Count?: number -} - -/** JWE Deflate option. */ -export interface DeflateOption { - /** - * In a browser runtime you have to provide an implementation for Deflate Raw when you will be - * producing JWEs with compressed plaintext. - */ - deflateRaw?: DeflateFunction -} - -/** JWE Encryption options. */ -export interface EncryptOptions extends CritOption, DeflateOption {} - -/** JWT Claims Set verification options. */ -export interface JWTClaimVerificationOptions { - /** Expected JWT "aud" (Audience) Claim value(s). */ - audience?: string | string[] - - /** - * Expected clock tolerance - * - * - In seconds when number (e.g. 5) - * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). - */ - clockTolerance?: string | number - - /** Expected JWT "iss" (Issuer) Claim value(s). */ - issuer?: string | string[] - - /** - * Maximum time elapsed (in seconds) from the JWT "iat" (Issued At) Claim value. - * - * - In seconds when number (e.g. 5) - * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). - */ - maxTokenAge?: string | number - - /** Expected JWT "sub" (Subject) Claim value. */ - subject?: string - - /** Expected JWT "typ" (Type) Header Parameter value. */ - typ?: string - - /** Date to use when comparing NumericDate claims, defaults to `new Date()`. */ - currentDate?: Date -} - -/** JWS Verification options. */ -export interface VerifyOptions extends CritOption { - /** - * A list of accepted JWS "alg" (Algorithm) Header Parameter values. By default all "alg" - * (Algorithm) values applicable for the used key/secret are allowed. Note: "none" is never - * accepted. - */ - algorithms?: string[] -} - -/** JWS Signing options. */ -export interface SignOptions extends CritOption {} - -/** Recognized JWT Claims Set members, any other members may also be present. */ -export interface JWTPayload { - /** - * JWT Issuer - * - * @see [RFC7519#section-4.1.1](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1) - */ - iss?: string - - /** - * JWT Subject - * - * @see [RFC7519#section-4.1.2](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2) - */ - sub?: string - - /** JWT Audience [RFC7519#section-4.1.3](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3). */ - aud?: string | string[] - - /** - * JWT ID - * - * @see [RFC7519#section-4.1.7](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7) - */ - jti?: string - - /** - * JWT Not Before - * - * @see [RFC7519#section-4.1.5](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5) - */ - nbf?: number - - /** - * JWT Expiration Time - * - * @see [RFC7519#section-4.1.4](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4) - */ - exp?: number - - /** - * JWT Issued At - * - * @see [RFC7519#section-4.1.6](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6) - */ - iat?: number - - /** Any other JWT Claim Set member. */ - [propName: string]: unknown -} - -/** - * Deflate Raw implementation, e.g. promisified - * [zlib.deflateRaw](https://nodejs.org/api/zlib.html#zlibdeflaterawbuffer-options-callback). - */ -export interface DeflateFunction { - (input: Uint8Array): Promise -} - -/** - * Inflate Raw implementation, e.g. promisified - * [zlib.inflateRaw](https://nodejs.org/api/zlib.html#zlibinflaterawbuffer-options-callback). - */ -export interface InflateFunction { - (input: Uint8Array): Promise -} - -export interface FlattenedDecryptResult { - /** JWE AAD. */ - additionalAuthenticatedData?: Uint8Array - - /** Plaintext. */ - plaintext: Uint8Array - - /** JWE Protected Header. */ - protectedHeader?: JWEHeaderParameters - - /** JWE Shared Unprotected Header. */ - sharedUnprotectedHeader?: JWEHeaderParameters - - /** JWE Per-Recipient Unprotected Header. */ - unprotectedHeader?: JWEHeaderParameters -} - -export interface GeneralDecryptResult extends FlattenedDecryptResult {} - -export interface CompactDecryptResult { - /** Plaintext. */ - plaintext: Uint8Array - - /** JWE Protected Header. */ - protectedHeader: CompactJWEHeaderParameters -} - -export interface FlattenedVerifyResult { - /** JWS Payload. */ - payload: Uint8Array - - /** JWS Protected Header. */ - protectedHeader?: JWSHeaderParameters - - /** JWS Unprotected Header. */ - unprotectedHeader?: JWSHeaderParameters -} - -export interface GeneralVerifyResult extends FlattenedVerifyResult {} - -export interface CompactVerifyResult { - /** JWS Payload. */ - payload: Uint8Array - - /** JWS Protected Header. */ - protectedHeader: CompactJWSHeaderParameters -} - -export interface JWTVerifyResult { - /** JWT Claims Set. */ - payload: JWTPayload - - /** JWS Protected Header. */ - protectedHeader: JWTHeaderParameters -} - -export interface JWTDecryptResult { - /** JWT Claims Set. */ - payload: JWTPayload - - /** JWE Protected Header. */ - protectedHeader: CompactJWEHeaderParameters -} - -export interface ResolvedKey { - /** Key resolved from the key resolver function. */ - key: KeyLike | Uint8Array -} - -/** Recognized Compact JWS Header Parameters, any other Header Members may also be present. */ -export interface CompactJWSHeaderParameters extends JWSHeaderParameters { - alg: string -} - -/** Recognized Signed JWT Header Parameters, any other Header Members may also be present. */ -export interface JWTHeaderParameters extends CompactJWSHeaderParameters { - b64?: true -} - -/** Recognized Compact JWE Header Parameters, any other Header Members may also be present. */ -export interface CompactJWEHeaderParameters extends JWEHeaderParameters { - alg: string - enc: string -} - -/** JSON Web Key Set */ -export interface JSONWebKeySet { - keys: JWK[] -} diff --git a/dist/types/util/base64url.d.ts b/dist/types/util/base64url.d.ts deleted file mode 100644 index ec08361d2c..0000000000 --- a/dist/types/util/base64url.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Utility function to encode a string or Uint8Array as a base64url string. - * - * @param input Value that will be base64url-encoded. - */ -interface Base64UrlEncode { - (input: Uint8Array | string): string; -} -/** - * Utility function to decode a base64url encoded string. - * - * @param input Value that will be base64url-decoded. - */ -interface Base64UrlDecode { - (input: Uint8Array | string): Uint8Array; -} -export declare const encode: Base64UrlEncode; -export declare const decode: Base64UrlDecode; -export {}; diff --git a/dist/types/util/decode_jwt.d.ts b/dist/types/util/decode_jwt.d.ts deleted file mode 100644 index 151cf733d1..0000000000 --- a/dist/types/util/decode_jwt.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { JWTPayload } from '../types'; -/** - * Decodes a signed JSON Web Token payload. This does not validate the JWT Claims Set types or - * values. This does not validate the JWS Signature. For a proper Signed JWT Claims Set validation - * and JWS signature verification use `jose.jwtVerify()`. For an encrypted JWT Claims Set validation - * and JWE decryption use `jose.jwtDecrypt()`. - * - * @example Usage - * - * ```js - * const claims = jose.decodeJwt(token) - * console.log(claims) - * ``` - * - * @param jwt JWT token in compact JWS serialization. - */ -export declare function decodeJwt(jwt: string): JWTPayload; diff --git a/dist/types/util/decode_protected_header.d.ts b/dist/types/util/decode_protected_header.d.ts deleted file mode 100644 index b452f82bfc..0000000000 --- a/dist/types/util/decode_protected_header.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { JWSHeaderParameters, JWEHeaderParameters } from '../types'; -export type ProtectedHeaderParameters = JWSHeaderParameters & JWEHeaderParameters; -/** - * Decodes the Protected Header of a JWE/JWS/JWT token utilizing any JOSE serialization. - * - * @example Usage - * - * ```js - * const protectedHeader = jose.decodeProtectedHeader(token) - * console.log(protectedHeader) - * ``` - * - * @param token JWE/JWS/JWT token in any JOSE serialization. - */ -export declare function decodeProtectedHeader(token: string | object): ProtectedHeaderParameters; diff --git a/dist/types/util/errors.d.ts b/dist/types/util/errors.d.ts deleted file mode 100644 index 3c5ac69778..0000000000 --- a/dist/types/util/errors.d.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { KeyLike } from '../types'; -/** A generic Error subclass that all other specific JOSE Error subclasses inherit from. */ -export declare class JOSEError extends Error { - /** A unique error code for the particular error subclass. */ - static get code(): string; - /** A unique error code for the particular error subclass. */ - code: string; - constructor(message?: string); -} -/** An error subclass thrown when a JWT Claim Set member validation fails. */ -export declare class JWTClaimValidationFailed extends JOSEError { - static get code(): 'ERR_JWT_CLAIM_VALIDATION_FAILED'; - code: string; - /** The Claim for which the validation failed. */ - claim: string; - /** Reason code for the validation failure. */ - reason: string; - constructor(message: string, claim?: string, reason?: string); -} -/** An error subclass thrown when a JWT is expired. */ -export declare class JWTExpired extends JOSEError implements JWTClaimValidationFailed { - static get code(): 'ERR_JWT_EXPIRED'; - code: string; - /** The Claim for which the validation failed. */ - claim: string; - /** Reason code for the validation failure. */ - reason: string; - constructor(message: string, claim?: string, reason?: string); -} -/** An error subclass thrown when a JOSE Algorithm is not allowed per developer preference. */ -export declare class JOSEAlgNotAllowed extends JOSEError { - static get code(): 'ERR_JOSE_ALG_NOT_ALLOWED'; - code: string; -} -/** - * An error subclass thrown when a particular feature or algorithm is not supported by this - * implementation or JOSE in general. - */ -export declare class JOSENotSupported extends JOSEError { - static get code(): 'ERR_JOSE_NOT_SUPPORTED'; - code: string; -} -/** An error subclass thrown when a JWE ciphertext decryption fails. */ -export declare class JWEDecryptionFailed extends JOSEError { - static get code(): 'ERR_JWE_DECRYPTION_FAILED'; - code: string; - message: string; -} -/** An error subclass thrown when a JWE is invalid. */ -export declare class JWEInvalid extends JOSEError { - static get code(): 'ERR_JWE_INVALID'; - code: string; -} -/** An error subclass thrown when a JWS is invalid. */ -export declare class JWSInvalid extends JOSEError { - static get code(): 'ERR_JWS_INVALID'; - code: string; -} -/** An error subclass thrown when a JWT is invalid. */ -export declare class JWTInvalid extends JOSEError { - static get code(): 'ERR_JWT_INVALID'; - code: string; -} -/** An error subclass thrown when a JWK is invalid. */ -export declare class JWKInvalid extends JOSEError { - static get code(): 'ERR_JWK_INVALID'; - code: string; -} -/** An error subclass thrown when a JWKS is invalid. */ -export declare class JWKSInvalid extends JOSEError { - static get code(): 'ERR_JWKS_INVALID'; - code: string; -} -/** An error subclass thrown when no keys match from a JWKS. */ -export declare class JWKSNoMatchingKey extends JOSEError { - static get code(): 'ERR_JWKS_NO_MATCHING_KEY'; - code: string; - message: string; -} -/** An error subclass thrown when multiple keys match from a JWKS. */ -export declare class JWKSMultipleMatchingKeys extends JOSEError { - /** @ignore */ - [Symbol.asyncIterator]: () => AsyncIterableIterator; - static get code(): 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; - code: string; - message: string; -} -/** Timeout was reached when retrieving the JWKS response. */ -export declare class JWKSTimeout extends JOSEError { - static get code(): 'ERR_JWKS_TIMEOUT'; - code: string; - message: string; -} -/** An error subclass thrown when JWS signature verification fails. */ -export declare class JWSSignatureVerificationFailed extends JOSEError { - static get code(): 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; - code: string; - message: string; -} From 46934ac474ba0119976c5ac15cce4ea7bf50de8c Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 27 Feb 2023 14:10:18 +0100 Subject: [PATCH 2/3] fix(types): declare explicit return from EmbeddedJWK --- src/jwk/embedded.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/jwk/embedded.ts b/src/jwk/embedded.ts index b75dc532d9..a538f5cf0d 100644 --- a/src/jwk/embedded.ts +++ b/src/jwk/embedded.ts @@ -1,4 +1,4 @@ -import type { FlattenedJWSInput, JWSHeaderParameters } from '../types.d' +import type { KeyLike, FlattenedJWSInput, JWSHeaderParameters } from '../types.d' import { importJWK } from '../key/import.js' import isObject from '../lib/is_object.js' import { JWSInvalid } from '../util/errors.js' @@ -24,7 +24,10 @@ import { JWSInvalid } from '../util/errors.js' * console.log(payload) * ``` */ -export async function EmbeddedJWK(protectedHeader: JWSHeaderParameters, token: FlattenedJWSInput) { +export async function EmbeddedJWK( + protectedHeader: JWSHeaderParameters, + token: FlattenedJWSInput, +): Promise { const joseHeader = { ...protectedHeader, ...token.header, From 0c5b164f52dbbaf2d23d7bf6914f1c50b76de969 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 27 Feb 2023 14:13:01 +0100 Subject: [PATCH 3/3] chore(release): 4.12.2 --- CHANGELOG.md | 7 + README.md | 2 +- dist/browser/index.bundle.js | 3368 ++++++++++++++++ dist/browser/index.bundle.min.js | 4 + dist/browser/index.js | 31 + dist/browser/index.umd.js | 3373 +++++++++++++++++ dist/browser/index.umd.min.js | 5 + dist/browser/jwe/compact/decrypt.js | 27 + dist/browser/jwe/compact/encrypt.js | 26 + dist/browser/jwe/flattened/decrypt.js | 137 + dist/browser/jwe/flattened/encrypt.js | 175 + dist/browser/jwe/general/decrypt.js | 31 + dist/browser/jwe/general/encrypt.js | 178 + dist/browser/jwk/embedded.js | 17 + dist/browser/jwk/thumbprint.js | 53 + dist/browser/jwks/local.js | 113 + dist/browser/jwks/remote.js | 81 + dist/browser/jws/compact/sign.js | 17 + dist/browser/jws/compact/verify.js | 21 + dist/browser/jws/flattened/sign.js | 81 + dist/browser/jws/flattened/verify.js | 104 + dist/browser/jws/general/sign.js | 67 + dist/browser/jws/general/verify.js | 24 + dist/browser/jwt/decrypt.js | 23 + dist/browser/jwt/encrypt.js | 68 + dist/browser/jwt/produce.js | 54 + dist/browser/jwt/sign.js | 21 + dist/browser/jwt/unsecured.js | 32 + dist/browser/jwt/verify.js | 16 + dist/browser/key/export.js | 12 + dist/browser/key/generate_key_pair.js | 4 + dist/browser/key/generate_secret.js | 4 + dist/browser/key/import.js | 50 + dist/browser/lib/aesgcmkw.js | 14 + dist/browser/lib/buffer_utils.js | 51 + dist/browser/lib/cek.js | 20 + dist/browser/lib/check_iv_length.js | 8 + dist/browser/lib/check_key_type.js | 45 + dist/browser/lib/check_p2s.js | 6 + dist/browser/lib/crypto_key.js | 158 + dist/browser/lib/decrypt_key_management.js | 98 + dist/browser/lib/encrypt_key_management.js | 87 + dist/browser/lib/epoch.js | 1 + dist/browser/lib/format_pem.js | 4 + dist/browser/lib/invalid_key_input.js | 30 + dist/browser/lib/is_disjoint.js | 22 + dist/browser/lib/is_object.js | 16 + dist/browser/lib/iv.js | 20 + dist/browser/lib/jwt_claims_set.js | 91 + dist/browser/lib/secs.js | 44 + dist/browser/lib/validate_algorithms.js | 11 + dist/browser/lib/validate_crit.js | 34 + dist/browser/package.json | 1 + dist/browser/runtime/aeskw.js | 32 + dist/browser/runtime/asn1.js | 214 ++ dist/browser/runtime/base64url.js | 37 + dist/browser/runtime/bogus.js | 6 + dist/browser/runtime/check_cek_length.js | 8 + dist/browser/runtime/check_key_length.js | 8 + dist/browser/runtime/decrypt.js | 85 + dist/browser/runtime/digest.js | 6 + dist/browser/runtime/ecdhes.js | 46 + dist/browser/runtime/encrypt.js | 68 + dist/browser/runtime/env.js | 5 + dist/browser/runtime/fetch_jwks.js | 34 + dist/browser/runtime/generate.js | 153 + dist/browser/runtime/get_sign_verify_key.js | 17 + dist/browser/runtime/is_key_like.js | 5 + dist/browser/runtime/jwk_to_key.js | 155 + dist/browser/runtime/key_to_jwk.js | 21 + dist/browser/runtime/pbes2kw.js | 51 + dist/browser/runtime/random.js | 2 + dist/browser/runtime/rsaes.js | 37 + dist/browser/runtime/sign.js | 11 + dist/browser/runtime/subtle_dsa.js | 30 + dist/browser/runtime/subtle_rsaes.js | 12 + dist/browser/runtime/timing_safe_equal.js | 19 + dist/browser/runtime/verify.js | 16 + dist/browser/runtime/webcrypto.js | 2 + dist/browser/runtime/zlib.js | 7 + dist/browser/util/base64url.js | 3 + dist/browser/util/decode_jwt.js | 32 + dist/browser/util/decode_protected_header.js | 34 + dist/browser/util/errors.js | 148 + dist/deno/README.md | 51 + dist/deno/index.ts | 98 + dist/deno/jwe/compact/decrypt.ts | 99 + dist/deno/jwe/compact/encrypt.ts | 91 + dist/deno/jwe/flattened/decrypt.ts | 247 ++ dist/deno/jwe/flattened/encrypt.ts | 309 ++ dist/deno/jwe/general/decrypt.ts | 107 + dist/deno/jwe/general/encrypt.ts | 306 ++ dist/deno/jwk/embedded.ts | 46 + dist/deno/jwk/thumbprint.ts | 114 + dist/deno/jwks/local.ts | 245 ++ dist/deno/jwks/remote.ts | 204 + dist/deno/jws/compact/sign.ts | 52 + dist/deno/jws/compact/verify.ts | 90 + dist/deno/jws/flattened/sign.ts | 152 + dist/deno/jws/flattened/verify.ts | 203 + dist/deno/jws/general/sign.ts | 143 + dist/deno/jws/general/verify.ts | 98 + dist/deno/jwt/decrypt.ts | 108 + dist/deno/jwt/encrypt.ts | 162 + dist/deno/jwt/produce.ts | 104 + dist/deno/jwt/sign.ts | 134 + dist/deno/jwt/unsecured.ts | 78 + dist/deno/jwt/verify.ts | 147 + dist/deno/key/export.ts | 60 + dist/deno/key/generate_key_pair.ts | 57 + dist/deno/key/generate_secret.ts | 35 + dist/deno/key/import.ts | 193 + dist/deno/lib/aesgcmkw.ts | 30 + dist/deno/lib/buffer_utils.ts | 60 + dist/deno/lib/cek.ts | 21 + dist/deno/lib/check_iv_length.ts | 10 + dist/deno/lib/check_key_type.ts | 74 + dist/deno/lib/check_p2s.ts | 7 + dist/deno/lib/crypto_key.ts | 151 + dist/deno/lib/decrypt_key_management.ts | 141 + dist/deno/lib/encrypt_key_management.ts | 124 + dist/deno/lib/epoch.ts | 1 + dist/deno/lib/format_pem.ts | 4 + dist/deno/lib/invalid_key_input.ts | 30 + dist/deno/lib/is_disjoint.ts | 26 + dist/deno/lib/is_object.ts | 17 + dist/deno/lib/iv.ts | 21 + dist/deno/lib/jwt_claims_set.ts | 139 + dist/deno/lib/secs.ts | 51 + dist/deno/lib/validate_algorithms.ts | 16 + dist/deno/lib/validate_crit.ts | 56 + dist/deno/runtime/aeskw.ts | 56 + dist/deno/runtime/asn1.ts | 268 ++ dist/deno/runtime/base64url.ts | 41 + dist/deno/runtime/bogus.ts | 7 + dist/deno/runtime/check_cek_length.ts | 12 + dist/deno/runtime/check_key_length.ts | 8 + dist/deno/runtime/decrypt.ts | 137 + dist/deno/runtime/digest.ts | 11 + dist/deno/runtime/ecdhes.ts | 72 + dist/deno/runtime/encrypt.ts | 122 + dist/deno/runtime/env.ts | 10 + dist/deno/runtime/fetch_jwks.ts | 43 + dist/deno/runtime/generate.ts | 169 + dist/deno/runtime/get_sign_verify_key.ts | 26 + dist/deno/runtime/interfaces.d.ts | 75 + dist/deno/runtime/is_key_like.ts | 8 + dist/deno/runtime/jwk_to_key.ts | 167 + dist/deno/runtime/key_to_jwk.ts | 25 + dist/deno/runtime/pbes2kw.ts | 78 + dist/deno/runtime/random.ts | 3 + dist/deno/runtime/rsaes.ts | 64 + dist/deno/runtime/sign.ts | 18 + dist/deno/runtime/subtle_dsa.ts | 35 + dist/deno/runtime/subtle_rsaes.ts | 15 + dist/deno/runtime/timing_safe_equal.ts | 23 + dist/deno/runtime/verify.ts | 18 + dist/deno/runtime/webcrypto.ts | 3 + dist/deno/runtime/zlib.ts | 13 + dist/deno/types.d.ts | 628 +++ dist/deno/util/base64url.ts | 21 + dist/deno/util/decode_jwt.ts | 49 + dist/deno/util/decode_protected_header.ts | 48 + dist/deno/util/errors.ts | 185 + dist/node/cjs/index.js | 65 + dist/node/cjs/jwe/compact/decrypt.js | 31 + dist/node/cjs/jwe/compact/encrypt.js | 30 + dist/node/cjs/jwe/flattened/decrypt.js | 141 + dist/node/cjs/jwe/flattened/encrypt.js | 179 + dist/node/cjs/jwe/general/decrypt.js | 35 + dist/node/cjs/jwe/general/encrypt.js | 182 + dist/node/cjs/jwk/embedded.js | 21 + dist/node/cjs/jwk/thumbprint.js | 58 + dist/node/cjs/jwks/local.js | 119 + dist/node/cjs/jwks/remote.js | 85 + dist/node/cjs/jws/compact/sign.js | 21 + dist/node/cjs/jws/compact/verify.js | 25 + dist/node/cjs/jws/flattened/sign.js | 85 + dist/node/cjs/jws/flattened/verify.js | 108 + dist/node/cjs/jws/general/sign.js | 71 + dist/node/cjs/jws/general/verify.js | 28 + dist/node/cjs/jwt/decrypt.js | 27 + dist/node/cjs/jwt/encrypt.js | 72 + dist/node/cjs/jwt/produce.js | 58 + dist/node/cjs/jwt/sign.js | 25 + dist/node/cjs/jwt/unsecured.js | 36 + dist/node/cjs/jwt/verify.js | 20 + dist/node/cjs/key/export.js | 18 + dist/node/cjs/key/generate_key_pair.js | 8 + dist/node/cjs/key/generate_secret.js | 8 + dist/node/cjs/key/import.js | 57 + dist/node/cjs/lib/aesgcmkw.js | 19 + dist/node/cjs/lib/buffer_utils.js | 60 + dist/node/cjs/lib/cek.js | 24 + dist/node/cjs/lib/check_iv_length.js | 10 + dist/node/cjs/lib/check_key_type.js | 47 + dist/node/cjs/lib/check_p2s.js | 9 + dist/node/cjs/lib/crypto_key.js | 163 + dist/node/cjs/lib/decrypt_key_management.js | 100 + dist/node/cjs/lib/encrypt_key_management.js | 89 + dist/node/cjs/lib/epoch.js | 3 + dist/node/cjs/lib/invalid_key_input.js | 34 + dist/node/cjs/lib/is_disjoint.js | 24 + dist/node/cjs/lib/is_object.js | 19 + dist/node/cjs/lib/iv.js | 24 + dist/node/cjs/lib/jwt_claims_set.js | 93 + dist/node/cjs/lib/secs.js | 46 + dist/node/cjs/lib/validate_algorithms.js | 13 + dist/node/cjs/lib/validate_crit.js | 36 + dist/node/cjs/runtime/aeskw.js | 55 + dist/node/cjs/runtime/asn1.js | 54 + .../node/cjs/runtime/asn1_sequence_decoder.js | 47 + .../node/cjs/runtime/asn1_sequence_encoder.js | 91 + dist/node/cjs/runtime/base64url.js | 26 + dist/node/cjs/runtime/cbc_tag.js | 11 + dist/node/cjs/runtime/check_cek_length.js | 37 + dist/node/cjs/runtime/check_modulus_length.js | 52 + dist/node/cjs/runtime/ciphers.js | 8 + dist/node/cjs/runtime/decrypt.js | 97 + dist/node/cjs/runtime/digest.js | 5 + dist/node/cjs/runtime/dsa_digest.js | 25 + dist/node/cjs/runtime/ecdhes.js | 70 + dist/node/cjs/runtime/encrypt.js | 74 + dist/node/cjs/runtime/env.js | 7 + dist/node/cjs/runtime/fetch_jwks.js | 45 + dist/node/cjs/runtime/flags.js | 8 + dist/node/cjs/runtime/generate.js | 105 + dist/node/cjs/runtime/get_named_curve.js | 95 + dist/node/cjs/runtime/get_sign_verify_key.js | 24 + dist/node/cjs/runtime/hmac_digest.js | 16 + dist/node/cjs/runtime/is_key_like.js | 11 + dist/node/cjs/runtime/is_key_object.js | 7 + dist/node/cjs/runtime/jwk_to_key.js | 118 + dist/node/cjs/runtime/key_to_jwk.js | 160 + dist/node/cjs/runtime/node_key.js | 78 + dist/node/cjs/runtime/pbes2kw.js | 48 + dist/node/cjs/runtime/random.js | 5 + dist/node/cjs/runtime/rsaes.js | 69 + dist/node/cjs/runtime/sign.js | 25 + dist/node/cjs/runtime/timing_safe_equal.js | 5 + dist/node/cjs/runtime/verify.js | 38 + dist/node/cjs/runtime/webcrypto.js | 11 + dist/node/cjs/runtime/zlib.js | 11 + dist/node/cjs/util/base64url.js | 6 + dist/node/cjs/util/decode_jwt.js | 36 + dist/node/cjs/util/decode_protected_header.js | 38 + dist/node/cjs/util/errors.js | 166 + dist/node/esm/index.js | 29 + dist/node/esm/jwe/compact/decrypt.js | 27 + dist/node/esm/jwe/compact/encrypt.js | 26 + dist/node/esm/jwe/flattened/decrypt.js | 137 + dist/node/esm/jwe/flattened/encrypt.js | 175 + dist/node/esm/jwe/general/decrypt.js | 31 + dist/node/esm/jwe/general/encrypt.js | 178 + dist/node/esm/jwk/embedded.js | 17 + dist/node/esm/jwk/thumbprint.js | 53 + dist/node/esm/jwks/local.js | 113 + dist/node/esm/jwks/remote.js | 81 + dist/node/esm/jws/compact/sign.js | 17 + dist/node/esm/jws/compact/verify.js | 21 + dist/node/esm/jws/flattened/sign.js | 81 + dist/node/esm/jws/flattened/verify.js | 104 + dist/node/esm/jws/general/sign.js | 67 + dist/node/esm/jws/general/verify.js | 24 + dist/node/esm/jwt/decrypt.js | 23 + dist/node/esm/jwt/encrypt.js | 68 + dist/node/esm/jwt/produce.js | 54 + dist/node/esm/jwt/sign.js | 21 + dist/node/esm/jwt/unsecured.js | 32 + dist/node/esm/jwt/verify.js | 16 + dist/node/esm/key/export.js | 12 + dist/node/esm/key/generate_key_pair.js | 4 + dist/node/esm/key/generate_secret.js | 4 + dist/node/esm/key/import.js | 50 + dist/node/esm/lib/aesgcmkw.js | 14 + dist/node/esm/lib/buffer_utils.js | 51 + dist/node/esm/lib/cek.js | 20 + dist/node/esm/lib/check_iv_length.js | 8 + dist/node/esm/lib/check_key_type.js | 45 + dist/node/esm/lib/check_p2s.js | 6 + dist/node/esm/lib/crypto_key.js | 158 + dist/node/esm/lib/decrypt_key_management.js | 98 + dist/node/esm/lib/encrypt_key_management.js | 87 + dist/node/esm/lib/epoch.js | 1 + dist/node/esm/lib/invalid_key_input.js | 30 + dist/node/esm/lib/is_disjoint.js | 22 + dist/node/esm/lib/is_object.js | 16 + dist/node/esm/lib/iv.js | 20 + dist/node/esm/lib/jwt_claims_set.js | 91 + dist/node/esm/lib/secs.js | 44 + dist/node/esm/lib/validate_algorithms.js | 11 + dist/node/esm/lib/validate_crit.js | 34 + dist/node/esm/package.json | 1 + dist/node/esm/runtime/aeskw.js | 50 + dist/node/esm/runtime/asn1.js | 46 + .../node/esm/runtime/asn1_sequence_decoder.js | 44 + .../node/esm/runtime/asn1_sequence_encoder.js | 88 + dist/node/esm/runtime/base64url.js | 20 + dist/node/esm/runtime/cbc_tag.js | 8 + dist/node/esm/runtime/check_cek_length.js | 35 + dist/node/esm/runtime/check_modulus_length.js | 48 + dist/node/esm/runtime/ciphers.js | 6 + dist/node/esm/runtime/decrypt.js | 95 + dist/node/esm/runtime/digest.js | 3 + dist/node/esm/runtime/dsa_digest.js | 22 + dist/node/esm/runtime/ecdhes.js | 64 + dist/node/esm/runtime/encrypt.js | 72 + dist/node/esm/runtime/env.js | 3 + dist/node/esm/runtime/fetch_jwks.js | 43 + dist/node/esm/runtime/flags.js | 5 + dist/node/esm/runtime/generate.js | 100 + dist/node/esm/runtime/get_named_curve.js | 91 + dist/node/esm/runtime/get_sign_verify_key.js | 21 + dist/node/esm/runtime/hmac_digest.js | 13 + dist/node/esm/runtime/is_key_like.js | 8 + dist/node/esm/runtime/is_key_object.js | 5 + dist/node/esm/runtime/jwk_to_key.js | 116 + dist/node/esm/runtime/key_to_jwk.js | 158 + dist/node/esm/runtime/node_key.js | 75 + dist/node/esm/runtime/pbes2kw.js | 43 + dist/node/esm/runtime/random.js | 1 + dist/node/esm/runtime/rsaes.js | 64 + dist/node/esm/runtime/sign.js | 23 + dist/node/esm/runtime/timing_safe_equal.js | 3 + dist/node/esm/runtime/verify.js | 36 + dist/node/esm/runtime/webcrypto.js | 8 + dist/node/esm/runtime/zlib.js | 6 + dist/node/esm/util/base64url.js | 3 + dist/node/esm/util/decode_jwt.js | 32 + dist/node/esm/util/decode_protected_header.js | 34 + dist/node/esm/util/errors.js | 148 + dist/types/index.d.ts | 47 + dist/types/jwe/compact/decrypt.d.ts | 33 + dist/types/jwe/compact/encrypt.d.ts | 60 + dist/types/jwe/flattened/decrypt.d.ts | 43 + dist/types/jwe/flattened/encrypt.d.ts | 89 + dist/types/jwe/general/decrypt.d.ts | 47 + dist/types/jwe/general/encrypt.d.ts | 74 + dist/types/jwk/embedded.d.ts | 23 + dist/types/jwk/thumbprint.d.ts | 47 + dist/types/jwks/local.d.ts | 85 + dist/types/jwks/remote.d.ts | 92 + dist/types/jws/compact/sign.d.ts | 34 + dist/types/jws/compact/verify.d.ts | 37 + dist/types/jws/flattened/sign.d.ts | 42 + dist/types/jws/flattened/verify.d.ts | 42 + dist/types/jws/general/sign.d.ts | 54 + dist/types/jws/general/verify.d.ts | 45 + dist/types/jwt/decrypt.d.ts | 41 + dist/types/jwt/encrypt.d.ts | 85 + dist/types/jwt/produce.d.ts | 54 + dist/types/jwt/sign.d.ts | 113 + dist/types/jwt/unsecured.d.ts | 44 + dist/types/jwt/verify.d.ts | 108 + dist/types/key/export.d.ts | 47 + dist/types/key/generate_key_pair.d.ts | 44 + dist/types/key/generate_secret.d.ts | 26 + dist/types/key/import.d.ts | 119 + dist/types/types.d.ts | 628 +++ dist/types/util/base64url.d.ts | 19 + dist/types/util/decode_jwt.d.ts | 17 + dist/types/util/decode_protected_header.d.ts | 15 + dist/types/util/errors.d.ts | 99 + docs/README.md | 2 +- package-lock.json | 4 +- package.json | 2 +- 366 files changed, 27889 insertions(+), 5 deletions(-) create mode 100644 dist/browser/index.bundle.js create mode 100644 dist/browser/index.bundle.min.js create mode 100644 dist/browser/index.js create mode 100644 dist/browser/index.umd.js create mode 100644 dist/browser/index.umd.min.js create mode 100644 dist/browser/jwe/compact/decrypt.js create mode 100644 dist/browser/jwe/compact/encrypt.js create mode 100644 dist/browser/jwe/flattened/decrypt.js create mode 100644 dist/browser/jwe/flattened/encrypt.js create mode 100644 dist/browser/jwe/general/decrypt.js create mode 100644 dist/browser/jwe/general/encrypt.js create mode 100644 dist/browser/jwk/embedded.js create mode 100644 dist/browser/jwk/thumbprint.js create mode 100644 dist/browser/jwks/local.js create mode 100644 dist/browser/jwks/remote.js create mode 100644 dist/browser/jws/compact/sign.js create mode 100644 dist/browser/jws/compact/verify.js create mode 100644 dist/browser/jws/flattened/sign.js create mode 100644 dist/browser/jws/flattened/verify.js create mode 100644 dist/browser/jws/general/sign.js create mode 100644 dist/browser/jws/general/verify.js create mode 100644 dist/browser/jwt/decrypt.js create mode 100644 dist/browser/jwt/encrypt.js create mode 100644 dist/browser/jwt/produce.js create mode 100644 dist/browser/jwt/sign.js create mode 100644 dist/browser/jwt/unsecured.js create mode 100644 dist/browser/jwt/verify.js create mode 100644 dist/browser/key/export.js create mode 100644 dist/browser/key/generate_key_pair.js create mode 100644 dist/browser/key/generate_secret.js create mode 100644 dist/browser/key/import.js create mode 100644 dist/browser/lib/aesgcmkw.js create mode 100644 dist/browser/lib/buffer_utils.js create mode 100644 dist/browser/lib/cek.js create mode 100644 dist/browser/lib/check_iv_length.js create mode 100644 dist/browser/lib/check_key_type.js create mode 100644 dist/browser/lib/check_p2s.js create mode 100644 dist/browser/lib/crypto_key.js create mode 100644 dist/browser/lib/decrypt_key_management.js create mode 100644 dist/browser/lib/encrypt_key_management.js create mode 100644 dist/browser/lib/epoch.js create mode 100644 dist/browser/lib/format_pem.js create mode 100644 dist/browser/lib/invalid_key_input.js create mode 100644 dist/browser/lib/is_disjoint.js create mode 100644 dist/browser/lib/is_object.js create mode 100644 dist/browser/lib/iv.js create mode 100644 dist/browser/lib/jwt_claims_set.js create mode 100644 dist/browser/lib/secs.js create mode 100644 dist/browser/lib/validate_algorithms.js create mode 100644 dist/browser/lib/validate_crit.js create mode 100644 dist/browser/package.json create mode 100644 dist/browser/runtime/aeskw.js create mode 100644 dist/browser/runtime/asn1.js create mode 100644 dist/browser/runtime/base64url.js create mode 100644 dist/browser/runtime/bogus.js create mode 100644 dist/browser/runtime/check_cek_length.js create mode 100644 dist/browser/runtime/check_key_length.js create mode 100644 dist/browser/runtime/decrypt.js create mode 100644 dist/browser/runtime/digest.js create mode 100644 dist/browser/runtime/ecdhes.js create mode 100644 dist/browser/runtime/encrypt.js create mode 100644 dist/browser/runtime/env.js create mode 100644 dist/browser/runtime/fetch_jwks.js create mode 100644 dist/browser/runtime/generate.js create mode 100644 dist/browser/runtime/get_sign_verify_key.js create mode 100644 dist/browser/runtime/is_key_like.js create mode 100644 dist/browser/runtime/jwk_to_key.js create mode 100644 dist/browser/runtime/key_to_jwk.js create mode 100644 dist/browser/runtime/pbes2kw.js create mode 100644 dist/browser/runtime/random.js create mode 100644 dist/browser/runtime/rsaes.js create mode 100644 dist/browser/runtime/sign.js create mode 100644 dist/browser/runtime/subtle_dsa.js create mode 100644 dist/browser/runtime/subtle_rsaes.js create mode 100644 dist/browser/runtime/timing_safe_equal.js create mode 100644 dist/browser/runtime/verify.js create mode 100644 dist/browser/runtime/webcrypto.js create mode 100644 dist/browser/runtime/zlib.js create mode 100644 dist/browser/util/base64url.js create mode 100644 dist/browser/util/decode_jwt.js create mode 100644 dist/browser/util/decode_protected_header.js create mode 100644 dist/browser/util/errors.js create mode 100644 dist/deno/README.md create mode 100644 dist/deno/index.ts create mode 100644 dist/deno/jwe/compact/decrypt.ts create mode 100644 dist/deno/jwe/compact/encrypt.ts create mode 100644 dist/deno/jwe/flattened/decrypt.ts create mode 100644 dist/deno/jwe/flattened/encrypt.ts create mode 100644 dist/deno/jwe/general/decrypt.ts create mode 100644 dist/deno/jwe/general/encrypt.ts create mode 100644 dist/deno/jwk/embedded.ts create mode 100644 dist/deno/jwk/thumbprint.ts create mode 100644 dist/deno/jwks/local.ts create mode 100644 dist/deno/jwks/remote.ts create mode 100644 dist/deno/jws/compact/sign.ts create mode 100644 dist/deno/jws/compact/verify.ts create mode 100644 dist/deno/jws/flattened/sign.ts create mode 100644 dist/deno/jws/flattened/verify.ts create mode 100644 dist/deno/jws/general/sign.ts create mode 100644 dist/deno/jws/general/verify.ts create mode 100644 dist/deno/jwt/decrypt.ts create mode 100644 dist/deno/jwt/encrypt.ts create mode 100644 dist/deno/jwt/produce.ts create mode 100644 dist/deno/jwt/sign.ts create mode 100644 dist/deno/jwt/unsecured.ts create mode 100644 dist/deno/jwt/verify.ts create mode 100644 dist/deno/key/export.ts create mode 100644 dist/deno/key/generate_key_pair.ts create mode 100644 dist/deno/key/generate_secret.ts create mode 100644 dist/deno/key/import.ts create mode 100644 dist/deno/lib/aesgcmkw.ts create mode 100644 dist/deno/lib/buffer_utils.ts create mode 100644 dist/deno/lib/cek.ts create mode 100644 dist/deno/lib/check_iv_length.ts create mode 100644 dist/deno/lib/check_key_type.ts create mode 100644 dist/deno/lib/check_p2s.ts create mode 100644 dist/deno/lib/crypto_key.ts create mode 100644 dist/deno/lib/decrypt_key_management.ts create mode 100644 dist/deno/lib/encrypt_key_management.ts create mode 100644 dist/deno/lib/epoch.ts create mode 100644 dist/deno/lib/format_pem.ts create mode 100644 dist/deno/lib/invalid_key_input.ts create mode 100644 dist/deno/lib/is_disjoint.ts create mode 100644 dist/deno/lib/is_object.ts create mode 100644 dist/deno/lib/iv.ts create mode 100644 dist/deno/lib/jwt_claims_set.ts create mode 100644 dist/deno/lib/secs.ts create mode 100644 dist/deno/lib/validate_algorithms.ts create mode 100644 dist/deno/lib/validate_crit.ts create mode 100644 dist/deno/runtime/aeskw.ts create mode 100644 dist/deno/runtime/asn1.ts create mode 100644 dist/deno/runtime/base64url.ts create mode 100644 dist/deno/runtime/bogus.ts create mode 100644 dist/deno/runtime/check_cek_length.ts create mode 100644 dist/deno/runtime/check_key_length.ts create mode 100644 dist/deno/runtime/decrypt.ts create mode 100644 dist/deno/runtime/digest.ts create mode 100644 dist/deno/runtime/ecdhes.ts create mode 100644 dist/deno/runtime/encrypt.ts create mode 100644 dist/deno/runtime/env.ts create mode 100644 dist/deno/runtime/fetch_jwks.ts create mode 100644 dist/deno/runtime/generate.ts create mode 100644 dist/deno/runtime/get_sign_verify_key.ts create mode 100644 dist/deno/runtime/interfaces.d.ts create mode 100644 dist/deno/runtime/is_key_like.ts create mode 100644 dist/deno/runtime/jwk_to_key.ts create mode 100644 dist/deno/runtime/key_to_jwk.ts create mode 100644 dist/deno/runtime/pbes2kw.ts create mode 100644 dist/deno/runtime/random.ts create mode 100644 dist/deno/runtime/rsaes.ts create mode 100644 dist/deno/runtime/sign.ts create mode 100644 dist/deno/runtime/subtle_dsa.ts create mode 100644 dist/deno/runtime/subtle_rsaes.ts create mode 100644 dist/deno/runtime/timing_safe_equal.ts create mode 100644 dist/deno/runtime/verify.ts create mode 100644 dist/deno/runtime/webcrypto.ts create mode 100644 dist/deno/runtime/zlib.ts create mode 100644 dist/deno/types.d.ts create mode 100644 dist/deno/util/base64url.ts create mode 100644 dist/deno/util/decode_jwt.ts create mode 100644 dist/deno/util/decode_protected_header.ts create mode 100644 dist/deno/util/errors.ts create mode 100644 dist/node/cjs/index.js create mode 100644 dist/node/cjs/jwe/compact/decrypt.js create mode 100644 dist/node/cjs/jwe/compact/encrypt.js create mode 100644 dist/node/cjs/jwe/flattened/decrypt.js create mode 100644 dist/node/cjs/jwe/flattened/encrypt.js create mode 100644 dist/node/cjs/jwe/general/decrypt.js create mode 100644 dist/node/cjs/jwe/general/encrypt.js create mode 100644 dist/node/cjs/jwk/embedded.js create mode 100644 dist/node/cjs/jwk/thumbprint.js create mode 100644 dist/node/cjs/jwks/local.js create mode 100644 dist/node/cjs/jwks/remote.js create mode 100644 dist/node/cjs/jws/compact/sign.js create mode 100644 dist/node/cjs/jws/compact/verify.js create mode 100644 dist/node/cjs/jws/flattened/sign.js create mode 100644 dist/node/cjs/jws/flattened/verify.js create mode 100644 dist/node/cjs/jws/general/sign.js create mode 100644 dist/node/cjs/jws/general/verify.js create mode 100644 dist/node/cjs/jwt/decrypt.js create mode 100644 dist/node/cjs/jwt/encrypt.js create mode 100644 dist/node/cjs/jwt/produce.js create mode 100644 dist/node/cjs/jwt/sign.js create mode 100644 dist/node/cjs/jwt/unsecured.js create mode 100644 dist/node/cjs/jwt/verify.js create mode 100644 dist/node/cjs/key/export.js create mode 100644 dist/node/cjs/key/generate_key_pair.js create mode 100644 dist/node/cjs/key/generate_secret.js create mode 100644 dist/node/cjs/key/import.js create mode 100644 dist/node/cjs/lib/aesgcmkw.js create mode 100644 dist/node/cjs/lib/buffer_utils.js create mode 100644 dist/node/cjs/lib/cek.js create mode 100644 dist/node/cjs/lib/check_iv_length.js create mode 100644 dist/node/cjs/lib/check_key_type.js create mode 100644 dist/node/cjs/lib/check_p2s.js create mode 100644 dist/node/cjs/lib/crypto_key.js create mode 100644 dist/node/cjs/lib/decrypt_key_management.js create mode 100644 dist/node/cjs/lib/encrypt_key_management.js create mode 100644 dist/node/cjs/lib/epoch.js create mode 100644 dist/node/cjs/lib/invalid_key_input.js create mode 100644 dist/node/cjs/lib/is_disjoint.js create mode 100644 dist/node/cjs/lib/is_object.js create mode 100644 dist/node/cjs/lib/iv.js create mode 100644 dist/node/cjs/lib/jwt_claims_set.js create mode 100644 dist/node/cjs/lib/secs.js create mode 100644 dist/node/cjs/lib/validate_algorithms.js create mode 100644 dist/node/cjs/lib/validate_crit.js create mode 100644 dist/node/cjs/runtime/aeskw.js create mode 100644 dist/node/cjs/runtime/asn1.js create mode 100644 dist/node/cjs/runtime/asn1_sequence_decoder.js create mode 100644 dist/node/cjs/runtime/asn1_sequence_encoder.js create mode 100644 dist/node/cjs/runtime/base64url.js create mode 100644 dist/node/cjs/runtime/cbc_tag.js create mode 100644 dist/node/cjs/runtime/check_cek_length.js create mode 100644 dist/node/cjs/runtime/check_modulus_length.js create mode 100644 dist/node/cjs/runtime/ciphers.js create mode 100644 dist/node/cjs/runtime/decrypt.js create mode 100644 dist/node/cjs/runtime/digest.js create mode 100644 dist/node/cjs/runtime/dsa_digest.js create mode 100644 dist/node/cjs/runtime/ecdhes.js create mode 100644 dist/node/cjs/runtime/encrypt.js create mode 100644 dist/node/cjs/runtime/env.js create mode 100644 dist/node/cjs/runtime/fetch_jwks.js create mode 100644 dist/node/cjs/runtime/flags.js create mode 100644 dist/node/cjs/runtime/generate.js create mode 100644 dist/node/cjs/runtime/get_named_curve.js create mode 100644 dist/node/cjs/runtime/get_sign_verify_key.js create mode 100644 dist/node/cjs/runtime/hmac_digest.js create mode 100644 dist/node/cjs/runtime/is_key_like.js create mode 100644 dist/node/cjs/runtime/is_key_object.js create mode 100644 dist/node/cjs/runtime/jwk_to_key.js create mode 100644 dist/node/cjs/runtime/key_to_jwk.js create mode 100644 dist/node/cjs/runtime/node_key.js create mode 100644 dist/node/cjs/runtime/pbes2kw.js create mode 100644 dist/node/cjs/runtime/random.js create mode 100644 dist/node/cjs/runtime/rsaes.js create mode 100644 dist/node/cjs/runtime/sign.js create mode 100644 dist/node/cjs/runtime/timing_safe_equal.js create mode 100644 dist/node/cjs/runtime/verify.js create mode 100644 dist/node/cjs/runtime/webcrypto.js create mode 100644 dist/node/cjs/runtime/zlib.js create mode 100644 dist/node/cjs/util/base64url.js create mode 100644 dist/node/cjs/util/decode_jwt.js create mode 100644 dist/node/cjs/util/decode_protected_header.js create mode 100644 dist/node/cjs/util/errors.js create mode 100644 dist/node/esm/index.js create mode 100644 dist/node/esm/jwe/compact/decrypt.js create mode 100644 dist/node/esm/jwe/compact/encrypt.js create mode 100644 dist/node/esm/jwe/flattened/decrypt.js create mode 100644 dist/node/esm/jwe/flattened/encrypt.js create mode 100644 dist/node/esm/jwe/general/decrypt.js create mode 100644 dist/node/esm/jwe/general/encrypt.js create mode 100644 dist/node/esm/jwk/embedded.js create mode 100644 dist/node/esm/jwk/thumbprint.js create mode 100644 dist/node/esm/jwks/local.js create mode 100644 dist/node/esm/jwks/remote.js create mode 100644 dist/node/esm/jws/compact/sign.js create mode 100644 dist/node/esm/jws/compact/verify.js create mode 100644 dist/node/esm/jws/flattened/sign.js create mode 100644 dist/node/esm/jws/flattened/verify.js create mode 100644 dist/node/esm/jws/general/sign.js create mode 100644 dist/node/esm/jws/general/verify.js create mode 100644 dist/node/esm/jwt/decrypt.js create mode 100644 dist/node/esm/jwt/encrypt.js create mode 100644 dist/node/esm/jwt/produce.js create mode 100644 dist/node/esm/jwt/sign.js create mode 100644 dist/node/esm/jwt/unsecured.js create mode 100644 dist/node/esm/jwt/verify.js create mode 100644 dist/node/esm/key/export.js create mode 100644 dist/node/esm/key/generate_key_pair.js create mode 100644 dist/node/esm/key/generate_secret.js create mode 100644 dist/node/esm/key/import.js create mode 100644 dist/node/esm/lib/aesgcmkw.js create mode 100644 dist/node/esm/lib/buffer_utils.js create mode 100644 dist/node/esm/lib/cek.js create mode 100644 dist/node/esm/lib/check_iv_length.js create mode 100644 dist/node/esm/lib/check_key_type.js create mode 100644 dist/node/esm/lib/check_p2s.js create mode 100644 dist/node/esm/lib/crypto_key.js create mode 100644 dist/node/esm/lib/decrypt_key_management.js create mode 100644 dist/node/esm/lib/encrypt_key_management.js create mode 100644 dist/node/esm/lib/epoch.js create mode 100644 dist/node/esm/lib/invalid_key_input.js create mode 100644 dist/node/esm/lib/is_disjoint.js create mode 100644 dist/node/esm/lib/is_object.js create mode 100644 dist/node/esm/lib/iv.js create mode 100644 dist/node/esm/lib/jwt_claims_set.js create mode 100644 dist/node/esm/lib/secs.js create mode 100644 dist/node/esm/lib/validate_algorithms.js create mode 100644 dist/node/esm/lib/validate_crit.js create mode 100644 dist/node/esm/package.json create mode 100644 dist/node/esm/runtime/aeskw.js create mode 100644 dist/node/esm/runtime/asn1.js create mode 100644 dist/node/esm/runtime/asn1_sequence_decoder.js create mode 100644 dist/node/esm/runtime/asn1_sequence_encoder.js create mode 100644 dist/node/esm/runtime/base64url.js create mode 100644 dist/node/esm/runtime/cbc_tag.js create mode 100644 dist/node/esm/runtime/check_cek_length.js create mode 100644 dist/node/esm/runtime/check_modulus_length.js create mode 100644 dist/node/esm/runtime/ciphers.js create mode 100644 dist/node/esm/runtime/decrypt.js create mode 100644 dist/node/esm/runtime/digest.js create mode 100644 dist/node/esm/runtime/dsa_digest.js create mode 100644 dist/node/esm/runtime/ecdhes.js create mode 100644 dist/node/esm/runtime/encrypt.js create mode 100644 dist/node/esm/runtime/env.js create mode 100644 dist/node/esm/runtime/fetch_jwks.js create mode 100644 dist/node/esm/runtime/flags.js create mode 100644 dist/node/esm/runtime/generate.js create mode 100644 dist/node/esm/runtime/get_named_curve.js create mode 100644 dist/node/esm/runtime/get_sign_verify_key.js create mode 100644 dist/node/esm/runtime/hmac_digest.js create mode 100644 dist/node/esm/runtime/is_key_like.js create mode 100644 dist/node/esm/runtime/is_key_object.js create mode 100644 dist/node/esm/runtime/jwk_to_key.js create mode 100644 dist/node/esm/runtime/key_to_jwk.js create mode 100644 dist/node/esm/runtime/node_key.js create mode 100644 dist/node/esm/runtime/pbes2kw.js create mode 100644 dist/node/esm/runtime/random.js create mode 100644 dist/node/esm/runtime/rsaes.js create mode 100644 dist/node/esm/runtime/sign.js create mode 100644 dist/node/esm/runtime/timing_safe_equal.js create mode 100644 dist/node/esm/runtime/verify.js create mode 100644 dist/node/esm/runtime/webcrypto.js create mode 100644 dist/node/esm/runtime/zlib.js create mode 100644 dist/node/esm/util/base64url.js create mode 100644 dist/node/esm/util/decode_jwt.js create mode 100644 dist/node/esm/util/decode_protected_header.js create mode 100644 dist/node/esm/util/errors.js create mode 100644 dist/types/index.d.ts create mode 100644 dist/types/jwe/compact/decrypt.d.ts create mode 100644 dist/types/jwe/compact/encrypt.d.ts create mode 100644 dist/types/jwe/flattened/decrypt.d.ts create mode 100644 dist/types/jwe/flattened/encrypt.d.ts create mode 100644 dist/types/jwe/general/decrypt.d.ts create mode 100644 dist/types/jwe/general/encrypt.d.ts create mode 100644 dist/types/jwk/embedded.d.ts create mode 100644 dist/types/jwk/thumbprint.d.ts create mode 100644 dist/types/jwks/local.d.ts create mode 100644 dist/types/jwks/remote.d.ts create mode 100644 dist/types/jws/compact/sign.d.ts create mode 100644 dist/types/jws/compact/verify.d.ts create mode 100644 dist/types/jws/flattened/sign.d.ts create mode 100644 dist/types/jws/flattened/verify.d.ts create mode 100644 dist/types/jws/general/sign.d.ts create mode 100644 dist/types/jws/general/verify.d.ts create mode 100644 dist/types/jwt/decrypt.d.ts create mode 100644 dist/types/jwt/encrypt.d.ts create mode 100644 dist/types/jwt/produce.d.ts create mode 100644 dist/types/jwt/sign.d.ts create mode 100644 dist/types/jwt/unsecured.d.ts create mode 100644 dist/types/jwt/verify.d.ts create mode 100644 dist/types/key/export.d.ts create mode 100644 dist/types/key/generate_key_pair.d.ts create mode 100644 dist/types/key/generate_secret.d.ts create mode 100644 dist/types/key/import.d.ts create mode 100644 dist/types/types.d.ts create mode 100644 dist/types/util/base64url.d.ts create mode 100644 dist/types/util/decode_jwt.d.ts create mode 100644 dist/types/util/decode_protected_header.d.ts create mode 100644 dist/types/util/errors.d.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index c8f7eb023c..6050abc14a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [4.12.2](https://github.com/panva/jose/compare/v4.12.1...v4.12.2) (2023-02-27) + + +### Fixes + +* **types:** declare explicit return from EmbeddedJWK ([46934ac](https://github.com/panva/jose/commit/46934ac474ba0119976c5ac15cce4ea7bf50de8c)) + ## [4.12.1](https://github.com/panva/jose/compare/v4.12.0...v4.12.1) (2023-02-27) diff --git a/README.md b/README.md index c6ccb86f89..2fec0c18d4 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ const jose = require('jose') **`example`** Deno import ```js -import * as jose from 'https://deno.land/x/jose@v4.12.1/index.ts' +import * as jose from 'https://deno.land/x/jose@v4.12.2/index.ts' ``` - JSON Web Tokens (JWT) diff --git a/dist/browser/index.bundle.js b/dist/browser/index.bundle.js new file mode 100644 index 0000000000..d083427e5b --- /dev/null +++ b/dist/browser/index.bundle.js @@ -0,0 +1,3368 @@ +var __defProp = Object.defineProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; + +// dist/browser/runtime/webcrypto.js +var webcrypto_default = crypto; +var isCryptoKey = (key) => key instanceof CryptoKey; + +// dist/browser/runtime/digest.js +var digest = async (algorithm, data) => { + const subtleDigest = `SHA-${algorithm.slice(-3)}`; + return new Uint8Array(await webcrypto_default.subtle.digest(subtleDigest, data)); +}; +var digest_default = digest; + +// dist/browser/lib/buffer_utils.js +var encoder = new TextEncoder(); +var decoder = new TextDecoder(); +var MAX_INT32 = 2 ** 32; +function concat(...buffers) { + const size = buffers.reduce((acc, { length }) => acc + length, 0); + const buf = new Uint8Array(size); + let i = 0; + buffers.forEach((buffer) => { + buf.set(buffer, i); + i += buffer.length; + }); + return buf; +} +function p2s(alg, p2sInput) { + return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); +} +function writeUInt32BE(buf, value, offset) { + if (value < 0 || value >= MAX_INT32) { + throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); + } + buf.set([value >>> 24, value >>> 16, value >>> 8, value & 255], offset); +} +function uint64be(value) { + const high = Math.floor(value / MAX_INT32); + const low = value % MAX_INT32; + const buf = new Uint8Array(8); + writeUInt32BE(buf, high, 0); + writeUInt32BE(buf, low, 4); + return buf; +} +function uint32be(value) { + const buf = new Uint8Array(4); + writeUInt32BE(buf, value); + return buf; +} +function lengthAndInput(input) { + return concat(uint32be(input.length), input); +} +async function concatKdf(secret, bits, value) { + const iterations = Math.ceil((bits >> 3) / 32); + const res = new Uint8Array(iterations * 32); + for (let iter = 0; iter < iterations; iter++) { + const buf = new Uint8Array(4 + secret.length + value.length); + buf.set(uint32be(iter + 1)); + buf.set(secret, 4); + buf.set(value, 4 + secret.length); + res.set(await digest_default("sha256", buf), iter * 32); + } + return res.slice(0, bits >> 3); +} + +// dist/browser/runtime/base64url.js +var encodeBase64 = (input) => { + let unencoded = input; + if (typeof unencoded === "string") { + unencoded = encoder.encode(unencoded); + } + const CHUNK_SIZE = 32768; + const arr = []; + for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { + arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))); + } + return btoa(arr.join("")); +}; +var encode = (input) => { + return encodeBase64(input).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); +}; +var decodeBase64 = (encoded) => { + const binary = atob(encoded); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i); + } + return bytes; +}; +var decode = (input) => { + let encoded = input; + if (encoded instanceof Uint8Array) { + encoded = decoder.decode(encoded); + } + encoded = encoded.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""); + try { + return decodeBase64(encoded); + } catch (_a) { + throw new TypeError("The input to be decoded is not correctly encoded."); + } +}; + +// dist/browser/util/errors.js +var errors_exports = {}; +__export(errors_exports, { + JOSEAlgNotAllowed: () => JOSEAlgNotAllowed, + JOSEError: () => JOSEError, + JOSENotSupported: () => JOSENotSupported, + JWEDecryptionFailed: () => JWEDecryptionFailed, + JWEInvalid: () => JWEInvalid, + JWKInvalid: () => JWKInvalid, + JWKSInvalid: () => JWKSInvalid, + JWKSMultipleMatchingKeys: () => JWKSMultipleMatchingKeys, + JWKSNoMatchingKey: () => JWKSNoMatchingKey, + JWKSTimeout: () => JWKSTimeout, + JWSInvalid: () => JWSInvalid, + JWSSignatureVerificationFailed: () => JWSSignatureVerificationFailed, + JWTClaimValidationFailed: () => JWTClaimValidationFailed, + JWTExpired: () => JWTExpired, + JWTInvalid: () => JWTInvalid +}); +var JOSEError = class extends Error { + static get code() { + return "ERR_JOSE_GENERIC"; + } + constructor(message2) { + var _a; + super(message2); + this.code = "ERR_JOSE_GENERIC"; + this.name = this.constructor.name; + (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); + } +}; +var JWTClaimValidationFailed = class extends JOSEError { + static get code() { + return "ERR_JWT_CLAIM_VALIDATION_FAILED"; + } + constructor(message2, claim = "unspecified", reason = "unspecified") { + super(message2); + this.code = "ERR_JWT_CLAIM_VALIDATION_FAILED"; + this.claim = claim; + this.reason = reason; + } +}; +var JWTExpired = class extends JOSEError { + static get code() { + return "ERR_JWT_EXPIRED"; + } + constructor(message2, claim = "unspecified", reason = "unspecified") { + super(message2); + this.code = "ERR_JWT_EXPIRED"; + this.claim = claim; + this.reason = reason; + } +}; +var JOSEAlgNotAllowed = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JOSE_ALG_NOT_ALLOWED"; + } + static get code() { + return "ERR_JOSE_ALG_NOT_ALLOWED"; + } +}; +var JOSENotSupported = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JOSE_NOT_SUPPORTED"; + } + static get code() { + return "ERR_JOSE_NOT_SUPPORTED"; + } +}; +var JWEDecryptionFailed = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWE_DECRYPTION_FAILED"; + this.message = "decryption operation failed"; + } + static get code() { + return "ERR_JWE_DECRYPTION_FAILED"; + } +}; +var JWEInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWE_INVALID"; + } + static get code() { + return "ERR_JWE_INVALID"; + } +}; +var JWSInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWS_INVALID"; + } + static get code() { + return "ERR_JWS_INVALID"; + } +}; +var JWTInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWT_INVALID"; + } + static get code() { + return "ERR_JWT_INVALID"; + } +}; +var JWKInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWK_INVALID"; + } + static get code() { + return "ERR_JWK_INVALID"; + } +}; +var JWKSInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_INVALID"; + } + static get code() { + return "ERR_JWKS_INVALID"; + } +}; +var JWKSNoMatchingKey = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_NO_MATCHING_KEY"; + this.message = "no applicable key found in the JSON Web Key Set"; + } + static get code() { + return "ERR_JWKS_NO_MATCHING_KEY"; + } +}; +var JWKSMultipleMatchingKeys = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; + this.message = "multiple matching keys found in the JSON Web Key Set"; + } + static get code() { + return "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; + } +}; +var JWKSTimeout = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_TIMEOUT"; + this.message = "request timed out"; + } + static get code() { + return "ERR_JWKS_TIMEOUT"; + } +}; +var JWSSignatureVerificationFailed = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; + this.message = "signature verification failed"; + } + static get code() { + return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; + } +}; + +// dist/browser/runtime/random.js +var random_default = webcrypto_default.getRandomValues.bind(webcrypto_default); + +// dist/browser/lib/iv.js +function bitLength(alg) { + switch (alg) { + case "A128GCM": + case "A128GCMKW": + case "A192GCM": + case "A192GCMKW": + case "A256GCM": + case "A256GCMKW": + return 96; + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + return 128; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +var iv_default = (alg) => random_default(new Uint8Array(bitLength(alg) >> 3)); + +// dist/browser/lib/check_iv_length.js +var checkIvLength = (enc, iv) => { + if (iv.length << 3 !== bitLength(enc)) { + throw new JWEInvalid("Invalid Initialization Vector length"); + } +}; +var check_iv_length_default = checkIvLength; + +// dist/browser/runtime/check_cek_length.js +var checkCekLength = (cek, expected) => { + const actual = cek.byteLength << 3; + if (actual !== expected) { + throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); + } +}; +var check_cek_length_default = checkCekLength; + +// dist/browser/runtime/timing_safe_equal.js +var timingSafeEqual = (a, b) => { + if (!(a instanceof Uint8Array)) { + throw new TypeError("First argument must be a buffer"); + } + if (!(b instanceof Uint8Array)) { + throw new TypeError("Second argument must be a buffer"); + } + if (a.length !== b.length) { + throw new TypeError("Input buffers must have the same length"); + } + const len = a.length; + let out = 0; + let i = -1; + while (++i < len) { + out |= a[i] ^ b[i]; + } + return out === 0; +}; +var timing_safe_equal_default = timingSafeEqual; + +// dist/browser/runtime/env.js +function isCloudflareWorkers() { + return typeof WebSocketPair !== "undefined" || typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime !== "undefined" && EdgeRuntime === "vercel"; +} + +// dist/browser/lib/crypto_key.js +function unusable(name, prop = "algorithm.name") { + return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); +} +function isAlgorithm(algorithm, name) { + return algorithm.name === name; +} +function getHashLength(hash) { + return parseInt(hash.name.slice(4), 10); +} +function getNamedCurve(alg) { + switch (alg) { + case "ES256": + return "P-256"; + case "ES384": + return "P-384"; + case "ES512": + return "P-521"; + default: + throw new Error("unreachable"); + } +} +function checkUsage(key, usages) { + if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { + let msg = "CryptoKey does not support this operation, its usages must include "; + if (usages.length > 2) { + const last = usages.pop(); + msg += `one of ${usages.join(", ")}, or ${last}.`; + } else if (usages.length === 2) { + msg += `one of ${usages[0]} or ${usages[1]}.`; + } else { + msg += `${usages[0]}.`; + } + throw new TypeError(msg); + } +} +function checkSigCryptoKey(key, alg, ...usages) { + switch (alg) { + case "HS256": + case "HS384": + case "HS512": { + if (!isAlgorithm(key.algorithm, "HMAC")) + throw unusable("HMAC"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "RS256": + case "RS384": + case "RS512": { + if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5")) + throw unusable("RSASSA-PKCS1-v1_5"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "PS256": + case "PS384": + case "PS512": { + if (!isAlgorithm(key.algorithm, "RSA-PSS")) + throw unusable("RSA-PSS"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "EdDSA": { + if (key.algorithm.name !== "Ed25519" && key.algorithm.name !== "Ed448") { + if (isCloudflareWorkers()) { + if (isAlgorithm(key.algorithm, "NODE-ED25519")) + break; + throw unusable("Ed25519, Ed448, or NODE-ED25519"); + } + throw unusable("Ed25519 or Ed448"); + } + break; + } + case "ES256": + case "ES384": + case "ES512": { + if (!isAlgorithm(key.algorithm, "ECDSA")) + throw unusable("ECDSA"); + const expected = getNamedCurve(alg); + const actual = key.algorithm.namedCurve; + if (actual !== expected) + throw unusable(expected, "algorithm.namedCurve"); + break; + } + default: + throw new TypeError("CryptoKey does not support this operation"); + } + checkUsage(key, usages); +} +function checkEncCryptoKey(key, alg, ...usages) { + switch (alg) { + case "A128GCM": + case "A192GCM": + case "A256GCM": { + if (!isAlgorithm(key.algorithm, "AES-GCM")) + throw unusable("AES-GCM"); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, "algorithm.length"); + break; + } + case "A128KW": + case "A192KW": + case "A256KW": { + if (!isAlgorithm(key.algorithm, "AES-KW")) + throw unusable("AES-KW"); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, "algorithm.length"); + break; + } + case "ECDH": { + switch (key.algorithm.name) { + case "ECDH": + case "X25519": + case "X448": + break; + default: + throw unusable("ECDH, X25519, or X448"); + } + break; + } + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": + if (!isAlgorithm(key.algorithm, "PBKDF2")) + throw unusable("PBKDF2"); + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": { + if (!isAlgorithm(key.algorithm, "RSA-OAEP")) + throw unusable("RSA-OAEP"); + const expected = parseInt(alg.slice(9), 10) || 1; + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + default: + throw new TypeError("CryptoKey does not support this operation"); + } + checkUsage(key, usages); +} + +// dist/browser/lib/invalid_key_input.js +function message(msg, actual, ...types2) { + if (types2.length > 2) { + const last = types2.pop(); + msg += `one of type ${types2.join(", ")}, or ${last}.`; + } else if (types2.length === 2) { + msg += `one of type ${types2[0]} or ${types2[1]}.`; + } else { + msg += `of type ${types2[0]}.`; + } + if (actual == null) { + msg += ` Received ${actual}`; + } else if (typeof actual === "function" && actual.name) { + msg += ` Received function ${actual.name}`; + } else if (typeof actual === "object" && actual != null) { + if (actual.constructor && actual.constructor.name) { + msg += ` Received an instance of ${actual.constructor.name}`; + } + } + return msg; +} +var invalid_key_input_default = (actual, ...types2) => { + return message("Key must be ", actual, ...types2); +}; +function withAlg(alg, actual, ...types2) { + return message(`Key for the ${alg} algorithm must be `, actual, ...types2); +} + +// dist/browser/runtime/is_key_like.js +var is_key_like_default = (key) => { + return isCryptoKey(key); +}; +var types = ["CryptoKey"]; + +// dist/browser/runtime/decrypt.js +async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); + } + const keySize = parseInt(enc.slice(1, 4), 10); + const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["decrypt"]); + const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { + hash: `SHA-${keySize << 1}`, + name: "HMAC" + }, false, ["sign"]); + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); + const expectedTag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); + let macCheckPassed; + try { + macCheckPassed = timing_safe_equal_default(tag, expectedTag); + } catch (_a) { + } + if (!macCheckPassed) { + throw new JWEDecryptionFailed(); + } + let plaintext; + try { + plaintext = new Uint8Array(await webcrypto_default.subtle.decrypt({ iv, name: "AES-CBC" }, encKey, ciphertext)); + } catch (_b) { + } + if (!plaintext) { + throw new JWEDecryptionFailed(); + } + return plaintext; +} +async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { + let encKey; + if (cek instanceof Uint8Array) { + encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["decrypt"]); + } else { + checkEncCryptoKey(cek, enc, "decrypt"); + encKey = cek; + } + try { + return new Uint8Array(await webcrypto_default.subtle.decrypt({ + additionalData: aad, + iv, + name: "AES-GCM", + tagLength: 128 + }, encKey, concat(ciphertext, tag))); + } catch (_a) { + throw new JWEDecryptionFailed(); + } +} +var decrypt = async (enc, cek, ciphertext, iv, tag, aad) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); + } + check_iv_length_default(enc, iv); + switch (enc) { + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); + return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad); + case "A128GCM": + case "A192GCM": + case "A256GCM": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); + return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); + default: + throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); + } +}; +var decrypt_default = decrypt; + +// dist/browser/runtime/zlib.js +var inflate = async () => { + throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.'); +}; +var deflate = async () => { + throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.'); +}; + +// dist/browser/lib/is_disjoint.js +var isDisjoint = (...headers) => { + const sources = headers.filter(Boolean); + if (sources.length === 0 || sources.length === 1) { + return true; + } + let acc; + for (const header of sources) { + const parameters = Object.keys(header); + if (!acc || acc.size === 0) { + acc = new Set(parameters); + continue; + } + for (const parameter of parameters) { + if (acc.has(parameter)) { + return false; + } + acc.add(parameter); + } + } + return true; +}; +var is_disjoint_default = isDisjoint; + +// dist/browser/lib/is_object.js +function isObjectLike(value) { + return typeof value === "object" && value !== null; +} +function isObject(input) { + if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") { + return false; + } + if (Object.getPrototypeOf(input) === null) { + return true; + } + let proto = input; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + return Object.getPrototypeOf(input) === proto; +} + +// dist/browser/runtime/bogus.js +var bogusWebCrypto = [ + { hash: "SHA-256", name: "HMAC" }, + true, + ["sign"] +]; +var bogus_default = bogusWebCrypto; + +// dist/browser/runtime/aeskw.js +function checkKeySize(key, alg) { + if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) { + throw new TypeError(`Invalid key size for alg: ${alg}`); + } +} +function getCryptoKey(key, alg, usage) { + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, usage); + return key; + } + if (key instanceof Uint8Array) { + return webcrypto_default.subtle.importKey("raw", key, "AES-KW", true, [usage]); + } + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); +} +var wrap = async (alg, key, cek) => { + const cryptoKey = await getCryptoKey(key, alg, "wrapKey"); + checkKeySize(cryptoKey, alg); + const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, cryptoKey, "AES-KW")); +}; +var unwrap = async (alg, key, encryptedKey) => { + const cryptoKey = await getCryptoKey(key, alg, "unwrapKey"); + checkKeySize(cryptoKey, alg); + const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, cryptoKey, "AES-KW", ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); +}; + +// dist/browser/runtime/ecdhes.js +async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { + if (!isCryptoKey(publicKey)) { + throw new TypeError(invalid_key_input_default(publicKey, ...types)); + } + checkEncCryptoKey(publicKey, "ECDH"); + if (!isCryptoKey(privateKey)) { + throw new TypeError(invalid_key_input_default(privateKey, ...types)); + } + checkEncCryptoKey(privateKey, "ECDH", "deriveBits"); + const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); + let length; + if (publicKey.algorithm.name === "X25519") { + length = 256; + } else if (publicKey.algorithm.name === "X448") { + length = 448; + } else { + length = Math.ceil(parseInt(publicKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3; + } + const sharedSecret = new Uint8Array(await webcrypto_default.subtle.deriveBits({ + name: publicKey.algorithm.name, + public: publicKey + }, privateKey, length)); + return concatKdf(sharedSecret, keyLength, value); +} +async function generateEpk(key) { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + return webcrypto_default.subtle.generateKey(key.algorithm, true, ["deriveBits"]); +} +function ecdhAllowed(key) { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + return ["P-256", "P-384", "P-521"].includes(key.algorithm.namedCurve) || key.algorithm.name === "X25519" || key.algorithm.name === "X448"; +} + +// dist/browser/lib/check_p2s.js +function checkP2s(p2s2) { + if (!(p2s2 instanceof Uint8Array) || p2s2.length < 8) { + throw new JWEInvalid("PBES2 Salt Input must be 8 or more octets"); + } +} + +// dist/browser/runtime/pbes2kw.js +function getCryptoKey2(key, alg) { + if (key instanceof Uint8Array) { + return webcrypto_default.subtle.importKey("raw", key, "PBKDF2", false, ["deriveBits"]); + } + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, "deriveBits", "deriveKey"); + return key; + } + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); +} +async function deriveKey2(p2s2, alg, p2c, key) { + checkP2s(p2s2); + const salt = p2s(alg, p2s2); + const keylen = parseInt(alg.slice(13, 16), 10); + const subtleAlg = { + hash: `SHA-${alg.slice(8, 11)}`, + iterations: p2c, + name: "PBKDF2", + salt + }; + const wrapAlg = { + length: keylen, + name: "AES-KW" + }; + const cryptoKey = await getCryptoKey2(key, alg); + if (cryptoKey.usages.includes("deriveBits")) { + return new Uint8Array(await webcrypto_default.subtle.deriveBits(subtleAlg, cryptoKey, keylen)); + } + if (cryptoKey.usages.includes("deriveKey")) { + return webcrypto_default.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ["wrapKey", "unwrapKey"]); + } + throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"'); +} +var encrypt = async (alg, key, cek, p2c = 2048, p2s2 = random_default(new Uint8Array(16))) => { + const derived = await deriveKey2(p2s2, alg, p2c, key); + const encryptedKey = await wrap(alg.slice(-6), derived, cek); + return { encryptedKey, p2c, p2s: encode(p2s2) }; +}; +var decrypt2 = async (alg, key, encryptedKey, p2c, p2s2) => { + const derived = await deriveKey2(p2s2, alg, p2c, key); + return unwrap(alg.slice(-6), derived, encryptedKey); +}; + +// dist/browser/runtime/subtle_rsaes.js +function subtleRsaEs(alg) { + switch (alg) { + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + return "RSA-OAEP"; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} + +// dist/browser/runtime/check_key_length.js +var check_key_length_default = (alg, key) => { + if (alg.startsWith("RS") || alg.startsWith("PS")) { + const { modulusLength } = key.algorithm; + if (typeof modulusLength !== "number" || modulusLength < 2048) { + throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); + } + } +}; + +// dist/browser/runtime/rsaes.js +var encrypt2 = async (alg, key, cek) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + checkEncCryptoKey(key, alg, "encrypt", "wrapKey"); + check_key_length_default(alg, key); + if (key.usages.includes("encrypt")) { + return new Uint8Array(await webcrypto_default.subtle.encrypt(subtleRsaEs(alg), key, cek)); + } + if (key.usages.includes("wrapKey")) { + const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, key, subtleRsaEs(alg))); + } + throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation'); +}; +var decrypt3 = async (alg, key, encryptedKey) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + checkEncCryptoKey(key, alg, "decrypt", "unwrapKey"); + check_key_length_default(alg, key); + if (key.usages.includes("decrypt")) { + return new Uint8Array(await webcrypto_default.subtle.decrypt(subtleRsaEs(alg), key, encryptedKey)); + } + if (key.usages.includes("unwrapKey")) { + const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, key, subtleRsaEs(alg), ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); + } + throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation'); +}; + +// dist/browser/lib/cek.js +function bitLength2(alg) { + switch (alg) { + case "A128GCM": + return 128; + case "A192GCM": + return 192; + case "A256GCM": + case "A128CBC-HS256": + return 256; + case "A192CBC-HS384": + return 384; + case "A256CBC-HS512": + return 512; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +var cek_default = (alg) => random_default(new Uint8Array(bitLength2(alg) >> 3)); + +// dist/browser/lib/format_pem.js +var format_pem_default = (b64, descriptor) => { + const newlined = (b64.match(/.{1,64}/g) || []).join("\n"); + return `-----BEGIN ${descriptor}----- +${newlined} +-----END ${descriptor}-----`; +}; + +// dist/browser/runtime/asn1.js +var genericExport = async (keyType, keyFormat, key) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + if (!key.extractable) { + throw new TypeError("CryptoKey is not extractable"); + } + if (key.type !== keyType) { + throw new TypeError(`key is not a ${keyType} key`); + } + return format_pem_default(encodeBase64(new Uint8Array(await webcrypto_default.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`); +}; +var toSPKI = (key) => { + return genericExport("public", "spki", key); +}; +var toPKCS8 = (key) => { + return genericExport("private", "pkcs8", key); +}; +var findOid = (keyData, oid, from = 0) => { + if (from === 0) { + oid.unshift(oid.length); + oid.unshift(6); + } + let i = keyData.indexOf(oid[0], from); + if (i === -1) + return false; + const sub = keyData.subarray(i, i + oid.length); + if (sub.length !== oid.length) + return false; + return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1); +}; +var getNamedCurve2 = (keyData) => { + switch (true) { + case findOid(keyData, [42, 134, 72, 206, 61, 3, 1, 7]): + return "P-256"; + case findOid(keyData, [43, 129, 4, 0, 34]): + return "P-384"; + case findOid(keyData, [43, 129, 4, 0, 35]): + return "P-521"; + case findOid(keyData, [43, 101, 110]): + return "X25519"; + case findOid(keyData, [43, 101, 111]): + return "X448"; + case findOid(keyData, [43, 101, 112]): + return "Ed25519"; + case findOid(keyData, [43, 101, 113]): + return "Ed448"; + default: + throw new JOSENotSupported("Invalid or unsupported EC Key Curve or OKP Key Sub Type"); + } +}; +var genericImport = async (replace, keyFormat, pem, alg, options) => { + var _a, _b; + let algorithm; + let keyUsages; + const keyData = new Uint8Array(atob(pem.replace(replace, "")).split("").map((c) => c.charCodeAt(0))); + const isPublic = keyFormat === "spki"; + switch (alg) { + case "PS256": + case "PS384": + case "PS512": + algorithm = { name: "RSA-PSS", hash: `SHA-${alg.slice(-3)}` }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "RS256": + case "RS384": + case "RS512": + algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.slice(-3)}` }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + algorithm = { + name: "RSA-OAEP", + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}` + }; + keyUsages = isPublic ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"]; + break; + case "ES256": + algorithm = { name: "ECDSA", namedCurve: "P-256" }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "ES384": + algorithm = { name: "ECDSA", namedCurve: "P-384" }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "ES512": + algorithm = { name: "ECDSA", namedCurve: "P-521" }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + const namedCurve = getNamedCurve2(keyData); + algorithm = namedCurve.startsWith("P-") ? { name: "ECDH", namedCurve } : { name: namedCurve }; + keyUsages = isPublic ? [] : ["deriveBits"]; + break; + } + case "EdDSA": + algorithm = { name: getNamedCurve2(keyData) }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value'); + } + try { + return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); + } catch (err) { + if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { + algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages); + } + throw err; + } +}; +var fromPKCS8 = (pem, alg, options) => { + return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, "pkcs8", pem, alg, options); +}; +var fromSPKI = (pem, alg, options) => { + return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "spki", pem, alg, options); +}; +function getElement(seq) { + let result = []; + let next = 0; + while (next < seq.length) { + let nextPart = parseElement(seq.subarray(next)); + result.push(nextPart); + next += nextPart.byteLength; + } + return result; +} +function parseElement(bytes) { + let position = 0; + let tag = bytes[0] & 31; + position++; + if (tag === 31) { + tag = 0; + while (bytes[position] >= 128) { + tag = tag * 128 + bytes[position] - 128; + position++; + } + tag = tag * 128 + bytes[position] - 128; + position++; + } + let length = 0; + if (bytes[position] < 128) { + length = bytes[position]; + position++; + } else if (length === 128) { + length = 0; + while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { + if (length > bytes.byteLength) { + throw new TypeError("invalid indefinite form length"); + } + length++; + } + const byteLength2 = position + length + 2; + return { + byteLength: byteLength2, + contents: bytes.subarray(position, position + length), + raw: bytes.subarray(0, byteLength2) + }; + } else { + let numberOfDigits = bytes[position] & 127; + position++; + length = 0; + for (let i = 0; i < numberOfDigits; i++) { + length = length * 256 + bytes[position]; + position++; + } + } + const byteLength = position + length; + return { + byteLength, + contents: bytes.subarray(position, byteLength), + raw: bytes.subarray(0, byteLength) + }; +} +function spkiFromX509(buf) { + const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents); + return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 160 ? 6 : 5].raw); +} +function getSPKI(x509) { + const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ""); + const raw = decodeBase64(pem); + return format_pem_default(spkiFromX509(raw), "PUBLIC KEY"); +} +var fromX509 = (pem, alg, options) => { + let spki; + try { + spki = getSPKI(pem); + } catch (cause) { + throw new TypeError("failed to parse the X.509 certificate", { cause }); + } + return fromSPKI(spki, alg, options); +}; + +// dist/browser/runtime/jwk_to_key.js +function subtleMapping(jwk) { + let algorithm; + let keyUsages; + switch (jwk.kty) { + case "oct": { + switch (jwk.alg) { + case "HS256": + case "HS384": + case "HS512": + algorithm = { name: "HMAC", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = ["sign", "verify"]; + break; + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`); + case "A128GCM": + case "A192GCM": + case "A256GCM": + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": + algorithm = { name: "AES-GCM" }; + keyUsages = ["encrypt", "decrypt"]; + break; + case "A128KW": + case "A192KW": + case "A256KW": + algorithm = { name: "AES-KW" }; + keyUsages = ["wrapKey", "unwrapKey"]; + break; + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": + algorithm = { name: "PBKDF2" }; + keyUsages = ["deriveBits"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "RSA": { + switch (jwk.alg) { + case "PS256": + case "PS384": + case "PS512": + algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "RS256": + case "RS384": + case "RS512": + algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + algorithm = { + name: "RSA-OAEP", + hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}` + }; + keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "EC": { + switch (jwk.alg) { + case "ES256": + algorithm = { name: "ECDSA", namedCurve: "P-256" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ES384": + algorithm = { name: "ECDSA", namedCurve: "P-384" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ES512": + algorithm = { name: "ECDSA", namedCurve: "P-521" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": + algorithm = { name: "ECDH", namedCurve: jwk.crv }; + keyUsages = jwk.d ? ["deriveBits"] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "OKP": { + switch (jwk.alg) { + case "EdDSA": + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ["deriveBits"] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); + } + return { algorithm, keyUsages }; +} +var parse = async (jwk) => { + var _a, _b; + if (!jwk.alg) { + throw new TypeError('"alg" argument is required when "jwk.alg" is not present'); + } + const { algorithm, keyUsages } = subtleMapping(jwk); + const rest = [ + algorithm, + (_a = jwk.ext) !== null && _a !== void 0 ? _a : false, + (_b = jwk.key_ops) !== null && _b !== void 0 ? _b : keyUsages + ]; + if (algorithm.name === "PBKDF2") { + return webcrypto_default.subtle.importKey("raw", decode(jwk.k), ...rest); + } + const keyData = { ...jwk }; + delete keyData.alg; + delete keyData.use; + try { + return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); + } catch (err) { + if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { + rest[0] = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); + } + throw err; + } +}; +var jwk_to_key_default = parse; + +// dist/browser/key/import.js +async function importSPKI(spki, alg, options) { + if (typeof spki !== "string" || spki.indexOf("-----BEGIN PUBLIC KEY-----") !== 0) { + throw new TypeError('"spki" must be SPKI formatted string'); + } + return fromSPKI(spki, alg, options); +} +async function importX509(x509, alg, options) { + if (typeof x509 !== "string" || x509.indexOf("-----BEGIN CERTIFICATE-----") !== 0) { + throw new TypeError('"x509" must be X.509 formatted string'); + } + return fromX509(x509, alg, options); +} +async function importPKCS8(pkcs8, alg, options) { + if (typeof pkcs8 !== "string" || pkcs8.indexOf("-----BEGIN PRIVATE KEY-----") !== 0) { + throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); + } + return fromPKCS8(pkcs8, alg, options); +} +async function importJWK(jwk, alg, octAsKeyObject) { + var _a; + if (!isObject(jwk)) { + throw new TypeError("JWK must be an object"); + } + alg || (alg = jwk.alg); + switch (jwk.kty) { + case "oct": + if (typeof jwk.k !== "string" || !jwk.k) { + throw new TypeError('missing "k" (Key Value) Parameter value'); + } + octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : octAsKeyObject = jwk.ext !== true; + if (octAsKeyObject) { + return jwk_to_key_default({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); + } + return decode(jwk.k); + case "RSA": + if (jwk.oth !== void 0) { + throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); + } + case "EC": + case "OKP": + return jwk_to_key_default({ ...jwk, alg }); + default: + throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); + } +} + +// dist/browser/lib/check_key_type.js +var symmetricTypeCheck = (alg, key) => { + if (key instanceof Uint8Array) + return; + if (!is_key_like_default(key)) { + throw new TypeError(withAlg(alg, key, ...types, "Uint8Array")); + } + if (key.type !== "secret") { + throw new TypeError(`${types.join(" or ")} instances for symmetric algorithms must be of type "secret"`); + } +}; +var asymmetricTypeCheck = (alg, key, usage) => { + if (!is_key_like_default(key)) { + throw new TypeError(withAlg(alg, key, ...types)); + } + if (key.type === "secret") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`); + } + if (usage === "sign" && key.type === "public") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`); + } + if (usage === "decrypt" && key.type === "public") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`); + } + if (key.algorithm && usage === "verify" && key.type === "private") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`); + } + if (key.algorithm && usage === "encrypt" && key.type === "private") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`); + } +}; +var checkKeyType = (alg, key, usage) => { + const symmetric = alg.startsWith("HS") || alg === "dir" || alg.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(alg); + if (symmetric) { + symmetricTypeCheck(alg, key); + } else { + asymmetricTypeCheck(alg, key, usage); + } +}; +var check_key_type_default = checkKeyType; + +// dist/browser/runtime/encrypt.js +async function cbcEncrypt(enc, plaintext, cek, iv, aad) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); + } + const keySize = parseInt(enc.slice(1, 4), 10); + const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["encrypt"]); + const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { + hash: `SHA-${keySize << 1}`, + name: "HMAC" + }, false, ["sign"]); + const ciphertext = new Uint8Array(await webcrypto_default.subtle.encrypt({ + iv, + name: "AES-CBC" + }, encKey, plaintext)); + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); + const tag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); + return { ciphertext, tag }; +} +async function gcmEncrypt(enc, plaintext, cek, iv, aad) { + let encKey; + if (cek instanceof Uint8Array) { + encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["encrypt"]); + } else { + checkEncCryptoKey(cek, enc, "encrypt"); + encKey = cek; + } + const encrypted = new Uint8Array(await webcrypto_default.subtle.encrypt({ + additionalData: aad, + iv, + name: "AES-GCM", + tagLength: 128 + }, encKey, plaintext)); + const tag = encrypted.slice(-16); + const ciphertext = encrypted.slice(0, -16); + return { ciphertext, tag }; +} +var encrypt3 = async (enc, plaintext, cek, iv, aad) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); + } + check_iv_length_default(enc, iv); + switch (enc) { + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); + return cbcEncrypt(enc, plaintext, cek, iv, aad); + case "A128GCM": + case "A192GCM": + case "A256GCM": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); + return gcmEncrypt(enc, plaintext, cek, iv, aad); + default: + throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); + } +}; +var encrypt_default = encrypt3; + +// dist/browser/lib/aesgcmkw.js +async function wrap2(alg, key, cek, iv) { + const jweAlgorithm = alg.slice(0, 7); + iv || (iv = iv_default(jweAlgorithm)); + const { ciphertext: encryptedKey, tag } = await encrypt_default(jweAlgorithm, cek, key, iv, new Uint8Array(0)); + return { encryptedKey, iv: encode(iv), tag: encode(tag) }; +} +async function unwrap2(alg, key, encryptedKey, iv, tag) { + const jweAlgorithm = alg.slice(0, 7); + return decrypt_default(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); +} + +// dist/browser/lib/decrypt_key_management.js +async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { + check_key_type_default(alg, key, "decrypt"); + switch (alg) { + case "dir": { + if (encryptedKey !== void 0) + throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); + return key; + } + case "ECDH-ES": + if (encryptedKey !== void 0) + throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + if (!isObject(joseHeader.epk)) + throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); + if (!ecdhAllowed(key)) + throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); + const epk = await importJWK(joseHeader.epk, alg); + let partyUInfo; + let partyVInfo; + if (joseHeader.apu !== void 0) { + if (typeof joseHeader.apu !== "string") + throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); + partyUInfo = decode(joseHeader.apu); + } + if (joseHeader.apv !== void 0) { + if (typeof joseHeader.apv !== "string") + throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); + partyVInfo = decode(joseHeader.apv); + } + const sharedSecret = await deriveKey(epk, key, alg === "ECDH-ES" ? joseHeader.enc : alg, alg === "ECDH-ES" ? bitLength2(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); + if (alg === "ECDH-ES") + return sharedSecret; + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + return unwrap(alg.slice(-6), sharedSecret, encryptedKey); + } + case "RSA1_5": + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + return decrypt3(alg, key, encryptedKey); + } + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + if (typeof joseHeader.p2c !== "number") + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); + const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 1e4; + if (joseHeader.p2c > p2cLimit) + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); + if (typeof joseHeader.p2s !== "string") + throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); + return decrypt2(alg, key, encryptedKey, joseHeader.p2c, decode(joseHeader.p2s)); + } + case "A128KW": + case "A192KW": + case "A256KW": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + return unwrap(alg, key, encryptedKey); + } + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + if (typeof joseHeader.iv !== "string") + throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); + if (typeof joseHeader.tag !== "string") + throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); + const iv = decode(joseHeader.iv); + const tag = decode(joseHeader.tag); + return unwrap2(alg, key, encryptedKey, iv, tag); + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } +} +var decrypt_key_management_default = decryptKeyManagement; + +// dist/browser/lib/validate_crit.js +function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { + if (joseHeader.crit !== void 0 && protectedHeader.crit === void 0) { + throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); + } + if (!protectedHeader || protectedHeader.crit === void 0) { + return /* @__PURE__ */ new Set(); + } + if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) { + throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); + } + let recognized; + if (recognizedOption !== void 0) { + recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); + } else { + recognized = recognizedDefault; + } + for (const parameter of protectedHeader.crit) { + if (!recognized.has(parameter)) { + throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); + } + if (joseHeader[parameter] === void 0) { + throw new Err(`Extension Header Parameter "${parameter}" is missing`); + } else if (recognized.get(parameter) && protectedHeader[parameter] === void 0) { + throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); + } + } + return new Set(protectedHeader.crit); +} +var validate_crit_default = validateCrit; + +// dist/browser/lib/validate_algorithms.js +var validateAlgorithms = (option, algorithms) => { + if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) { + throw new TypeError(`"${option}" option must be an array of strings`); + } + if (!algorithms) { + return void 0; + } + return new Set(algorithms); +}; +var validate_algorithms_default = validateAlgorithms; + +// dist/browser/jwe/flattened/decrypt.js +async function flattenedDecrypt(jwe, key, options) { + var _a; + if (!isObject(jwe)) { + throw new JWEInvalid("Flattened JWE must be an object"); + } + if (jwe.protected === void 0 && jwe.header === void 0 && jwe.unprotected === void 0) { + throw new JWEInvalid("JOSE Header missing"); + } + if (typeof jwe.iv !== "string") { + throw new JWEInvalid("JWE Initialization Vector missing or incorrect type"); + } + if (typeof jwe.ciphertext !== "string") { + throw new JWEInvalid("JWE Ciphertext missing or incorrect type"); + } + if (typeof jwe.tag !== "string") { + throw new JWEInvalid("JWE Authentication Tag missing or incorrect type"); + } + if (jwe.protected !== void 0 && typeof jwe.protected !== "string") { + throw new JWEInvalid("JWE Protected Header incorrect type"); + } + if (jwe.encrypted_key !== void 0 && typeof jwe.encrypted_key !== "string") { + throw new JWEInvalid("JWE Encrypted Key incorrect type"); + } + if (jwe.aad !== void 0 && typeof jwe.aad !== "string") { + throw new JWEInvalid("JWE AAD incorrect type"); + } + if (jwe.header !== void 0 && !isObject(jwe.header)) { + throw new JWEInvalid("JWE Shared Unprotected Header incorrect type"); + } + if (jwe.unprotected !== void 0 && !isObject(jwe.unprotected)) { + throw new JWEInvalid("JWE Per-Recipient Unprotected Header incorrect type"); + } + let parsedProt; + if (jwe.protected) { + try { + const protectedHeader2 = decode(jwe.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader2)); + } catch (_b) { + throw new JWEInvalid("JWE Protected Header is invalid"); + } + } + if (!is_disjoint_default(parsedProt, jwe.header, jwe.unprotected)) { + throw new JWEInvalid("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint"); + } + const joseHeader = { + ...parsedProt, + ...jwe.header, + ...jwe.unprotected + }; + validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + if (joseHeader.zip !== void 0) { + if (!parsedProt || !parsedProt.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== "DEF") { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWEInvalid("missing JWE Algorithm (alg) in JWE Header"); + } + if (typeof enc !== "string" || !enc) { + throw new JWEInvalid("missing JWE Encryption Algorithm (enc) in JWE Header"); + } + const keyManagementAlgorithms = options && validate_algorithms_default("keyManagementAlgorithms", options.keyManagementAlgorithms); + const contentEncryptionAlgorithms = options && validate_algorithms_default("contentEncryptionAlgorithms", options.contentEncryptionAlgorithms); + if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { + throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); + } + let encryptedKey; + if (jwe.encrypted_key !== void 0) { + encryptedKey = decode(jwe.encrypted_key); + } + let resolvedKey = false; + if (typeof key === "function") { + key = await key(parsedProt, jwe); + resolvedKey = true; + } + let cek; + try { + cek = await decrypt_key_management_default(alg, key, encryptedKey, joseHeader, options); + } catch (err) { + if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { + throw err; + } + cek = cek_default(enc); + } + const iv = decode(jwe.iv); + const tag = decode(jwe.tag); + const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ""); + let additionalData; + if (jwe.aad !== void 0) { + additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(jwe.aad)); + } else { + additionalData = protectedHeader; + } + let plaintext = await decrypt_default(enc, cek, decode(jwe.ciphertext), iv, tag, additionalData); + if (joseHeader.zip === "DEF") { + plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); + } + const result = { plaintext }; + if (jwe.protected !== void 0) { + result.protectedHeader = parsedProt; + } + if (jwe.aad !== void 0) { + result.additionalAuthenticatedData = decode(jwe.aad); + } + if (jwe.unprotected !== void 0) { + result.sharedUnprotectedHeader = jwe.unprotected; + } + if (jwe.header !== void 0) { + result.unprotectedHeader = jwe.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} + +// dist/browser/jwe/compact/decrypt.js +async function compactDecrypt(jwe, key, options) { + if (jwe instanceof Uint8Array) { + jwe = decoder.decode(jwe); + } + if (typeof jwe !== "string") { + throw new JWEInvalid("Compact JWE must be a string or Uint8Array"); + } + const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length } = jwe.split("."); + if (length !== 5) { + throw new JWEInvalid("Invalid Compact JWE"); + } + const decrypted = await flattenedDecrypt({ + ciphertext, + iv: iv || void 0, + protected: protectedHeader || void 0, + tag: tag || void 0, + encrypted_key: encryptedKey || void 0 + }, key, options); + const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: decrypted.key }; + } + return result; +} + +// dist/browser/jwe/general/decrypt.js +async function generalDecrypt(jwe, key, options) { + if (!isObject(jwe)) { + throw new JWEInvalid("General JWE must be an object"); + } + if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { + throw new JWEInvalid("JWE Recipients missing or incorrect type"); + } + if (!jwe.recipients.length) { + throw new JWEInvalid("JWE Recipients has no members"); + } + for (const recipient of jwe.recipients) { + try { + return await flattenedDecrypt({ + aad: jwe.aad, + ciphertext: jwe.ciphertext, + encrypted_key: recipient.encrypted_key, + header: recipient.header, + iv: jwe.iv, + protected: jwe.protected, + tag: jwe.tag, + unprotected: jwe.unprotected + }, key, options); + } catch (_a) { + } + } + throw new JWEDecryptionFailed(); +} + +// dist/browser/runtime/key_to_jwk.js +var keyToJWK = async (key) => { + if (key instanceof Uint8Array) { + return { + kty: "oct", + k: encode(key) + }; + } + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); + } + if (!key.extractable) { + throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK"); + } + const { ext, key_ops, alg, use, ...jwk } = await webcrypto_default.subtle.exportKey("jwk", key); + return jwk; +}; +var key_to_jwk_default = keyToJWK; + +// dist/browser/key/export.js +async function exportSPKI(key) { + return toSPKI(key); +} +async function exportPKCS8(key) { + return toPKCS8(key); +} +async function exportJWK(key) { + return key_to_jwk_default(key); +} + +// dist/browser/lib/encrypt_key_management.js +async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { + let encryptedKey; + let parameters; + let cek; + check_key_type_default(alg, key, "encrypt"); + switch (alg) { + case "dir": { + cek = key; + break; + } + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + if (!ecdhAllowed(key)) { + throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); + } + const { apu, apv } = providedParameters; + let { epk: ephemeralKey } = providedParameters; + ephemeralKey || (ephemeralKey = (await generateEpk(key)).privateKey); + const { x, y, crv, kty } = await exportJWK(ephemeralKey); + const sharedSecret = await deriveKey(key, ephemeralKey, alg === "ECDH-ES" ? enc : alg, alg === "ECDH-ES" ? bitLength2(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); + parameters = { epk: { x, crv, kty } }; + if (kty === "EC") + parameters.epk.y = y; + if (apu) + parameters.apu = encode(apu); + if (apv) + parameters.apv = encode(apv); + if (alg === "ECDH-ES") { + cek = sharedSecret; + break; + } + cek = providedCek || cek_default(enc); + const kwAlg = alg.slice(-6); + encryptedKey = await wrap(kwAlg, sharedSecret, cek); + break; + } + case "RSA1_5": + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": { + cek = providedCek || cek_default(enc); + encryptedKey = await encrypt2(alg, key, cek); + break; + } + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": { + cek = providedCek || cek_default(enc); + const { p2c, p2s: p2s2 } = providedParameters; + ({ encryptedKey, ...parameters } = await encrypt(alg, key, cek, p2c, p2s2)); + break; + } + case "A128KW": + case "A192KW": + case "A256KW": { + cek = providedCek || cek_default(enc); + encryptedKey = await wrap(alg, key, cek); + break; + } + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": { + cek = providedCek || cek_default(enc); + const { iv } = providedParameters; + ({ encryptedKey, ...parameters } = await wrap2(alg, key, cek, iv)); + break; + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } + return { cek, encryptedKey, parameters }; +} +var encrypt_key_management_default = encryptKeyManagement; + +// dist/browser/jwe/flattened/encrypt.js +var unprotected = Symbol(); +var FlattenedEncrypt = class { + constructor(plaintext) { + if (!(plaintext instanceof Uint8Array)) { + throw new TypeError("plaintext must be an instance of Uint8Array"); + } + this._plaintext = plaintext; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError("setKeyManagementParameters can only be called once"); + } + this._keyManagementParameters = parameters; + return this; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._sharedUnprotectedHeader) { + throw new TypeError("setSharedUnprotectedHeader can only be called once"); + } + this._sharedUnprotectedHeader = sharedUnprotectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError("setContentEncryptionKey can only be called once"); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError("setInitializationVector can only be called once"); + } + this._iv = iv; + return this; + } + async encrypt(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { + throw new JWEInvalid("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()"); + } + if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { + throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...this._sharedUnprotectedHeader + }; + validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== void 0) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== "DEF") { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (typeof enc !== "string" || !enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + let encryptedKey; + if (alg === "dir") { + if (this._cek) { + throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption"); + } + } else if (alg === "ECDH-ES") { + if (this._cek) { + throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement"); + } + } + let cek; + { + let parameters; + ({ cek, encryptedKey, parameters } = await encrypt_key_management_default(alg, enc, key, this._cek, this._keyManagementParameters)); + if (parameters) { + if (options && unprotected in options) { + if (!this._unprotectedHeader) { + this.setUnprotectedHeader(parameters); + } else { + this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; + } + } else { + if (!this._protectedHeader) { + this.setProtectedHeader(parameters); + } else { + this._protectedHeader = { ...this._protectedHeader, ...parameters }; + } + } + } + } + this._iv || (this._iv = iv_default(enc)); + let additionalData; + let protectedHeader; + let aadMember; + if (this._protectedHeader) { + protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); + } else { + protectedHeader = encoder.encode(""); + } + if (this._aad) { + aadMember = encode(this._aad); + additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(aadMember)); + } else { + additionalData = protectedHeader; + } + let ciphertext; + let tag; + if (joseHeader.zip === "DEF") { + const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); + ({ ciphertext, tag } = await encrypt_default(enc, deflated, cek, this._iv, additionalData)); + } else { + ; + ({ ciphertext, tag } = await encrypt_default(enc, this._plaintext, cek, this._iv, additionalData)); + } + const jwe = { + ciphertext: encode(ciphertext), + iv: encode(this._iv), + tag: encode(tag) + }; + if (encryptedKey) { + jwe.encrypted_key = encode(encryptedKey); + } + if (aadMember) { + jwe.aad = aadMember; + } + if (this._protectedHeader) { + jwe.protected = decoder.decode(protectedHeader); + } + if (this._sharedUnprotectedHeader) { + jwe.unprotected = this._sharedUnprotectedHeader; + } + if (this._unprotectedHeader) { + jwe.header = this._unprotectedHeader; + } + return jwe; + } +}; + +// dist/browser/jwe/general/encrypt.js +var IndividualRecipient = class { + constructor(enc, key, options) { + this.parent = enc; + this.key = key; + this.options = options; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addRecipient(...args) { + return this.parent.addRecipient(...args); + } + encrypt(...args) { + return this.parent.encrypt(...args); + } + done() { + return this.parent; + } +}; +var GeneralEncrypt = class { + constructor(plaintext) { + this._recipients = []; + this._plaintext = plaintext; + } + addRecipient(key, options) { + const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); + this._recipients.push(recipient); + return recipient; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError("setSharedUnprotectedHeader can only be called once"); + } + this._unprotectedHeader = sharedUnprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + async encrypt(options) { + var _a, _b, _c; + if (!this._recipients.length) { + throw new JWEInvalid("at least one recipient must be added"); + } + options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; + if (this._recipients.length === 1) { + const [recipient] = this._recipients; + const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).encrypt(recipient.key, { ...recipient.options, ...options }); + let jwe2 = { + ciphertext: flattened.ciphertext, + iv: flattened.iv, + recipients: [{}], + tag: flattened.tag + }; + if (flattened.aad) + jwe2.aad = flattened.aad; + if (flattened.protected) + jwe2.protected = flattened.protected; + if (flattened.unprotected) + jwe2.unprotected = flattened.unprotected; + if (flattened.encrypted_key) + jwe2.recipients[0].encrypted_key = flattened.encrypted_key; + if (flattened.header) + jwe2.recipients[0].header = flattened.header; + return jwe2; + } + let enc; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { + throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader + }; + const { alg } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (alg === "dir" || alg === "ECDH-ES") { + throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); + } + if (typeof joseHeader.enc !== "string" || !joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + if (!enc) { + enc = joseHeader.enc; + } else if (enc !== joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); + } + validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), recipient.options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== void 0) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + } + } + const cek = cek_default(enc); + let jwe = { + ciphertext: "", + iv: "", + recipients: [], + tag: "" + }; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + const target = {}; + jwe.recipients.push(target); + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader + }; + const p2c = joseHeader.alg.startsWith("PBES2") ? 2048 + i : void 0; + if (i === 0) { + const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setContentEncryptionKey(cek).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).setKeyManagementParameters({ p2c }).encrypt(recipient.key, { + ...recipient.options, + ...options, + [unprotected]: true + }); + jwe.ciphertext = flattened.ciphertext; + jwe.iv = flattened.iv; + jwe.tag = flattened.tag; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + target.encrypted_key = flattened.encrypted_key; + if (flattened.header) + target.header = flattened.header; + continue; + } + const { encryptedKey, parameters } = await encrypt_key_management_default(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); + target.encrypted_key = encode(encryptedKey); + if (recipient.unprotectedHeader || parameters) + target.header = { ...recipient.unprotectedHeader, ...parameters }; + } + return jwe; + } +}; + +// dist/browser/runtime/subtle_dsa.js +function subtleDsa(alg, algorithm) { + const hash = `SHA-${alg.slice(-3)}`; + switch (alg) { + case "HS256": + case "HS384": + case "HS512": + return { hash, name: "HMAC" }; + case "PS256": + case "PS384": + case "PS512": + return { hash, name: "RSA-PSS", saltLength: alg.slice(-3) >> 3 }; + case "RS256": + case "RS384": + case "RS512": + return { hash, name: "RSASSA-PKCS1-v1_5" }; + case "ES256": + case "ES384": + case "ES512": + return { hash, name: "ECDSA", namedCurve: algorithm.namedCurve }; + case "EdDSA": + if (isCloudflareWorkers() && algorithm.name === "NODE-ED25519") { + return { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + } + return { name: algorithm.name }; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} + +// dist/browser/runtime/get_sign_verify_key.js +function getCryptoKey3(alg, key, usage) { + if (isCryptoKey(key)) { + checkSigCryptoKey(key, alg, usage); + return key; + } + if (key instanceof Uint8Array) { + if (!alg.startsWith("HS")) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + return webcrypto_default.subtle.importKey("raw", key, { hash: `SHA-${alg.slice(-3)}`, name: "HMAC" }, false, [usage]); + } + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); +} + +// dist/browser/runtime/verify.js +var verify = async (alg, key, signature, data) => { + const cryptoKey = await getCryptoKey3(alg, key, "verify"); + check_key_length_default(alg, cryptoKey); + const algorithm = subtleDsa(alg, cryptoKey.algorithm); + try { + return await webcrypto_default.subtle.verify(algorithm, cryptoKey, signature, data); + } catch (_a) { + return false; + } +}; +var verify_default = verify; + +// dist/browser/jws/flattened/verify.js +async function flattenedVerify(jws, key, options) { + var _a; + if (!isObject(jws)) { + throw new JWSInvalid("Flattened JWS must be an object"); + } + if (jws.protected === void 0 && jws.header === void 0) { + throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); + } + if (jws.protected !== void 0 && typeof jws.protected !== "string") { + throw new JWSInvalid("JWS Protected Header incorrect type"); + } + if (jws.payload === void 0) { + throw new JWSInvalid("JWS Payload missing"); + } + if (typeof jws.signature !== "string") { + throw new JWSInvalid("JWS Signature missing or incorrect type"); + } + if (jws.header !== void 0 && !isObject(jws.header)) { + throw new JWSInvalid("JWS Unprotected Header incorrect type"); + } + let parsedProt = {}; + if (jws.protected) { + try { + const protectedHeader = decode(jws.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader)); + } catch (_b) { + throw new JWSInvalid("JWS Protected Header is invalid"); + } + } + if (!is_disjoint_default(parsedProt, jws.header)) { + throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); + } + const joseHeader = { + ...parsedProt, + ...jws.header + }; + const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + let b64 = true; + if (extensions.has("b64")) { + b64 = parsedProt.b64; + if (typeof b64 !== "boolean") { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + const algorithms = options && validate_algorithms_default("algorithms", options.algorithms); + if (algorithms && !algorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (b64) { + if (typeof jws.payload !== "string") { + throw new JWSInvalid("JWS Payload must be a string"); + } + } else if (typeof jws.payload !== "string" && !(jws.payload instanceof Uint8Array)) { + throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance"); + } + let resolvedKey = false; + if (typeof key === "function") { + key = await key(parsedProt, jws); + resolvedKey = true; + } + check_key_type_default(alg, key, "verify"); + const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ""), encoder.encode("."), typeof jws.payload === "string" ? encoder.encode(jws.payload) : jws.payload); + const signature = decode(jws.signature); + const verified = await verify_default(alg, key, signature, data); + if (!verified) { + throw new JWSSignatureVerificationFailed(); + } + let payload; + if (b64) { + payload = decode(jws.payload); + } else if (typeof jws.payload === "string") { + payload = encoder.encode(jws.payload); + } else { + payload = jws.payload; + } + const result = { payload }; + if (jws.protected !== void 0) { + result.protectedHeader = parsedProt; + } + if (jws.header !== void 0) { + result.unprotectedHeader = jws.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} + +// dist/browser/jws/compact/verify.js +async function compactVerify(jws, key, options) { + if (jws instanceof Uint8Array) { + jws = decoder.decode(jws); + } + if (typeof jws !== "string") { + throw new JWSInvalid("Compact JWS must be a string or Uint8Array"); + } + const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split("."); + if (length !== 3) { + throw new JWSInvalid("Invalid Compact JWS"); + } + const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); + const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: verified.key }; + } + return result; +} + +// dist/browser/jws/general/verify.js +async function generalVerify(jws, key, options) { + if (!isObject(jws)) { + throw new JWSInvalid("General JWS must be an object"); + } + if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { + throw new JWSInvalid("JWS Signatures missing or incorrect type"); + } + for (const signature of jws.signatures) { + try { + return await flattenedVerify({ + header: signature.header, + payload: jws.payload, + protected: signature.protected, + signature: signature.signature + }, key, options); + } catch (_a) { + } + } + throw new JWSSignatureVerificationFailed(); +} + +// dist/browser/lib/epoch.js +var epoch_default = (date) => Math.floor(date.getTime() / 1e3); + +// dist/browser/lib/secs.js +var minute = 60; +var hour = minute * 60; +var day = hour * 24; +var week = day * 7; +var year = day * 365.25; +var REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; +var secs_default = (str) => { + const matched = REGEX.exec(str); + if (!matched) { + throw new TypeError("Invalid time period format"); + } + const value = parseFloat(matched[1]); + const unit = matched[2].toLowerCase(); + switch (unit) { + case "sec": + case "secs": + case "second": + case "seconds": + case "s": + return Math.round(value); + case "minute": + case "minutes": + case "min": + case "mins": + case "m": + return Math.round(value * minute); + case "hour": + case "hours": + case "hr": + case "hrs": + case "h": + return Math.round(value * hour); + case "day": + case "days": + case "d": + return Math.round(value * day); + case "week": + case "weeks": + case "w": + return Math.round(value * week); + default: + return Math.round(value * year); + } +}; + +// dist/browser/lib/jwt_claims_set.js +var normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ""); +var checkAudiencePresence = (audPayload, audOption) => { + if (typeof audPayload === "string") { + return audOption.includes(audPayload); + } + if (Array.isArray(audPayload)) { + return audOption.some(Set.prototype.has.bind(new Set(audPayload))); + } + return false; +}; +var jwt_claims_set_default = (protectedHeader, encodedPayload, options = {}) => { + const { typ } = options; + if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { + throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', "typ", "check_failed"); + } + let payload; + try { + payload = JSON.parse(decoder.decode(encodedPayload)); + } catch (_a) { + } + if (!isObject(payload)) { + throw new JWTInvalid("JWT Claims Set must be a top-level JSON object"); + } + const { issuer } = options; + if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { + throw new JWTClaimValidationFailed('unexpected "iss" claim value', "iss", "check_failed"); + } + const { subject } = options; + if (subject && payload.sub !== subject) { + throw new JWTClaimValidationFailed('unexpected "sub" claim value', "sub", "check_failed"); + } + const { audience } = options; + if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) { + throw new JWTClaimValidationFailed('unexpected "aud" claim value', "aud", "check_failed"); + } + let tolerance; + switch (typeof options.clockTolerance) { + case "string": + tolerance = secs_default(options.clockTolerance); + break; + case "number": + tolerance = options.clockTolerance; + break; + case "undefined": + tolerance = 0; + break; + default: + throw new TypeError("Invalid clockTolerance option type"); + } + const { currentDate } = options; + const now = epoch_default(currentDate || /* @__PURE__ */ new Date()); + if ((payload.iat !== void 0 || options.maxTokenAge) && typeof payload.iat !== "number") { + throw new JWTClaimValidationFailed('"iat" claim must be a number', "iat", "invalid"); + } + if (payload.nbf !== void 0) { + if (typeof payload.nbf !== "number") { + throw new JWTClaimValidationFailed('"nbf" claim must be a number', "nbf", "invalid"); + } + if (payload.nbf > now + tolerance) { + throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', "nbf", "check_failed"); + } + } + if (payload.exp !== void 0) { + if (typeof payload.exp !== "number") { + throw new JWTClaimValidationFailed('"exp" claim must be a number', "exp", "invalid"); + } + if (payload.exp <= now - tolerance) { + throw new JWTExpired('"exp" claim timestamp check failed', "exp", "check_failed"); + } + } + if (options.maxTokenAge) { + const age = now - payload.iat; + const max = typeof options.maxTokenAge === "number" ? options.maxTokenAge : secs_default(options.maxTokenAge); + if (age - tolerance > max) { + throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', "iat", "check_failed"); + } + if (age < 0 - tolerance) { + throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', "iat", "check_failed"); + } + } + return payload; +}; + +// dist/browser/jwt/verify.js +async function jwtVerify(jwt, key, options) { + var _a; + const verified = await compactVerify(jwt, key, options); + if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes("b64")) && verified.protectedHeader.b64 === false) { + throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); + } + const payload = jwt_claims_set_default(verified.protectedHeader, verified.payload, options); + const result = { payload, protectedHeader: verified.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: verified.key }; + } + return result; +} + +// dist/browser/jwt/decrypt.js +async function jwtDecrypt(jwt, key, options) { + const decrypted = await compactDecrypt(jwt, key, options); + const payload = jwt_claims_set_default(decrypted.protectedHeader, decrypted.plaintext, options); + const { protectedHeader } = decrypted; + if (protectedHeader.iss !== void 0 && protectedHeader.iss !== payload.iss) { + throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', "iss", "mismatch"); + } + if (protectedHeader.sub !== void 0 && protectedHeader.sub !== payload.sub) { + throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', "sub", "mismatch"); + } + if (protectedHeader.aud !== void 0 && JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { + throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', "aud", "mismatch"); + } + const result = { payload, protectedHeader }; + if (typeof key === "function") { + return { ...result, key: decrypted.key }; + } + return result; +} + +// dist/browser/jwe/compact/encrypt.js +var CompactEncrypt = class { + constructor(plaintext) { + this._flattened = new FlattenedEncrypt(plaintext); + } + setContentEncryptionKey(cek) { + this._flattened.setContentEncryptionKey(cek); + return this; + } + setInitializationVector(iv) { + this._flattened.setInitializationVector(iv); + return this; + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + setKeyManagementParameters(parameters) { + this._flattened.setKeyManagementParameters(parameters); + return this; + } + async encrypt(key, options) { + const jwe = await this._flattened.encrypt(key, options); + return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join("."); + } +}; + +// dist/browser/runtime/sign.js +var sign = async (alg, key, data) => { + const cryptoKey = await getCryptoKey3(alg, key, "sign"); + check_key_length_default(alg, cryptoKey); + const signature = await webcrypto_default.subtle.sign(subtleDsa(alg, cryptoKey.algorithm), cryptoKey, data); + return new Uint8Array(signature); +}; +var sign_default = sign; + +// dist/browser/jws/flattened/sign.js +var FlattenedSign = class { + constructor(payload) { + if (!(payload instanceof Uint8Array)) { + throw new TypeError("payload must be an instance of Uint8Array"); + } + this._payload = payload; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + async sign(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader) { + throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()"); + } + if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader)) { + throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader + }; + const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + let b64 = true; + if (extensions.has("b64")) { + b64 = this._protectedHeader.b64; + if (typeof b64 !== "boolean") { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + check_key_type_default(alg, key, "sign"); + let payload = this._payload; + if (b64) { + payload = encoder.encode(encode(payload)); + } + let protectedHeader; + if (this._protectedHeader) { + protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); + } else { + protectedHeader = encoder.encode(""); + } + const data = concat(protectedHeader, encoder.encode("."), payload); + const signature = await sign_default(alg, key, data); + const jws = { + signature: encode(signature), + payload: "" + }; + if (b64) { + jws.payload = decoder.decode(payload); + } + if (this._unprotectedHeader) { + jws.header = this._unprotectedHeader; + } + if (this._protectedHeader) { + jws.protected = decoder.decode(protectedHeader); + } + return jws; + } +}; + +// dist/browser/jws/compact/sign.js +var CompactSign = class { + constructor(payload) { + this._flattened = new FlattenedSign(payload); + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + async sign(key, options) { + const jws = await this._flattened.sign(key, options); + if (jws.payload === void 0) { + throw new TypeError("use the flattened module for creating JWS with b64: false"); + } + return `${jws.protected}.${jws.payload}.${jws.signature}`; + } +}; + +// dist/browser/jws/general/sign.js +var IndividualSignature = class { + constructor(sig, key, options) { + this.parent = sig; + this.key = key; + this.options = options; + } + setProtectedHeader(protectedHeader) { + if (this.protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this.protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addSignature(...args) { + return this.parent.addSignature(...args); + } + sign(...args) { + return this.parent.sign(...args); + } + done() { + return this.parent; + } +}; +var GeneralSign = class { + constructor(payload) { + this._signatures = []; + this._payload = payload; + } + addSignature(key, options) { + const signature = new IndividualSignature(this, key, options); + this._signatures.push(signature); + return signature; + } + async sign() { + if (!this._signatures.length) { + throw new JWSInvalid("at least one signature must be added"); + } + const jws = { + signatures: [], + payload: "" + }; + for (let i = 0; i < this._signatures.length; i++) { + const signature = this._signatures[i]; + const flattened = new FlattenedSign(this._payload); + flattened.setProtectedHeader(signature.protectedHeader); + flattened.setUnprotectedHeader(signature.unprotectedHeader); + const { payload, ...rest } = await flattened.sign(signature.key, signature.options); + if (i === 0) { + jws.payload = payload; + } else if (jws.payload !== payload) { + throw new JWSInvalid("inconsistent use of JWS Unencoded Payload Option (RFC7797)"); + } + jws.signatures.push(rest); + } + return jws; + } +}; + +// dist/browser/jwt/produce.js +var ProduceJWT = class { + constructor(payload) { + if (!isObject(payload)) { + throw new TypeError("JWT Claims Set MUST be an object"); + } + this._payload = payload; + } + setIssuer(issuer) { + this._payload = { ...this._payload, iss: issuer }; + return this; + } + setSubject(subject) { + this._payload = { ...this._payload, sub: subject }; + return this; + } + setAudience(audience) { + this._payload = { ...this._payload, aud: audience }; + return this; + } + setJti(jwtId) { + this._payload = { ...this._payload, jti: jwtId }; + return this; + } + setNotBefore(input) { + if (typeof input === "number") { + this._payload = { ...this._payload, nbf: input }; + } else { + this._payload = { ...this._payload, nbf: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; + } + return this; + } + setExpirationTime(input) { + if (typeof input === "number") { + this._payload = { ...this._payload, exp: input }; + } else { + this._payload = { ...this._payload, exp: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; + } + return this; + } + setIssuedAt(input) { + if (typeof input === "undefined") { + this._payload = { ...this._payload, iat: epoch_default(/* @__PURE__ */ new Date()) }; + } else { + this._payload = { ...this._payload, iat: input }; + } + return this; + } +}; + +// dist/browser/jwt/sign.js +var SignJWT = class extends ProduceJWT { + setProtectedHeader(protectedHeader) { + this._protectedHeader = protectedHeader; + return this; + } + async sign(key, options) { + var _a; + const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); + sig.setProtectedHeader(this._protectedHeader); + if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && this._protectedHeader.crit.includes("b64") && this._protectedHeader.b64 === false) { + throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); + } + return sig.sign(key, options); + } +}; + +// dist/browser/jwt/encrypt.js +var EncryptJWT = class extends ProduceJWT { + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError("setKeyManagementParameters can only be called once"); + } + this._keyManagementParameters = parameters; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError("setContentEncryptionKey can only be called once"); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError("setInitializationVector can only be called once"); + } + this._iv = iv; + return this; + } + replicateIssuerAsHeader() { + this._replicateIssuerAsHeader = true; + return this; + } + replicateSubjectAsHeader() { + this._replicateSubjectAsHeader = true; + return this; + } + replicateAudienceAsHeader() { + this._replicateAudienceAsHeader = true; + return this; + } + async encrypt(key, options) { + const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); + if (this._replicateIssuerAsHeader) { + this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; + } + if (this._replicateSubjectAsHeader) { + this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; + } + if (this._replicateAudienceAsHeader) { + this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; + } + enc.setProtectedHeader(this._protectedHeader); + if (this._iv) { + enc.setInitializationVector(this._iv); + } + if (this._cek) { + enc.setContentEncryptionKey(this._cek); + } + if (this._keyManagementParameters) { + enc.setKeyManagementParameters(this._keyManagementParameters); + } + return enc.encrypt(key, options); + } +}; + +// dist/browser/jwk/thumbprint.js +var check = (value, description) => { + if (typeof value !== "string" || !value) { + throw new JWKInvalid(`${description} missing or invalid`); + } +}; +async function calculateJwkThumbprint(jwk, digestAlgorithm) { + if (!isObject(jwk)) { + throw new TypeError("JWK must be an object"); + } + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; + if (digestAlgorithm !== "sha256" && digestAlgorithm !== "sha384" && digestAlgorithm !== "sha512") { + throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); + } + let components; + switch (jwk.kty) { + case "EC": + check(jwk.crv, '"crv" (Curve) Parameter'); + check(jwk.x, '"x" (X Coordinate) Parameter'); + check(jwk.y, '"y" (Y Coordinate) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; + break; + case "OKP": + check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); + check(jwk.x, '"x" (Public Key) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; + break; + case "RSA": + check(jwk.e, '"e" (Exponent) Parameter'); + check(jwk.n, '"n" (Modulus) Parameter'); + components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; + break; + case "oct": + check(jwk.k, '"k" (Key Value) Parameter'); + components = { k: jwk.k, kty: jwk.kty }; + break; + default: + throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); + } + const data = encoder.encode(JSON.stringify(components)); + return encode(await digest_default(digestAlgorithm, data)); +} +async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; + const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); + return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; +} + +// dist/browser/jwk/embedded.js +async function EmbeddedJWK(protectedHeader, token) { + const joseHeader = { + ...protectedHeader, + ...token.header + }; + if (!isObject(joseHeader.jwk)) { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); + } + const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); + if (key instanceof Uint8Array || key.type !== "public") { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); + } + return key; +} + +// dist/browser/jwks/local.js +function getKtyFromAlg(alg) { + switch (typeof alg === "string" && alg.slice(0, 2)) { + case "RS": + case "PS": + return "RSA"; + case "ES": + return "EC"; + case "Ed": + return "OKP"; + default: + throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); + } +} +function isJWKSLike(jwks) { + return jwks && typeof jwks === "object" && Array.isArray(jwks.keys) && jwks.keys.every(isJWKLike); +} +function isJWKLike(key) { + return isObject(key); +} +function clone(obj) { + if (typeof structuredClone === "function") { + return structuredClone(obj); + } + return JSON.parse(JSON.stringify(obj)); +} +var LocalJWKSet = class { + constructor(jwks) { + this._cached = /* @__PURE__ */ new WeakMap(); + if (!isJWKSLike(jwks)) { + throw new JWKSInvalid("JSON Web Key Set malformed"); + } + this._jwks = clone(jwks); + } + async getKey(protectedHeader, token) { + const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; + const kty = getKtyFromAlg(alg); + const candidates = this._jwks.keys.filter((jwk2) => { + let candidate = kty === jwk2.kty; + if (candidate && typeof kid === "string") { + candidate = kid === jwk2.kid; + } + if (candidate && typeof jwk2.alg === "string") { + candidate = alg === jwk2.alg; + } + if (candidate && typeof jwk2.use === "string") { + candidate = jwk2.use === "sig"; + } + if (candidate && Array.isArray(jwk2.key_ops)) { + candidate = jwk2.key_ops.includes("verify"); + } + if (candidate && alg === "EdDSA") { + candidate = jwk2.crv === "Ed25519" || jwk2.crv === "Ed448"; + } + if (candidate) { + switch (alg) { + case "ES256": + candidate = jwk2.crv === "P-256"; + break; + case "ES256K": + candidate = jwk2.crv === "secp256k1"; + break; + case "ES384": + candidate = jwk2.crv === "P-384"; + break; + case "ES512": + candidate = jwk2.crv === "P-521"; + break; + } + } + return candidate; + }); + const { 0: jwk, length } = candidates; + if (length === 0) { + throw new JWKSNoMatchingKey(); + } else if (length !== 1) { + const error = new JWKSMultipleMatchingKeys(); + const { _cached } = this; + error[Symbol.asyncIterator] = async function* () { + for (const jwk2 of candidates) { + try { + yield await importWithAlgCache(_cached, jwk2, alg); + } catch (_a) { + continue; + } + } + }; + throw error; + } + return importWithAlgCache(this._cached, jwk, alg); + } +}; +async function importWithAlgCache(cache, jwk, alg) { + const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); + if (cached[alg] === void 0) { + const keyObject = await importJWK({ ...jwk, ext: true }, alg); + if (keyObject.type !== "public") { + throw new JWKSInvalid("JSON Web Key Set members must be public keys"); + } + cached[alg] = keyObject; + } + return cached[alg]; +} +function createLocalJWKSet(jwks) { + return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); +} + +// dist/browser/runtime/fetch_jwks.js +var fetchJwks = async (url, timeout, options) => { + let controller; + let id; + let timedOut = false; + if (typeof AbortController === "function") { + controller = new AbortController(); + id = setTimeout(() => { + timedOut = true; + controller.abort(); + }, timeout); + } + const response = await fetch(url.href, { + signal: controller ? controller.signal : void 0, + redirect: "manual", + headers: options.headers + }).catch((err) => { + if (timedOut) + throw new JWKSTimeout(); + throw err; + }); + if (id !== void 0) + clearTimeout(id); + if (response.status !== 200) { + throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response"); + } + try { + return await response.json(); + } catch (_a) { + throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON"); + } +}; +var fetch_jwks_default = fetchJwks; + +// dist/browser/jwks/remote.js +var RemoteJWKSet = class extends LocalJWKSet { + constructor(url, options) { + super({ keys: [] }); + this._jwks = void 0; + if (!(url instanceof URL)) { + throw new TypeError("url must be an instance of URL"); + } + this._url = new URL(url.href); + this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; + this._timeoutDuration = typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === "number" ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5e3; + this._cooldownDuration = typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === "number" ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 3e4; + this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === "number" ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 6e5; + } + coolingDown() { + return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cooldownDuration : false; + } + fresh() { + return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cacheMaxAge : false; + } + async getKey(protectedHeader, token) { + if (!this._jwks || !this.fresh()) { + await this.reload(); + } + try { + return await super.getKey(protectedHeader, token); + } catch (err) { + if (err instanceof JWKSNoMatchingKey) { + if (this.coolingDown() === false) { + await this.reload(); + return super.getKey(protectedHeader, token); + } + } + throw err; + } + } + async reload() { + if (this._pendingFetch && isCloudflareWorkers()) { + return new Promise((resolve) => { + const isDone = () => { + if (this._pendingFetch === void 0) { + resolve(); + } else { + setTimeout(isDone, 5); + } + }; + isDone(); + }); + } + if (!this._pendingFetch) { + this._pendingFetch = fetch_jwks_default(this._url, this._timeoutDuration, this._options).then((json) => { + if (!isJWKSLike(json)) { + throw new JWKSInvalid("JSON Web Key Set malformed"); + } + this._jwks = { keys: json.keys }; + this._jwksTimestamp = Date.now(); + this._pendingFetch = void 0; + }).catch((err) => { + this._pendingFetch = void 0; + throw err; + }); + } + await this._pendingFetch; + } +}; +function createRemoteJWKSet(url, options) { + return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); +} + +// dist/browser/jwt/unsecured.js +var UnsecuredJWT = class extends ProduceJWT { + encode() { + const header = encode(JSON.stringify({ alg: "none" })); + const payload = encode(JSON.stringify(this._payload)); + return `${header}.${payload}.`; + } + static decode(jwt, options) { + if (typeof jwt !== "string") { + throw new JWTInvalid("Unsecured JWT must be a string"); + } + const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split("."); + if (length !== 3 || signature !== "") { + throw new JWTInvalid("Invalid Unsecured JWT"); + } + let header; + try { + header = JSON.parse(decoder.decode(decode(encodedHeader))); + if (header.alg !== "none") + throw new Error(); + } catch (_a) { + throw new JWTInvalid("Invalid Unsecured JWT"); + } + const payload = jwt_claims_set_default(header, decode(encodedPayload), options); + return { payload, header }; + } +}; + +// dist/browser/util/base64url.js +var base64url_exports2 = {}; +__export(base64url_exports2, { + decode: () => decode2, + encode: () => encode2 +}); +var encode2 = encode; +var decode2 = decode; + +// dist/browser/util/decode_protected_header.js +function decodeProtectedHeader(token) { + let protectedB64u; + if (typeof token === "string") { + const parts = token.split("."); + if (parts.length === 3 || parts.length === 5) { + ; + [protectedB64u] = parts; + } + } else if (typeof token === "object" && token) { + if ("protected" in token) { + protectedB64u = token.protected; + } else { + throw new TypeError("Token does not contain a Protected Header"); + } + } + try { + if (typeof protectedB64u !== "string" || !protectedB64u) { + throw new Error(); + } + const result = JSON.parse(decoder.decode(decode2(protectedB64u))); + if (!isObject(result)) { + throw new Error(); + } + return result; + } catch (_a) { + throw new TypeError("Invalid Token or Protected Header formatting"); + } +} + +// dist/browser/util/decode_jwt.js +function decodeJwt(jwt) { + if (typeof jwt !== "string") + throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string"); + const { 1: payload, length } = jwt.split("."); + if (length === 5) + throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded"); + if (length !== 3) + throw new JWTInvalid("Invalid JWT"); + if (!payload) + throw new JWTInvalid("JWTs must contain a payload"); + let decoded; + try { + decoded = decode2(payload); + } catch (_a) { + throw new JWTInvalid("Failed to parse the base64url encoded payload"); + } + let result; + try { + result = JSON.parse(decoder.decode(decoded)); + } catch (_b) { + throw new JWTInvalid("Failed to parse the decoded payload as JSON"); + } + if (!isObject(result)) + throw new JWTInvalid("Invalid JWT Claims Set"); + return result; +} + +// dist/browser/runtime/generate.js +async function generateSecret(alg, options) { + var _a; + let length; + let algorithm; + let keyUsages; + switch (alg) { + case "HS256": + case "HS384": + case "HS512": + length = parseInt(alg.slice(-3), 10); + algorithm = { name: "HMAC", hash: `SHA-${length}`, length }; + keyUsages = ["sign", "verify"]; + break; + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + length = parseInt(alg.slice(-3), 10); + return random_default(new Uint8Array(length >> 3)); + case "A128KW": + case "A192KW": + case "A256KW": + length = parseInt(alg.slice(1, 4), 10); + algorithm = { name: "AES-KW", length }; + keyUsages = ["wrapKey", "unwrapKey"]; + break; + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": + case "A128GCM": + case "A192GCM": + case "A256GCM": + length = parseInt(alg.slice(1, 4), 10); + algorithm = { name: "AES-GCM", length }; + keyUsages = ["encrypt", "decrypt"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + return webcrypto_default.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); +} +function getModulusLengthOption(options) { + var _a; + const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; + if (typeof modulusLength !== "number" || modulusLength < 2048) { + throw new JOSENotSupported("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used"); + } + return modulusLength; +} +async function generateKeyPair(alg, options) { + var _a, _b, _c, _d; + let algorithm; + let keyUsages; + switch (alg) { + case "PS256": + case "PS384": + case "PS512": + algorithm = { + name: "RSA-PSS", + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: getModulusLengthOption(options) + }; + keyUsages = ["sign", "verify"]; + break; + case "RS256": + case "RS384": + case "RS512": + algorithm = { + name: "RSASSA-PKCS1-v1_5", + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: getModulusLengthOption(options) + }; + keyUsages = ["sign", "verify"]; + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + algorithm = { + name: "RSA-OAEP", + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: getModulusLengthOption(options) + }; + keyUsages = ["decrypt", "unwrapKey", "encrypt", "wrapKey"]; + break; + case "ES256": + algorithm = { name: "ECDSA", namedCurve: "P-256" }; + keyUsages = ["sign", "verify"]; + break; + case "ES384": + algorithm = { name: "ECDSA", namedCurve: "P-384" }; + keyUsages = ["sign", "verify"]; + break; + case "ES512": + algorithm = { name: "ECDSA", namedCurve: "P-521" }; + keyUsages = ["sign", "verify"]; + break; + case "EdDSA": + keyUsages = ["sign", "verify"]; + const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : "Ed25519"; + switch (crv) { + case "Ed25519": + case "Ed448": + algorithm = { name: crv }; + break; + default: + throw new JOSENotSupported("Invalid or unsupported crv option provided"); + } + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + keyUsages = ["deriveKey", "deriveBits"]; + const crv2 = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : "P-256"; + switch (crv2) { + case "P-256": + case "P-384": + case "P-521": { + algorithm = { name: "ECDH", namedCurve: crv2 }; + break; + } + case "X25519": + case "X448": + algorithm = { name: crv2 }; + break; + default: + throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448"); + } + break; + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + try { + return await webcrypto_default.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages); + } catch (err) { + if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { + algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + return await webcrypto_default.subtle.generateKey(algorithm, (_d = options === null || options === void 0 ? void 0 : options.extractable) !== null && _d !== void 0 ? _d : false, keyUsages); + } + throw err; + } +} + +// dist/browser/key/generate_key_pair.js +async function generateKeyPair2(alg, options) { + return generateKeyPair(alg, options); +} + +// dist/browser/key/generate_secret.js +async function generateSecret2(alg, options) { + return generateSecret(alg, options); +} +export { + CompactEncrypt, + CompactSign, + EmbeddedJWK, + EncryptJWT, + FlattenedEncrypt, + FlattenedSign, + GeneralEncrypt, + GeneralSign, + SignJWT, + UnsecuredJWT, + base64url_exports2 as base64url, + calculateJwkThumbprint, + calculateJwkThumbprintUri, + compactDecrypt, + compactVerify, + createLocalJWKSet, + createRemoteJWKSet, + decodeJwt, + decodeProtectedHeader, + errors_exports as errors, + exportJWK, + exportPKCS8, + exportSPKI, + flattenedDecrypt, + flattenedVerify, + generalDecrypt, + generalVerify, + generateKeyPair2 as generateKeyPair, + generateSecret2 as generateSecret, + importJWK, + importPKCS8, + importSPKI, + importX509, + jwtDecrypt, + jwtVerify +}; diff --git a/dist/browser/index.bundle.min.js b/dist/browser/index.bundle.min.js new file mode 100644 index 0000000000..c0fdbc9842 --- /dev/null +++ b/dist/browser/index.bundle.min.js @@ -0,0 +1,4 @@ +var qt=Object.defineProperty;var ct=(e,t)=>{for(var r in t)qt(e,r,{get:t[r],enumerable:!0})};var f=crypto,b=e=>e instanceof CryptoKey;var Zt=async(e,t)=>{let r=`SHA-${e.slice(-3)}`;return new Uint8Array(await f.subtle.digest(r,t))},Ke=Zt;var E=new TextEncoder,v=new TextDecoder,xe=2**32;function W(...e){let t=e.reduce((o,{length:a})=>o+a,0),r=new Uint8Array(t),n=0;return e.forEach(o=>{r.set(o,n),n+=o.length}),r}function dt(e,t){return W(E.encode(e),new Uint8Array([0]),t)}function ke(e,t,r){if(t<0||t>=xe)throw new RangeError(`value must be >= 0 and <= ${xe-1}. Received ${t}`);e.set([t>>>24,t>>>16,t>>>8,t&255],r)}function He(e){let t=Math.floor(e/xe),r=e%xe,n=new Uint8Array(8);return ke(n,t,0),ke(n,r,4),n}function Ce(e){let t=new Uint8Array(4);return ke(t,e),t}function Pe(e){return W(Ce(e.length),e)}async function pt(e,t,r){let n=Math.ceil((t>>3)/32),o=new Uint8Array(n*32);for(let a=0;a>3)}var We=e=>{let t=e;typeof t=="string"&&(t=E.encode(t));let r=32768,n=[];for(let o=0;oWe(e).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_"),Be=e=>{let t=atob(e),r=new Uint8Array(t.length);for(let n=0;n{let t=e;t instanceof Uint8Array&&(t=v.decode(t)),t=t.replace(/-/g,"+").replace(/_/g,"/").replace(/\s/g,"");try{return Be(t)}catch(r){throw new TypeError("The input to be decoded is not correctly encoded.")}};var ft={};ct(ft,{JOSEAlgNotAllowed:()=>B,JOSEError:()=>C,JOSENotSupported:()=>l,JWEDecryptionFailed:()=>M,JWEInvalid:()=>u,JWKInvalid:()=>pe,JWKSInvalid:()=>L,JWKSMultipleMatchingKeys:()=>ue,JWKSNoMatchingKey:()=>q,JWKSTimeout:()=>fe,JWSInvalid:()=>h,JWSSignatureVerificationFailed:()=>Z,JWTClaimValidationFailed:()=>J,JWTExpired:()=>re,JWTInvalid:()=>H});var C=class extends Error{static get code(){return"ERR_JOSE_GENERIC"}constructor(t){var r;super(t),this.code="ERR_JOSE_GENERIC",this.name=this.constructor.name,(r=Error.captureStackTrace)===null||r===void 0||r.call(Error,this,this.constructor)}},J=class extends C{static get code(){return"ERR_JWT_CLAIM_VALIDATION_FAILED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_CLAIM_VALIDATION_FAILED",this.claim=r,this.reason=n}},re=class extends C{static get code(){return"ERR_JWT_EXPIRED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_EXPIRED",this.claim=r,this.reason=n}},B=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_ALG_NOT_ALLOWED"}static get code(){return"ERR_JOSE_ALG_NOT_ALLOWED"}},l=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_NOT_SUPPORTED"}static get code(){return"ERR_JOSE_NOT_SUPPORTED"}},M=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_DECRYPTION_FAILED",this.message="decryption operation failed"}static get code(){return"ERR_JWE_DECRYPTION_FAILED"}},u=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_INVALID"}static get code(){return"ERR_JWE_INVALID"}},h=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_INVALID"}static get code(){return"ERR_JWS_INVALID"}},H=class extends C{constructor(){super(...arguments),this.code="ERR_JWT_INVALID"}static get code(){return"ERR_JWT_INVALID"}},pe=class extends C{constructor(){super(...arguments),this.code="ERR_JWK_INVALID"}static get code(){return"ERR_JWK_INVALID"}},L=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_INVALID"}static get code(){return"ERR_JWKS_INVALID"}},q=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_NO_MATCHING_KEY",this.message="no applicable key found in the JSON Web Key Set"}static get code(){return"ERR_JWKS_NO_MATCHING_KEY"}},ue=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_MULTIPLE_MATCHING_KEYS",this.message="multiple matching keys found in the JSON Web Key Set"}static get code(){return"ERR_JWKS_MULTIPLE_MATCHING_KEYS"}},fe=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_TIMEOUT",this.message="request timed out"}static get code(){return"ERR_JWKS_TIMEOUT"}},Z=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED",this.message="signature verification failed"}static get code(){return"ERR_JWS_SIGNATURE_VERIFICATION_FAILED"}};var $=f.getRandomValues.bind(f);function Le(e){switch(e){case"A128GCM":case"A128GCMKW":case"A192GCM":case"A192GCMKW":case"A256GCM":case"A256GCMKW":return 96;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return 128;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var Je=e=>$(new Uint8Array(Le(e)>>3));var Qt=(e,t)=>{if(t.length<<3!==Le(e))throw new u("Invalid Initialization Vector length")},Te=Qt;var jt=(e,t)=>{let r=e.byteLength<<3;if(r!==t)throw new u(`Invalid Content Encryption Key length. Expected ${t} bits, got ${r} bits`)},ne=jt;var er=(e,t)=>{if(!(e instanceof Uint8Array))throw new TypeError("First argument must be a buffer");if(!(t instanceof Uint8Array))throw new TypeError("Second argument must be a buffer");if(e.length!==t.length)throw new TypeError("Input buffers must have the same length");let r=e.length,n=0,o=-1;for(;++oe.usages.includes(r))){let r="CryptoKey does not support this operation, its usages must include ";if(t.length>2){let n=t.pop();r+=`one of ${t.join(", ")}, or ${n}.`}else t.length===2?r+=`one of ${t[0]} or ${t[1]}.`:r+=`${t[0]}.`;throw new TypeError(r)}}function ht(e,t,...r){switch(t){case"HS256":case"HS384":case"HS512":{if(!N(e.algorithm,"HMAC"))throw P("HMAC");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"RS256":case"RS384":case"RS512":{if(!N(e.algorithm,"RSASSA-PKCS1-v1_5"))throw P("RSASSA-PKCS1-v1_5");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"PS256":case"PS384":case"PS512":{if(!N(e.algorithm,"RSA-PSS"))throw P("RSA-PSS");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"EdDSA":{if(e.algorithm.name!=="Ed25519"&&e.algorithm.name!=="Ed448"){if(D()){if(N(e.algorithm,"NODE-ED25519"))break;throw P("Ed25519, Ed448, or NODE-ED25519")}throw P("Ed25519 or Ed448")}break}case"ES256":case"ES384":case"ES512":{if(!N(e.algorithm,"ECDSA"))throw P("ECDSA");let n=tr(t);if(e.algorithm.namedCurve!==n)throw P(n,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r)}function I(e,t,...r){switch(t){case"A128GCM":case"A192GCM":case"A256GCM":{if(!N(e.algorithm,"AES-GCM"))throw P("AES-GCM");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"A128KW":case"A192KW":case"A256KW":{if(!N(e.algorithm,"AES-KW"))throw P("AES-KW");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"ECDH":{switch(e.algorithm.name){case"ECDH":case"X25519":case"X448":break;default:throw P("ECDH, X25519, or X448")}break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":if(!N(e.algorithm,"PBKDF2"))throw P("PBKDF2");break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(!N(e.algorithm,"RSA-OAEP"))throw P("RSA-OAEP");let n=parseInt(t.slice(9),10)||1;if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r)}function yt(e,t,...r){if(r.length>2){let n=r.pop();e+=`one of type ${r.join(", ")}, or ${n}.`}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t=="function"&&t.name?e+=` Received function ${t.name}`:typeof t=="object"&&t!=null&&t.constructor&&t.constructor.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var A=(e,...t)=>yt("Key must be ",e,...t);function $e(e,t,...r){return yt(`Key for the ${e} algorithm must be `,t,...r)}var Ge=e=>b(e),y=["CryptoKey"];async function rr(e,t,r,n,o,a){if(!(t instanceof Uint8Array))throw new TypeError(A(t,"Uint8Array"));let i=parseInt(e.slice(1,4),10),s=await f.subtle.importKey("raw",t.subarray(i>>3),"AES-CBC",!1,["decrypt"]),c=await f.subtle.importKey("raw",t.subarray(0,i>>3),{hash:`SHA-${i<<1}`,name:"HMAC"},!1,["sign"]),d=W(a,n,r,He(a.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",c,d)).slice(0,i>>3)),m;try{m=lt(o,p)}catch(T){}if(!m)throw new M;let K;try{K=new Uint8Array(await f.subtle.decrypt({iv:n,name:"AES-CBC"},s,r))}catch(T){}if(!K)throw new M;return K}async function nr(e,t,r,n,o,a){let i;t instanceof Uint8Array?i=await f.subtle.importKey("raw",t,"AES-GCM",!1,["decrypt"]):(I(t,e,"decrypt"),i=t);try{return new Uint8Array(await f.subtle.decrypt({additionalData:a,iv:n,name:"AES-GCM",tagLength:128},i,W(r,o)))}catch(s){throw new M}}var or=async(e,t,r,n,o,a)=>{if(!b(t)&&!(t instanceof Uint8Array))throw new TypeError(A(t,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(-3),10)),rr(e,t,r,n,o,a);case"A128GCM":case"A192GCM":case"A256GCM":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(1,4),10)),nr(e,t,r,n,o,a);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},De=or;var wt=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.')},Et=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.')};var ar=(...e)=>{let t=e.filter(Boolean);if(t.length===0||t.length===1)return!0;let r;for(let n of t){let o=Object.keys(n);if(!r||r.size===0){r=new Set(o);continue}for(let a of o){if(r.has(a))return!1;r.add(a)}}return!0},R=ar;function ir(e){return typeof e=="object"&&e!==null}function w(e){if(!ir(e)||Object.prototype.toString.call(e)!=="[object Object]")return!1;if(Object.getPrototypeOf(e)===null)return!0;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}var sr=[{hash:"SHA-256",name:"HMAC"},!0,["sign"]],oe=sr;function gt(e,t){if(e.algorithm.length!==parseInt(t.slice(1,4),10))throw new TypeError(`Invalid key size for alg: ${t}`)}function St(e,t,r){if(b(e))return I(e,t,r),e;if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"AES-KW",!0,[r]);throw new TypeError(A(e,...y,"Uint8Array"))}var le=async(e,t,r)=>{let n=await St(t,e,"wrapKey");gt(n,e);let o=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",o,n,"AES-KW"))},me=async(e,t,r)=>{let n=await St(t,e,"unwrapKey");gt(n,e);let o=await f.subtle.unwrapKey("raw",r,n,"AES-KW",...oe);return new Uint8Array(await f.subtle.exportKey("raw",o))};async function Re(e,t,r,n,o=new Uint8Array(0),a=new Uint8Array(0)){if(!b(e))throw new TypeError(A(e,...y));if(I(e,"ECDH"),!b(t))throw new TypeError(A(t,...y));I(t,"ECDH","deriveBits");let i=W(Pe(E.encode(r)),Pe(o),Pe(a),Ce(n)),s;e.algorithm.name==="X25519"?s=256:e.algorithm.name==="X448"?s=448:s=Math.ceil(parseInt(e.algorithm.namedCurve.substr(-3),10)/8)<<3;let c=new Uint8Array(await f.subtle.deriveBits({name:e.algorithm.name,public:e},t,s));return pt(c,n,i)}async function At(e){if(!b(e))throw new TypeError(A(e,...y));return f.subtle.generateKey(e.algorithm,!0,["deriveBits"])}function Oe(e){if(!b(e))throw new TypeError(A(e,...y));return["P-256","P-384","P-521"].includes(e.algorithm.namedCurve)||e.algorithm.name==="X25519"||e.algorithm.name==="X448"}function Ve(e){if(!(e instanceof Uint8Array)||e.length<8)throw new u("PBES2 Salt Input must be 8 or more octets")}function cr(e,t){if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"PBKDF2",!1,["deriveBits"]);if(b(e))return I(e,t,"deriveBits","deriveKey"),e;throw new TypeError(A(e,...y,"Uint8Array"))}async function _t(e,t,r,n){Ve(e);let o=dt(t,e),a=parseInt(t.slice(13,16),10),i={hash:`SHA-${t.slice(8,11)}`,iterations:r,name:"PBKDF2",salt:o},s={length:a,name:"AES-KW"},c=await cr(n,t);if(c.usages.includes("deriveBits"))return new Uint8Array(await f.subtle.deriveBits(i,c,a));if(c.usages.includes("deriveKey"))return f.subtle.deriveKey(i,c,s,!1,["wrapKey","unwrapKey"]);throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"')}var vt=async(e,t,r,n=2048,o=$(new Uint8Array(16)))=>{let a=await _t(o,e,n,t);return{encryptedKey:await le(e.slice(-6),a,r),p2c:n,p2s:g(o)}},Kt=async(e,t,r,n,o)=>{let a=await _t(o,e,n,t);return me(e.slice(-6),a,r)};function ae(e){switch(e){case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":return"RSA-OAEP";default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}var Q=(e,t)=>{if(e.startsWith("RS")||e.startsWith("PS")){let{modulusLength:r}=t.algorithm;if(typeof r!="number"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}};var xt=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"encrypt","wrapKey"),Q(e,t),t.usages.includes("encrypt"))return new Uint8Array(await f.subtle.encrypt(ae(e),t,r));if(t.usages.includes("wrapKey")){let n=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",n,t,ae(e)))}throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation')},Ht=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"decrypt","unwrapKey"),Q(e,t),t.usages.includes("decrypt"))return new Uint8Array(await f.subtle.decrypt(ae(e),t,r));if(t.usages.includes("unwrapKey")){let n=await f.subtle.unwrapKey("raw",r,t,ae(e),...oe);return new Uint8Array(await f.subtle.exportKey("raw",n))}throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation')};function he(e){switch(e){case"A128GCM":return 128;case"A192GCM":return 192;case"A256GCM":case"A128CBC-HS256":return 256;case"A192CBC-HS384":return 384;case"A256CBC-HS512":return 512;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var O=e=>$(new Uint8Array(he(e)>>3));var Fe=(e,t)=>{let r=(e.match(/.{1,64}/g)||[]).join(` +`);return`-----BEGIN ${t}----- +${r} +-----END ${t}-----`};var Wt=async(e,t,r)=>{if(!b(r))throw new TypeError(A(r,...y));if(!r.extractable)throw new TypeError("CryptoKey is not extractable");if(r.type!==e)throw new TypeError(`key is not a ${e} key`);return Fe(We(new Uint8Array(await f.subtle.exportKey(t,r))),`${e.toUpperCase()} KEY`)},Jt=e=>Wt("public","spki",e),Tt=e=>Wt("private","pkcs8",e),G=(e,t,r=0)=>{r===0&&(t.unshift(t.length),t.unshift(6));let n=e.indexOf(t[0],r);if(n===-1)return!1;let o=e.subarray(n,n+t.length);return o.length!==t.length?!1:o.every((a,i)=>a===t[i])||G(e,t,n+1)},Ct=e=>{switch(!0){case G(e,[42,134,72,206,61,3,1,7]):return"P-256";case G(e,[43,129,4,0,34]):return"P-384";case G(e,[43,129,4,0,35]):return"P-521";case G(e,[43,101,110]):return"X25519";case G(e,[43,101,111]):return"X448";case G(e,[43,101,112]):return"Ed25519";case G(e,[43,101,113]):return"Ed448";default:throw new l("Invalid or unsupported EC Key Curve or OKP Key Sub Type")}},It=async(e,t,r,n,o)=>{var a,i;let s,c,d=new Uint8Array(atob(r.replace(e,"")).split("").map(m=>m.charCodeAt(0))),p=t==="spki";switch(n){case"PS256":case"PS384":case"PS512":s={name:"RSA-PSS",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RS256":case"RS384":case"RS512":s={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":s={name:"RSA-OAEP",hash:`SHA-${parseInt(n.slice(-3),10)||1}`},c=p?["encrypt","wrapKey"]:["decrypt","unwrapKey"];break;case"ES256":s={name:"ECDSA",namedCurve:"P-256"},c=p?["verify"]:["sign"];break;case"ES384":s={name:"ECDSA",namedCurve:"P-384"},c=p?["verify"]:["sign"];break;case"ES512":s={name:"ECDSA",namedCurve:"P-521"},c=p?["verify"]:["sign"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{let m=Ct(d);s=m.startsWith("P-")?{name:"ECDH",namedCurve:m}:{name:m},c=p?[]:["deriveBits"];break}case"EdDSA":s={name:Ct(d)},c=p?["verify"]:["sign"];break;default:throw new l('Invalid or unsupported "alg" (Algorithm) value')}try{return await f.subtle.importKey(t,d,s,(a=o==null?void 0:o.extractable)!==null&&a!==void 0?a:!1,c)}catch(m){if(s.name==="Ed25519"&&(m==null?void 0:m.name)==="NotSupportedError"&&D())return s={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey(t,d,s,(i=o==null?void 0:o.extractable)!==null&&i!==void 0?i:!1,c);throw m}},Dt=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g,"pkcs8",e,t,r),ze=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g,"spki",e,t,r);function Pt(e){let t=[],r=0;for(;r=128;)r=r*128+e[t]-128,t++;r=r*128+e[t]-128,t++}let n=0;if(e[t]<128)n=e[t],t++;else if(n===128){for(n=0;e[t+n]!==0||e[t+n+1]!==0;){if(n>e.byteLength)throw new TypeError("invalid indefinite form length");n++}let a=t+n+2;return{byteLength:a,contents:e.subarray(t,t+n),raw:e.subarray(0,a)}}else{let a=e[t]&127;t++,n=0;for(let i=0;i{let n;try{n=pr(e)}catch(o){throw new TypeError("failed to parse the X.509 certificate",{cause:o})}return ze(n,t,r)};function ur(e){let t,r;switch(e.kty){case"oct":{switch(e.alg){case"HS256":case"HS384":case"HS512":t={name:"HMAC",hash:`SHA-${e.alg.slice(-3)}`},r=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":throw new l(`${e.alg} keys cannot be imported as CryptoKey instances`);case"A128GCM":case"A192GCM":case"A256GCM":case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":t={name:"AES-GCM"},r=["encrypt","decrypt"];break;case"A128KW":case"A192KW":case"A256KW":t={name:"AES-KW"},r=["wrapKey","unwrapKey"];break;case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":t={name:"PBKDF2"},r=["deriveBits"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"RSA":{switch(e.alg){case"PS256":case"PS384":case"PS512":t={name:"RSA-PSS",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":t={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":t={name:"RSA-OAEP",hash:`SHA-${parseInt(e.alg.slice(-3),10)||1}`},r=e.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"EC":{switch(e.alg){case"ES256":t={name:"ECDSA",namedCurve:"P-256"},r=e.d?["sign"]:["verify"];break;case"ES384":t={name:"ECDSA",namedCurve:"P-384"},r=e.d?["sign"]:["verify"];break;case"ES512":t={name:"ECDSA",namedCurve:"P-521"},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:"ECDH",namedCurve:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"OKP":{switch(e.alg){case"EdDSA":t={name:e.crv},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}default:throw new l('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return{algorithm:t,keyUsages:r}}var fr=async e=>{var t,r;if(!e.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');let{algorithm:n,keyUsages:o}=ur(e),a=[n,(t=e.ext)!==null&&t!==void 0?t:!1,(r=e.key_ops)!==null&&r!==void 0?r:o];if(n.name==="PBKDF2")return f.subtle.importKey("raw",S(e.k),...a);let i={...e};delete i.alg,delete i.use;try{return await f.subtle.importKey("jwk",i,...a)}catch(s){if(n.name==="Ed25519"&&(s==null?void 0:s.name)==="NotSupportedError"&&D())return a[0]={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey("jwk",i,...a);throw s}},Xe=fr;async function lr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PUBLIC KEY-----")!==0)throw new TypeError('"spki" must be SPKI formatted string');return ze(e,t,r)}async function mr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN CERTIFICATE-----")!==0)throw new TypeError('"x509" must be X.509 formatted string');return Ot(e,t,r)}async function hr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PRIVATE KEY-----")!==0)throw new TypeError('"pkcs8" must be PKCS#8 formatted string');return Dt(e,t,r)}async function j(e,t,r){var n;if(!w(e))throw new TypeError("JWK must be an object");switch(t||(t=e.alg),e.kty){case"oct":if(typeof e.k!="string"||!e.k)throw new TypeError('missing "k" (Key Value) Parameter value');return r!=null||(r=e.ext!==!0),r?Xe({...e,alg:t,ext:(n=e.ext)!==null&&n!==void 0?n:!1}):S(e.k);case"RSA":if(e.oth!==void 0)throw new l('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');case"EC":case"OKP":return Xe({...e,alg:t});default:throw new l('Unsupported "kty" (Key Type) Parameter value')}}var yr=(e,t)=>{if(!(t instanceof Uint8Array)){if(!Ge(t))throw new TypeError($e(e,t,...y,"Uint8Array"));if(t.type!=="secret")throw new TypeError(`${y.join(" or ")} instances for symmetric algorithms must be of type "secret"`)}},wr=(e,t,r)=>{if(!Ge(t))throw new TypeError($e(e,t,...y));if(t.type==="secret")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`);if(r==="sign"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`);if(r==="decrypt"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`);if(t.algorithm&&r==="verify"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`);if(t.algorithm&&r==="encrypt"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`)},Er=(e,t,r)=>{e.startsWith("HS")||e==="dir"||e.startsWith("PBES2")||/^A\d{3}(?:GCM)?KW$/.test(e)?yr(e,t):wr(e,t,r)},V=Er;async function gr(e,t,r,n,o){if(!(r instanceof Uint8Array))throw new TypeError(A(r,"Uint8Array"));let a=parseInt(e.slice(1,4),10),i=await f.subtle.importKey("raw",r.subarray(a>>3),"AES-CBC",!1,["encrypt"]),s=await f.subtle.importKey("raw",r.subarray(0,a>>3),{hash:`SHA-${a<<1}`,name:"HMAC"},!1,["sign"]),c=new Uint8Array(await f.subtle.encrypt({iv:n,name:"AES-CBC"},i,t)),d=W(o,n,c,He(o.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",s,d)).slice(0,a>>3));return{ciphertext:c,tag:p}}async function Sr(e,t,r,n,o){let a;r instanceof Uint8Array?a=await f.subtle.importKey("raw",r,"AES-GCM",!1,["encrypt"]):(I(r,e,"encrypt"),a=r);let i=new Uint8Array(await f.subtle.encrypt({additionalData:o,iv:n,name:"AES-GCM",tagLength:128},a,t)),s=i.slice(-16);return{ciphertext:i.slice(0,-16),tag:s}}var Ar=async(e,t,r,n,o)=>{if(!b(r)&&!(r instanceof Uint8Array))throw new TypeError(A(r,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(-3),10)),gr(e,t,r,n,o);case"A128GCM":case"A192GCM":case"A256GCM":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(1,4),10)),Sr(e,t,r,n,o);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},ye=Ar;async function Ut(e,t,r,n){let o=e.slice(0,7);n||(n=Je(o));let{ciphertext:a,tag:i}=await ye(o,r,t,n,new Uint8Array(0));return{encryptedKey:a,iv:g(n),tag:g(i)}}async function Mt(e,t,r,n,o){let a=e.slice(0,7);return De(a,t,r,n,o,new Uint8Array(0))}async function br(e,t,r,n,o){switch(V(e,t,"decrypt"),e){case"dir":{if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");return t}case"ECDH-ES":if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!w(n.epk))throw new u('JOSE Header "epk" (Ephemeral Public Key) missing or invalid');if(!Oe(t))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let a=await j(n.epk,e),i,s;if(n.apu!==void 0){if(typeof n.apu!="string")throw new u('JOSE Header "apu" (Agreement PartyUInfo) invalid');i=S(n.apu)}if(n.apv!==void 0){if(typeof n.apv!="string")throw new u('JOSE Header "apv" (Agreement PartyVInfo) invalid');s=S(n.apv)}let c=await Re(a,t,e==="ECDH-ES"?n.enc:e,e==="ECDH-ES"?he(n.enc):parseInt(e.slice(-5,-2),10),i,s);if(e==="ECDH-ES")return c;if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e.slice(-6),c,r)}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(r===void 0)throw new u("JWE Encrypted Key missing");return Ht(e,t,r)}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.p2c!="number")throw new u('JOSE Header "p2c" (PBES2 Count) missing or invalid');let a=(o==null?void 0:o.maxPBES2Count)||1e4;if(n.p2c>a)throw new u('JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds');if(typeof n.p2s!="string")throw new u('JOSE Header "p2s" (PBES2 Salt) missing or invalid');return Kt(e,t,r,n.p2c,S(n.p2s))}case"A128KW":case"A192KW":case"A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e,t,r)}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.iv!="string")throw new u('JOSE Header "iv" (Initialization Vector) missing or invalid');if(typeof n.tag!="string")throw new u('JOSE Header "tag" (Authentication Tag) missing or invalid');let a=S(n.iv),i=S(n.tag);return Mt(e,t,r,a,i)}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}}var Nt=br;function _r(e,t,r,n,o){if(o.crit!==void 0&&n.crit===void 0)throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');if(!n||n.crit===void 0)return new Set;if(!Array.isArray(n.crit)||n.crit.length===0||n.crit.some(i=>typeof i!="string"||i.length===0))throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let a;r!==void 0?a=new Map([...Object.entries(r),...t.entries()]):a=t;for(let i of n.crit){if(!a.has(i))throw new l(`Extension Header Parameter "${i}" is not recognized`);if(o[i]===void 0)throw new e(`Extension Header Parameter "${i}" is missing`);if(a.get(i)&&n[i]===void 0)throw new e(`Extension Header Parameter "${i}" MUST be integrity protected`)}return new Set(n.crit)}var U=_r;var vr=(e,t)=>{if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!="string")))throw new TypeError(`"${e}" option must be an array of strings`);if(t)return new Set(t)},we=vr;async function Ee(e,t,r){var n;if(!w(e))throw new u("Flattened JWE must be an object");if(e.protected===void 0&&e.header===void 0&&e.unprotected===void 0)throw new u("JOSE Header missing");if(typeof e.iv!="string")throw new u("JWE Initialization Vector missing or incorrect type");if(typeof e.ciphertext!="string")throw new u("JWE Ciphertext missing or incorrect type");if(typeof e.tag!="string")throw new u("JWE Authentication Tag missing or incorrect type");if(e.protected!==void 0&&typeof e.protected!="string")throw new u("JWE Protected Header incorrect type");if(e.encrypted_key!==void 0&&typeof e.encrypted_key!="string")throw new u("JWE Encrypted Key incorrect type");if(e.aad!==void 0&&typeof e.aad!="string")throw new u("JWE AAD incorrect type");if(e.header!==void 0&&!w(e.header))throw new u("JWE Shared Unprotected Header incorrect type");if(e.unprotected!==void 0&&!w(e.unprotected))throw new u("JWE Per-Recipient Unprotected Header incorrect type");let o;if(e.protected)try{let Y=S(e.protected);o=JSON.parse(v.decode(Y))}catch(Y){throw new u("JWE Protected Header is invalid")}if(!R(o,e.header,e.unprotected))throw new u("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint");let a={...o,...e.header,...e.unprotected};if(U(u,new Map,r==null?void 0:r.crit,o,a),a.zip!==void 0){if(!o||!o.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(a.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:i,enc:s}=a;if(typeof i!="string"||!i)throw new u("missing JWE Algorithm (alg) in JWE Header");if(typeof s!="string"||!s)throw new u("missing JWE Encryption Algorithm (enc) in JWE Header");let c=r&&we("keyManagementAlgorithms",r.keyManagementAlgorithms),d=r&&we("contentEncryptionAlgorithms",r.contentEncryptionAlgorithms);if(c&&!c.has(i))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(d&&!d.has(s))throw new B('"enc" (Encryption Algorithm) Header Parameter not allowed');let p;e.encrypted_key!==void 0&&(p=S(e.encrypted_key));let m=!1;typeof t=="function"&&(t=await t(o,e),m=!0);let K;try{K=await Nt(i,t,p,a,r)}catch(Y){if(Y instanceof TypeError||Y instanceof u||Y instanceof l)throw Y;K=O(s)}let T=S(e.iv),x=S(e.tag),_=E.encode((n=e.protected)!==null&&n!==void 0?n:""),k;e.aad!==void 0?k=W(_,E.encode("."),E.encode(e.aad)):k=_;let Ne=await De(s,K,S(e.ciphertext),T,x,k);a.zip==="DEF"&&(Ne=await((r==null?void 0:r.inflateRaw)||wt)(Ne));let te={plaintext:Ne};return e.protected!==void 0&&(te.protectedHeader=o),e.aad!==void 0&&(te.additionalAuthenticatedData=S(e.aad)),e.unprotected!==void 0&&(te.sharedUnprotectedHeader=e.unprotected),e.header!==void 0&&(te.unprotectedHeader=e.header),m?{...te,key:t}:te}async function Ye(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new u("Compact JWE must be a string or Uint8Array");let{0:n,1:o,2:a,3:i,4:s,length:c}=e.split(".");if(c!==5)throw new u("Invalid Compact JWE");let d=await Ee({ciphertext:i,iv:a||void 0,protected:n||void 0,tag:s||void 0,encrypted_key:o||void 0},t,r),p={plaintext:d.plaintext,protectedHeader:d.protectedHeader};return typeof t=="function"?{...p,key:d.key}:p}async function Kr(e,t,r){if(!w(e))throw new u("General JWE must be an object");if(!Array.isArray(e.recipients)||!e.recipients.every(w))throw new u("JWE Recipients missing or incorrect type");if(!e.recipients.length)throw new u("JWE Recipients has no members");for(let n of e.recipients)try{return await Ee({aad:e.aad,ciphertext:e.ciphertext,encrypted_key:n.encrypted_key,header:n.header,iv:e.iv,protected:e.protected,tag:e.tag,unprotected:e.unprotected},t,r)}catch(o){}throw new M}var xr=async e=>{if(e instanceof Uint8Array)return{kty:"oct",k:g(e)};if(!b(e))throw new TypeError(A(e,...y,"Uint8Array"));if(!e.extractable)throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");let{ext:t,key_ops:r,alg:n,use:o,...a}=await f.subtle.exportKey("jwk",e);return a},kt=xr;async function Hr(e){return Jt(e)}async function Cr(e){return Tt(e)}async function qe(e){return kt(e)}async function Pr(e,t,r,n,o={}){let a,i,s;switch(V(e,r,"encrypt"),e){case"dir":{s=r;break}case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!Oe(r))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let{apu:c,apv:d}=o,{epk:p}=o;p||(p=(await At(r)).privateKey);let{x:m,y:K,crv:T,kty:x}=await qe(p),_=await Re(r,p,e==="ECDH-ES"?t:e,e==="ECDH-ES"?he(t):parseInt(e.slice(-5,-2),10),c,d);if(i={epk:{x:m,crv:T,kty:x}},x==="EC"&&(i.epk.y=K),c&&(i.apu=g(c)),d&&(i.apv=g(d)),e==="ECDH-ES"){s=_;break}s=n||O(t);let k=e.slice(-6);a=await le(k,_,s);break}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{s=n||O(t),a=await xt(e,r,s);break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{s=n||O(t);let{p2c:c,p2s:d}=o;({encryptedKey:a,...i}=await vt(e,r,s,c,d));break}case"A128KW":case"A192KW":case"A256KW":{s=n||O(t),a=await le(e,r,s);break}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{s=n||O(t);let{iv:c}=o;({encryptedKey:a,...i}=await Ut(e,r,s,c));break}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}return{cek:s,encryptedKey:a,parameters:i}}var Ue=Pr;var Ze=Symbol(),F=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("plaintext must be an instance of Uint8Array");this._plaintext=t}setKeyManagementParameters(t){if(this._keyManagementParameters)throw new TypeError("setKeyManagementParameters can only be called once");return this._keyManagementParameters=t,this}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._sharedUnprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._sharedUnprotectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}setContentEncryptionKey(t){if(this._cek)throw new TypeError("setContentEncryptionKey can only be called once");return this._cek=t,this}setInitializationVector(t){if(this._iv)throw new TypeError("setInitializationVector can only be called once");return this._iv=t,this}async encrypt(t,r){if(!this._protectedHeader&&!this._unprotectedHeader&&!this._sharedUnprotectedHeader)throw new u("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()");if(!R(this._protectedHeader,this._unprotectedHeader,this._sharedUnprotectedHeader))throw new u("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader,...this._sharedUnprotectedHeader};if(U(u,new Map,r==null?void 0:r.crit,this._protectedHeader,n),n.zip!==void 0){if(!this._protectedHeader||!this._protectedHeader.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(n.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:o,enc:a}=n;if(typeof o!="string"||!o)throw new u('JWE "alg" (Algorithm) Header Parameter missing or invalid');if(typeof a!="string"||!a)throw new u('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');let i;if(o==="dir"){if(this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption")}else if(o==="ECDH-ES"&&this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement");let s;{let x;({cek:s,encryptedKey:i,parameters:x}=await Ue(o,a,t,this._cek,this._keyManagementParameters)),x&&(r&&Ze in r?this._unprotectedHeader?this._unprotectedHeader={...this._unprotectedHeader,...x}:this.setUnprotectedHeader(x):this._protectedHeader?this._protectedHeader={...this._protectedHeader,...x}:this.setProtectedHeader(x))}this._iv||(this._iv=Je(a));let c,d,p;this._protectedHeader?d=E.encode(g(JSON.stringify(this._protectedHeader))):d=E.encode(""),this._aad?(p=g(this._aad),c=W(d,E.encode("."),E.encode(p))):c=d;let m,K;if(n.zip==="DEF"){let x=await((r==null?void 0:r.deflateRaw)||Et)(this._plaintext);({ciphertext:m,tag:K}=await ye(a,x,s,this._iv,c))}else({ciphertext:m,tag:K}=await ye(a,this._plaintext,s,this._iv,c));let T={ciphertext:g(m),iv:g(this._iv),tag:g(K)};return i&&(T.encrypted_key=g(i)),p&&(T.aad=p),this._protectedHeader&&(T.protected=v.decode(d)),this._sharedUnprotectedHeader&&(T.unprotected=this._sharedUnprotectedHeader),this._unprotectedHeader&&(T.header=this._unprotectedHeader),T}};var Qe=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addRecipient(...t){return this.parent.addRecipient(...t)}encrypt(...t){return this.parent.encrypt(...t)}done(){return this.parent}},je=class{constructor(t){this._recipients=[],this._plaintext=t}addRecipient(t,r){let n=new Qe(this,t,{crit:r==null?void 0:r.crit});return this._recipients.push(n),n}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}async encrypt(t){var r,n,o;if(!this._recipients.length)throw new u("at least one recipient must be added");if(t={deflateRaw:t==null?void 0:t.deflateRaw},this._recipients.length===1){let[c]=this._recipients,d=await new F(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(c.unprotectedHeader).encrypt(c.key,{...c.options,...t}),p={ciphertext:d.ciphertext,iv:d.iv,recipients:[{}],tag:d.tag};return d.aad&&(p.aad=d.aad),d.protected&&(p.protected=d.protected),d.unprotected&&(p.unprotected=d.unprotected),d.encrypted_key&&(p.recipients[0].encrypted_key=d.encrypted_key),d.header&&(p.recipients[0].header=d.header),p}let a;for(let c=0;c>3};case"RS256":case"RS384":case"RS512":return{hash:r,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return{hash:r,name:"ECDSA",namedCurve:t.namedCurve};case"EdDSA":return D()&&t.name==="NODE-ED25519"?{name:"NODE-ED25519",namedCurve:"NODE-ED25519"}:{name:t.name};default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}function Se(e,t,r){if(b(t))return ht(t,e,r),t;if(t instanceof Uint8Array){if(!e.startsWith("HS"))throw new TypeError(A(t,...y));return f.subtle.importKey("raw",t,{hash:`SHA-${e.slice(-3)}`,name:"HMAC"},!1,[r])}throw new TypeError(A(t,...y,"Uint8Array"))}var Wr=async(e,t,r,n)=>{let o=await Se(e,t,"verify");Q(e,o);let a=ge(e,o.algorithm);try{return await f.subtle.verify(a,o,r,n)}catch(i){return!1}},Bt=Wr;async function Ae(e,t,r){var n;if(!w(e))throw new h("Flattened JWS must be an object");if(e.protected===void 0&&e.header===void 0)throw new h('Flattened JWS must have either of the "protected" or "header" members');if(e.protected!==void 0&&typeof e.protected!="string")throw new h("JWS Protected Header incorrect type");if(e.payload===void 0)throw new h("JWS Payload missing");if(typeof e.signature!="string")throw new h("JWS Signature missing or incorrect type");if(e.header!==void 0&&!w(e.header))throw new h("JWS Unprotected Header incorrect type");let o={};if(e.protected)try{let k=S(e.protected);o=JSON.parse(v.decode(k))}catch(k){throw new h("JWS Protected Header is invalid")}if(!R(o,e.header))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let a={...o,...e.header},i=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,o,a),s=!0;if(i.has("b64")&&(s=o.b64,typeof s!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:c}=a;if(typeof c!="string"||!c)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');let d=r&&we("algorithms",r.algorithms);if(d&&!d.has(c))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(s){if(typeof e.payload!="string")throw new h("JWS Payload must be a string")}else if(typeof e.payload!="string"&&!(e.payload instanceof Uint8Array))throw new h("JWS Payload must be a string or an Uint8Array instance");let p=!1;typeof t=="function"&&(t=await t(o,e),p=!0),V(c,t,"verify");let m=W(E.encode((n=e.protected)!==null&&n!==void 0?n:""),E.encode("."),typeof e.payload=="string"?E.encode(e.payload):e.payload),K=S(e.signature);if(!await Bt(c,t,K,m))throw new Z;let x;s?x=S(e.payload):typeof e.payload=="string"?x=E.encode(e.payload):x=e.payload;let _={payload:x};return e.protected!==void 0&&(_.protectedHeader=o),e.header!==void 0&&(_.unprotectedHeader=e.header),p?{..._,key:t}:_}async function et(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new h("Compact JWS must be a string or Uint8Array");let{0:n,1:o,2:a,length:i}=e.split(".");if(i!==3)throw new h("Invalid Compact JWS");let s=await Ae({payload:o,protected:n,signature:a},t,r),c={payload:s.payload,protectedHeader:s.protectedHeader};return typeof t=="function"?{...c,key:s.key}:c}async function Jr(e,t,r){if(!w(e))throw new h("General JWS must be an object");if(!Array.isArray(e.signatures)||!e.signatures.every(w))throw new h("JWS Signatures missing or incorrect type");for(let n of e.signatures)try{return await Ae({header:n.header,payload:e.payload,protected:n.protected,signature:n.signature},t,r)}catch(o){}throw new Z}var ie=e=>Math.floor(e.getTime()/1e3);var Tr=/^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i,se=e=>{let t=Tr.exec(e);if(!t)throw new TypeError("Invalid time period format");let r=parseFloat(t[1]);switch(t[2].toLowerCase()){case"sec":case"secs":case"second":case"seconds":case"s":return Math.round(r);case"minute":case"minutes":case"min":case"mins":case"m":return Math.round(r*60);case"hour":case"hours":case"hr":case"hrs":case"h":return Math.round(r*3600);case"day":case"days":case"d":return Math.round(r*86400);case"week":case"weeks":case"w":return Math.round(r*604800);default:return Math.round(r*31557600)}};var Lt=e=>e.toLowerCase().replace(/^application\//,""),Ir=(e,t)=>typeof e=="string"?t.includes(e):Array.isArray(e)?t.some(Set.prototype.has.bind(new Set(e))):!1,ce=(e,t,r={})=>{let{typ:n}=r;if(n&&(typeof e.typ!="string"||Lt(e.typ)!==Lt(n)))throw new J('unexpected "typ" JWT header value',"typ","check_failed");let o;try{o=JSON.parse(v.decode(t))}catch(m){}if(!w(o))throw new H("JWT Claims Set must be a top-level JSON object");let{issuer:a}=r;if(a&&!(Array.isArray(a)?a:[a]).includes(o.iss))throw new J('unexpected "iss" claim value',"iss","check_failed");let{subject:i}=r;if(i&&o.sub!==i)throw new J('unexpected "sub" claim value',"sub","check_failed");let{audience:s}=r;if(s&&!Ir(o.aud,typeof s=="string"?[s]:s))throw new J('unexpected "aud" claim value',"aud","check_failed");let c;switch(typeof r.clockTolerance){case"string":c=se(r.clockTolerance);break;case"number":c=r.clockTolerance;break;case"undefined":c=0;break;default:throw new TypeError("Invalid clockTolerance option type")}let{currentDate:d}=r,p=ie(d||new Date);if((o.iat!==void 0||r.maxTokenAge)&&typeof o.iat!="number")throw new J('"iat" claim must be a number',"iat","invalid");if(o.nbf!==void 0){if(typeof o.nbf!="number")throw new J('"nbf" claim must be a number',"nbf","invalid");if(o.nbf>p+c)throw new J('"nbf" claim timestamp check failed',"nbf","check_failed")}if(o.exp!==void 0){if(typeof o.exp!="number")throw new J('"exp" claim must be a number',"exp","invalid");if(o.exp<=p-c)throw new re('"exp" claim timestamp check failed',"exp","check_failed")}if(r.maxTokenAge){let m=p-o.iat,K=typeof r.maxTokenAge=="number"?r.maxTokenAge:se(r.maxTokenAge);if(m-c>K)throw new re('"iat" claim timestamp check failed (too far in the past)',"iat","check_failed");if(m<0-c)throw new J('"iat" claim timestamp check failed (it should be in the past)',"iat","check_failed")}return o};async function Dr(e,t,r){var n;let o=await et(e,t,r);if(!((n=o.protectedHeader.crit)===null||n===void 0)&&n.includes("b64")&&o.protectedHeader.b64===!1)throw new H("JWTs MUST NOT use unencoded payload");let i={payload:ce(o.protectedHeader,o.payload,r),protectedHeader:o.protectedHeader};return typeof t=="function"?{...i,key:o.key}:i}async function Rr(e,t,r){let n=await Ye(e,t,r),o=ce(n.protectedHeader,n.plaintext,r),{protectedHeader:a}=n;if(a.iss!==void 0&&a.iss!==o.iss)throw new J('replicated "iss" claim header parameter mismatch',"iss","mismatch");if(a.sub!==void 0&&a.sub!==o.sub)throw new J('replicated "sub" claim header parameter mismatch',"sub","mismatch");if(a.aud!==void 0&&JSON.stringify(a.aud)!==JSON.stringify(o.aud))throw new J('replicated "aud" claim header parameter mismatch',"aud","mismatch");let i={payload:o,protectedHeader:a};return typeof t=="function"?{...i,key:n.key}:i}var be=class{constructor(t){this._flattened=new F(t)}setContentEncryptionKey(t){return this._flattened.setContentEncryptionKey(t),this}setInitializationVector(t){return this._flattened.setInitializationVector(t),this}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}setKeyManagementParameters(t){return this._flattened.setKeyManagementParameters(t),this}async encrypt(t,r){let n=await this._flattened.encrypt(t,r);return[n.protected,n.encrypted_key,n.iv,n.ciphertext,n.tag].join(".")}};var Or=async(e,t,r)=>{let n=await Se(e,t,"sign");Q(e,n);let o=await f.subtle.sign(ge(e,n.algorithm),n,r);return new Uint8Array(o)},$t=Or;var ee=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("payload must be an instance of Uint8Array");this._payload=t}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}async sign(t,r){if(!this._protectedHeader&&!this._unprotectedHeader)throw new h("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");if(!R(this._protectedHeader,this._unprotectedHeader))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader},o=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,this._protectedHeader,n),a=!0;if(o.has("b64")&&(a=this._protectedHeader.b64,typeof a!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:i}=n;if(typeof i!="string"||!i)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');V(i,t,"sign");let s=this._payload;a&&(s=E.encode(g(s)));let c;this._protectedHeader?c=E.encode(g(JSON.stringify(this._protectedHeader))):c=E.encode("");let d=W(c,E.encode("."),s),p=await $t(i,t,d),m={signature:g(p),payload:""};return a&&(m.payload=v.decode(s)),this._unprotectedHeader&&(m.header=this._unprotectedHeader),this._protectedHeader&&(m.protected=v.decode(c)),m}};var _e=class{constructor(t){this._flattened=new ee(t)}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}async sign(t,r){let n=await this._flattened.sign(t,r);if(n.payload===void 0)throw new TypeError("use the flattened module for creating JWS with b64: false");return`${n.protected}.${n.payload}.${n.signature}`}};var tt=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n}setProtectedHeader(t){if(this.protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this.protectedHeader=t,this}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addSignature(...t){return this.parent.addSignature(...t)}sign(...t){return this.parent.sign(...t)}done(){return this.parent}},rt=class{constructor(t){this._signatures=[],this._payload=t}addSignature(t,r){let n=new tt(this,t,r);return this._signatures.push(n),n}async sign(){if(!this._signatures.length)throw new h("at least one signature must be added");let t={signatures:[],payload:""};for(let r=0;r{if(typeof e!="string"||!e)throw new pe(`${t} missing or invalid`)};async function Gt(e,t){if(!w(e))throw new TypeError("JWK must be an object");if(t!=null||(t="sha256"),t!=="sha256"&&t!=="sha384"&&t!=="sha512")throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"');let r;switch(e.kty){case"EC":X(e.crv,'"crv" (Curve) Parameter'),X(e.x,'"x" (X Coordinate) Parameter'),X(e.y,'"y" (Y Coordinate) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x,y:e.y};break;case"OKP":X(e.crv,'"crv" (Subtype of Key Pair) Parameter'),X(e.x,'"x" (Public Key) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x};break;case"RSA":X(e.e,'"e" (Exponent) Parameter'),X(e.n,'"n" (Modulus) Parameter'),r={e:e.e,kty:e.kty,n:e.n};break;case"oct":X(e.k,'"k" (Key Value) Parameter'),r={k:e.k,kty:e.kty};break;default:throw new l('"kty" (Key Type) Parameter missing or unsupported')}let n=E.encode(JSON.stringify(r));return g(await Ke(t,n))}async function Ur(e,t){t!=null||(t="sha256");let r=await Gt(e,t);return`urn:ietf:params:oauth:jwk-thumbprint:sha-${t.slice(-3)}:${r}`}async function Mr(e,t){let r={...e,...t.header};if(!w(r.jwk))throw new h('"jwk" (JSON Web Key) Header Parameter must be a JSON object');let n=await j({...r.jwk,ext:!0},r.alg,!0);if(n instanceof Uint8Array||n.type!=="public")throw new h('"jwk" (JSON Web Key) Header Parameter must be a public key');return n}function Nr(e){switch(typeof e=="string"&&e.slice(0,2)){case"RS":case"PS":return"RSA";case"ES":return"EC";case"Ed":return"OKP";default:throw new l('Unsupported "alg" value for a JSON Web Key Set')}}function at(e){return e&&typeof e=="object"&&Array.isArray(e.keys)&&e.keys.every(kr)}function kr(e){return w(e)}function Br(e){return typeof structuredClone=="function"?structuredClone(e):JSON.parse(JSON.stringify(e))}var de=class{constructor(t){if(this._cached=new WeakMap,!at(t))throw new L("JSON Web Key Set malformed");this._jwks=Br(t)}async getKey(t,r){let{alg:n,kid:o}={...t,...r==null?void 0:r.header},a=Nr(n),i=this._jwks.keys.filter(d=>{let p=a===d.kty;if(p&&typeof o=="string"&&(p=o===d.kid),p&&typeof d.alg=="string"&&(p=n===d.alg),p&&typeof d.use=="string"&&(p=d.use==="sig"),p&&Array.isArray(d.key_ops)&&(p=d.key_ops.includes("verify")),p&&n==="EdDSA"&&(p=d.crv==="Ed25519"||d.crv==="Ed448"),p)switch(n){case"ES256":p=d.crv==="P-256";break;case"ES256K":p=d.crv==="secp256k1";break;case"ES384":p=d.crv==="P-384";break;case"ES512":p=d.crv==="P-521";break}return p}),{0:s,length:c}=i;if(c===0)throw new q;if(c!==1){let d=new ue,{_cached:p}=this;throw d[Symbol.asyncIterator]=async function*(){for(let m of i)try{yield await Vt(p,m,n)}catch(K){continue}},d}return Vt(this._cached,s,n)}};async function Vt(e,t,r){let n=e.get(t)||e.set(t,{}).get(t);if(n[r]===void 0){let o=await j({...t,ext:!0},r);if(o.type!=="public")throw new L("JSON Web Key Set members must be public keys");n[r]=o}return n[r]}function Lr(e){return de.prototype.getKey.bind(new de(e))}var $r=async(e,t,r)=>{let n,o,a=!1;typeof AbortController=="function"&&(n=new AbortController,o=setTimeout(()=>{a=!0,n.abort()},t));let i=await fetch(e.href,{signal:n?n.signal:void 0,redirect:"manual",headers:r.headers}).catch(s=>{throw a?new fe:s});if(o!==void 0&&clearTimeout(o),i.status!==200)throw new C("Expected 200 OK from the JSON Web Key Set HTTP response");try{return await i.json()}catch(s){throw new C("Failed to parse the JSON Web Key Set HTTP response as JSON")}},Ft=$r;var Me=class extends de{constructor(t,r){if(super({keys:[]}),this._jwks=void 0,!(t instanceof URL))throw new TypeError("url must be an instance of URL");this._url=new URL(t.href),this._options={agent:r==null?void 0:r.agent,headers:r==null?void 0:r.headers},this._timeoutDuration=typeof(r==null?void 0:r.timeoutDuration)=="number"?r==null?void 0:r.timeoutDuration:5e3,this._cooldownDuration=typeof(r==null?void 0:r.cooldownDuration)=="number"?r==null?void 0:r.cooldownDuration:3e4,this._cacheMaxAge=typeof(r==null?void 0:r.cacheMaxAge)=="number"?r==null?void 0:r.cacheMaxAge:6e5}coolingDown(){return typeof this._jwksTimestamp=="number"?Date.now(){let r=()=>{this._pendingFetch===void 0?t():setTimeout(r,5)};r()});this._pendingFetch||(this._pendingFetch=Ft(this._url,this._timeoutDuration,this._options).then(t=>{if(!at(t))throw new L("JSON Web Key Set malformed");this._jwks={keys:t.keys},this._jwksTimestamp=Date.now(),this._pendingFetch=void 0}).catch(t=>{throw this._pendingFetch=void 0,t})),await this._pendingFetch}};function Gr(e,t){return Me.prototype.getKey.bind(new Me(e,t))}var it=class extends z{encode(){let t=g(JSON.stringify({alg:"none"})),r=g(JSON.stringify(this._payload));return`${t}.${r}.`}static decode(t,r){if(typeof t!="string")throw new H("Unsecured JWT must be a string");let{0:n,1:o,2:a,length:i}=t.split(".");if(i!==3||a!=="")throw new H("Invalid Unsecured JWT");let s;try{if(s=JSON.parse(v.decode(S(n))),s.alg!=="none")throw new Error}catch(d){throw new H("Invalid Unsecured JWT")}return{payload:ce(s,S(o),r),header:s}}};var zt={};ct(zt,{decode:()=>ve,encode:()=>Vr});var Vr=g,ve=S;function Fr(e){let t;if(typeof e=="string"){let r=e.split(".");(r.length===3||r.length===5)&&([t]=r)}else if(typeof e=="object"&&e)if("protected"in e)t=e.protected;else throw new TypeError("Token does not contain a Protected Header");try{if(typeof t!="string"||!t)throw new Error;let r=JSON.parse(v.decode(ve(t)));if(!w(r))throw new Error;return r}catch(r){throw new TypeError("Invalid Token or Protected Header formatting")}}function zr(e){if(typeof e!="string")throw new H("JWTs must use Compact JWS serialization, JWT must be a string");let{1:t,length:r}=e.split(".");if(r===5)throw new H("Only JWTs using Compact JWS serialization can be decoded");if(r!==3)throw new H("Invalid JWT");if(!t)throw new H("JWTs must contain a payload");let n;try{n=ve(t)}catch(a){throw new H("Failed to parse the base64url encoded payload")}let o;try{o=JSON.parse(v.decode(n))}catch(a){throw new H("Failed to parse the decoded payload as JSON")}if(!w(o))throw new H("Invalid JWT Claims Set");return o}async function Xt(e,t){var r;let n,o,a;switch(e){case"HS256":case"HS384":case"HS512":n=parseInt(e.slice(-3),10),o={name:"HMAC",hash:`SHA-${n}`,length:n},a=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return n=parseInt(e.slice(-3),10),$(new Uint8Array(n>>3));case"A128KW":case"A192KW":case"A256KW":n=parseInt(e.slice(1,4),10),o={name:"AES-KW",length:n},a=["wrapKey","unwrapKey"];break;case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":case"A128GCM":case"A192GCM":case"A256GCM":n=parseInt(e.slice(1,4),10),o={name:"AES-GCM",length:n},a=["encrypt","decrypt"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}return f.subtle.generateKey(o,(r=t==null?void 0:t.extractable)!==null&&r!==void 0?r:!1,a)}function st(e){var t;let r=(t=e==null?void 0:e.modulusLength)!==null&&t!==void 0?t:2048;if(typeof r!="number"||r<2048)throw new l("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used");return r}async function Yt(e,t){var r,n,o,a;let i,s;switch(e){case"PS256":case"PS384":case"PS512":i={name:"RSA-PSS",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RS256":case"RS384":case"RS512":i={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":i={name:"RSA-OAEP",hash:`SHA-${parseInt(e.slice(-3),10)||1}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["decrypt","unwrapKey","encrypt","wrapKey"];break;case"ES256":i={name:"ECDSA",namedCurve:"P-256"},s=["sign","verify"];break;case"ES384":i={name:"ECDSA",namedCurve:"P-384"},s=["sign","verify"];break;case"ES512":i={name:"ECDSA",namedCurve:"P-521"},s=["sign","verify"];break;case"EdDSA":s=["sign","verify"];let c=(r=t==null?void 0:t.crv)!==null&&r!==void 0?r:"Ed25519";switch(c){case"Ed25519":case"Ed448":i={name:c};break;default:throw new l("Invalid or unsupported crv option provided")}break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{s=["deriveKey","deriveBits"];let d=(n=t==null?void 0:t.crv)!==null&&n!==void 0?n:"P-256";switch(d){case"P-256":case"P-384":case"P-521":{i={name:"ECDH",namedCurve:d};break}case"X25519":case"X448":i={name:d};break;default:throw new l("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448")}break}default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}try{return await f.subtle.generateKey(i,(o=t==null?void 0:t.extractable)!==null&&o!==void 0?o:!1,s)}catch(c){if(i.name==="Ed25519"&&(c==null?void 0:c.name)==="NotSupportedError"&&D())return i={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.generateKey(i,(a=t==null?void 0:t.extractable)!==null&&a!==void 0?a:!1,s);throw c}}async function Xr(e,t){return Yt(e,t)}async function Yr(e,t){return Xt(e,t)}export{be as CompactEncrypt,_e as CompactSign,Mr as EmbeddedJWK,ot as EncryptJWT,F as FlattenedEncrypt,ee as FlattenedSign,je as GeneralEncrypt,rt as GeneralSign,nt as SignJWT,it as UnsecuredJWT,zt as base64url,Gt as calculateJwkThumbprint,Ur as calculateJwkThumbprintUri,Ye as compactDecrypt,et as compactVerify,Lr as createLocalJWKSet,Gr as createRemoteJWKSet,zr as decodeJwt,Fr as decodeProtectedHeader,ft as errors,qe as exportJWK,Cr as exportPKCS8,Hr as exportSPKI,Ee as flattenedDecrypt,Ae as flattenedVerify,Kr as generalDecrypt,Jr as generalVerify,Xr as generateKeyPair,Yr as generateSecret,j as importJWK,hr as importPKCS8,lr as importSPKI,mr as importX509,Rr as jwtDecrypt,Dr as jwtVerify}; diff --git a/dist/browser/index.js b/dist/browser/index.js new file mode 100644 index 0000000000..00e8cee4cd --- /dev/null +++ b/dist/browser/index.js @@ -0,0 +1,31 @@ +export { compactDecrypt } from './jwe/compact/decrypt.js'; +export { flattenedDecrypt } from './jwe/flattened/decrypt.js'; +export { generalDecrypt } from './jwe/general/decrypt.js'; +export { GeneralEncrypt } from './jwe/general/encrypt.js'; +export { compactVerify } from './jws/compact/verify.js'; +export { flattenedVerify } from './jws/flattened/verify.js'; +export { generalVerify } from './jws/general/verify.js'; +export { jwtVerify } from './jwt/verify.js'; +export { jwtDecrypt } from './jwt/decrypt.js'; +export { CompactEncrypt } from './jwe/compact/encrypt.js'; +export { FlattenedEncrypt } from './jwe/flattened/encrypt.js'; +export { CompactSign } from './jws/compact/sign.js'; +export { FlattenedSign } from './jws/flattened/sign.js'; +export { GeneralSign } from './jws/general/sign.js'; +export { SignJWT } from './jwt/sign.js'; +export { EncryptJWT } from './jwt/encrypt.js'; +export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.js'; +export { EmbeddedJWK } from './jwk/embedded.js'; +export { createLocalJWKSet } from './jwks/local.js'; +export { createRemoteJWKSet } from './jwks/remote.js'; +export { UnsecuredJWT } from './jwt/unsecured.js'; +export { exportPKCS8, exportSPKI, exportJWK } from './key/export.js'; +export { importSPKI, importPKCS8, importX509, importJWK } from './key/import.js'; +export { decodeProtectedHeader } from './util/decode_protected_header.js'; +export { decodeJwt } from './util/decode_jwt.js'; +import * as errors_1 from './util/errors.js'; +export { errors_1 as errors }; +export { generateKeyPair } from './key/generate_key_pair.js'; +export { generateSecret } from './key/generate_secret.js'; +import * as base64url_1 from './util/base64url.js'; +export { base64url_1 as base64url }; diff --git a/dist/browser/index.umd.js b/dist/browser/index.umd.js new file mode 100644 index 0000000000..930812fe00 --- /dev/null +++ b/dist/browser/index.umd.js @@ -0,0 +1,3373 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jose = {})); +})(this, (function (exports) { 'use strict'; + + var __defProp = Object.defineProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + + // dist/browser/runtime/webcrypto.js + var webcrypto_default = crypto; + var isCryptoKey = (key) => key instanceof CryptoKey; + + // dist/browser/runtime/digest.js + var digest = async (algorithm, data) => { + const subtleDigest = `SHA-${algorithm.slice(-3)}`; + return new Uint8Array(await webcrypto_default.subtle.digest(subtleDigest, data)); + }; + var digest_default = digest; + + // dist/browser/lib/buffer_utils.js + var encoder = new TextEncoder(); + var decoder = new TextDecoder(); + var MAX_INT32 = 2 ** 32; + function concat(...buffers) { + const size = buffers.reduce((acc, { length }) => acc + length, 0); + const buf = new Uint8Array(size); + let i = 0; + buffers.forEach((buffer) => { + buf.set(buffer, i); + i += buffer.length; + }); + return buf; + } + function p2s(alg, p2sInput) { + return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); + } + function writeUInt32BE(buf, value, offset) { + if (value < 0 || value >= MAX_INT32) { + throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); + } + buf.set([value >>> 24, value >>> 16, value >>> 8, value & 255], offset); + } + function uint64be(value) { + const high = Math.floor(value / MAX_INT32); + const low = value % MAX_INT32; + const buf = new Uint8Array(8); + writeUInt32BE(buf, high, 0); + writeUInt32BE(buf, low, 4); + return buf; + } + function uint32be(value) { + const buf = new Uint8Array(4); + writeUInt32BE(buf, value); + return buf; + } + function lengthAndInput(input) { + return concat(uint32be(input.length), input); + } + async function concatKdf(secret, bits, value) { + const iterations = Math.ceil((bits >> 3) / 32); + const res = new Uint8Array(iterations * 32); + for (let iter = 0; iter < iterations; iter++) { + const buf = new Uint8Array(4 + secret.length + value.length); + buf.set(uint32be(iter + 1)); + buf.set(secret, 4); + buf.set(value, 4 + secret.length); + res.set(await digest_default("sha256", buf), iter * 32); + } + return res.slice(0, bits >> 3); + } + + // dist/browser/runtime/base64url.js + var encodeBase64 = (input) => { + let unencoded = input; + if (typeof unencoded === "string") { + unencoded = encoder.encode(unencoded); + } + const CHUNK_SIZE = 32768; + const arr = []; + for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { + arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))); + } + return btoa(arr.join("")); + }; + var encode = (input) => { + return encodeBase64(input).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); + }; + var decodeBase64 = (encoded) => { + const binary = atob(encoded); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i); + } + return bytes; + }; + var decode = (input) => { + let encoded = input; + if (encoded instanceof Uint8Array) { + encoded = decoder.decode(encoded); + } + encoded = encoded.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""); + try { + return decodeBase64(encoded); + } catch (_a) { + throw new TypeError("The input to be decoded is not correctly encoded."); + } + }; + + // dist/browser/util/errors.js + var errors_exports = {}; + __export(errors_exports, { + JOSEAlgNotAllowed: () => JOSEAlgNotAllowed, + JOSEError: () => JOSEError, + JOSENotSupported: () => JOSENotSupported, + JWEDecryptionFailed: () => JWEDecryptionFailed, + JWEInvalid: () => JWEInvalid, + JWKInvalid: () => JWKInvalid, + JWKSInvalid: () => JWKSInvalid, + JWKSMultipleMatchingKeys: () => JWKSMultipleMatchingKeys, + JWKSNoMatchingKey: () => JWKSNoMatchingKey, + JWKSTimeout: () => JWKSTimeout, + JWSInvalid: () => JWSInvalid, + JWSSignatureVerificationFailed: () => JWSSignatureVerificationFailed, + JWTClaimValidationFailed: () => JWTClaimValidationFailed, + JWTExpired: () => JWTExpired, + JWTInvalid: () => JWTInvalid + }); + var JOSEError = class extends Error { + static get code() { + return "ERR_JOSE_GENERIC"; + } + constructor(message2) { + var _a; + super(message2); + this.code = "ERR_JOSE_GENERIC"; + this.name = this.constructor.name; + (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); + } + }; + var JWTClaimValidationFailed = class extends JOSEError { + static get code() { + return "ERR_JWT_CLAIM_VALIDATION_FAILED"; + } + constructor(message2, claim = "unspecified", reason = "unspecified") { + super(message2); + this.code = "ERR_JWT_CLAIM_VALIDATION_FAILED"; + this.claim = claim; + this.reason = reason; + } + }; + var JWTExpired = class extends JOSEError { + static get code() { + return "ERR_JWT_EXPIRED"; + } + constructor(message2, claim = "unspecified", reason = "unspecified") { + super(message2); + this.code = "ERR_JWT_EXPIRED"; + this.claim = claim; + this.reason = reason; + } + }; + var JOSEAlgNotAllowed = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JOSE_ALG_NOT_ALLOWED"; + } + static get code() { + return "ERR_JOSE_ALG_NOT_ALLOWED"; + } + }; + var JOSENotSupported = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JOSE_NOT_SUPPORTED"; + } + static get code() { + return "ERR_JOSE_NOT_SUPPORTED"; + } + }; + var JWEDecryptionFailed = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWE_DECRYPTION_FAILED"; + this.message = "decryption operation failed"; + } + static get code() { + return "ERR_JWE_DECRYPTION_FAILED"; + } + }; + var JWEInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWE_INVALID"; + } + static get code() { + return "ERR_JWE_INVALID"; + } + }; + var JWSInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWS_INVALID"; + } + static get code() { + return "ERR_JWS_INVALID"; + } + }; + var JWTInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWT_INVALID"; + } + static get code() { + return "ERR_JWT_INVALID"; + } + }; + var JWKInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWK_INVALID"; + } + static get code() { + return "ERR_JWK_INVALID"; + } + }; + var JWKSInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_INVALID"; + } + static get code() { + return "ERR_JWKS_INVALID"; + } + }; + var JWKSNoMatchingKey = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_NO_MATCHING_KEY"; + this.message = "no applicable key found in the JSON Web Key Set"; + } + static get code() { + return "ERR_JWKS_NO_MATCHING_KEY"; + } + }; + var JWKSMultipleMatchingKeys = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; + this.message = "multiple matching keys found in the JSON Web Key Set"; + } + static get code() { + return "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; + } + }; + var JWKSTimeout = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_TIMEOUT"; + this.message = "request timed out"; + } + static get code() { + return "ERR_JWKS_TIMEOUT"; + } + }; + var JWSSignatureVerificationFailed = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; + this.message = "signature verification failed"; + } + static get code() { + return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; + } + }; + + // dist/browser/runtime/random.js + var random_default = webcrypto_default.getRandomValues.bind(webcrypto_default); + + // dist/browser/lib/iv.js + function bitLength(alg) { + switch (alg) { + case "A128GCM": + case "A128GCMKW": + case "A192GCM": + case "A192GCMKW": + case "A256GCM": + case "A256GCMKW": + return 96; + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + return 128; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } + } + var iv_default = (alg) => random_default(new Uint8Array(bitLength(alg) >> 3)); + + // dist/browser/lib/check_iv_length.js + var checkIvLength = (enc, iv) => { + if (iv.length << 3 !== bitLength(enc)) { + throw new JWEInvalid("Invalid Initialization Vector length"); + } + }; + var check_iv_length_default = checkIvLength; + + // dist/browser/runtime/check_cek_length.js + var checkCekLength = (cek, expected) => { + const actual = cek.byteLength << 3; + if (actual !== expected) { + throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); + } + }; + var check_cek_length_default = checkCekLength; + + // dist/browser/runtime/timing_safe_equal.js + var timingSafeEqual = (a, b) => { + if (!(a instanceof Uint8Array)) { + throw new TypeError("First argument must be a buffer"); + } + if (!(b instanceof Uint8Array)) { + throw new TypeError("Second argument must be a buffer"); + } + if (a.length !== b.length) { + throw new TypeError("Input buffers must have the same length"); + } + const len = a.length; + let out = 0; + let i = -1; + while (++i < len) { + out |= a[i] ^ b[i]; + } + return out === 0; + }; + var timing_safe_equal_default = timingSafeEqual; + + // dist/browser/runtime/env.js + function isCloudflareWorkers() { + return typeof WebSocketPair !== "undefined" || typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime !== "undefined" && EdgeRuntime === "vercel"; + } + + // dist/browser/lib/crypto_key.js + function unusable(name, prop = "algorithm.name") { + return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); + } + function isAlgorithm(algorithm, name) { + return algorithm.name === name; + } + function getHashLength(hash) { + return parseInt(hash.name.slice(4), 10); + } + function getNamedCurve(alg) { + switch (alg) { + case "ES256": + return "P-256"; + case "ES384": + return "P-384"; + case "ES512": + return "P-521"; + default: + throw new Error("unreachable"); + } + } + function checkUsage(key, usages) { + if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { + let msg = "CryptoKey does not support this operation, its usages must include "; + if (usages.length > 2) { + const last = usages.pop(); + msg += `one of ${usages.join(", ")}, or ${last}.`; + } else if (usages.length === 2) { + msg += `one of ${usages[0]} or ${usages[1]}.`; + } else { + msg += `${usages[0]}.`; + } + throw new TypeError(msg); + } + } + function checkSigCryptoKey(key, alg, ...usages) { + switch (alg) { + case "HS256": + case "HS384": + case "HS512": { + if (!isAlgorithm(key.algorithm, "HMAC")) + throw unusable("HMAC"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "RS256": + case "RS384": + case "RS512": { + if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5")) + throw unusable("RSASSA-PKCS1-v1_5"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "PS256": + case "PS384": + case "PS512": { + if (!isAlgorithm(key.algorithm, "RSA-PSS")) + throw unusable("RSA-PSS"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "EdDSA": { + if (key.algorithm.name !== "Ed25519" && key.algorithm.name !== "Ed448") { + if (isCloudflareWorkers()) { + if (isAlgorithm(key.algorithm, "NODE-ED25519")) + break; + throw unusable("Ed25519, Ed448, or NODE-ED25519"); + } + throw unusable("Ed25519 or Ed448"); + } + break; + } + case "ES256": + case "ES384": + case "ES512": { + if (!isAlgorithm(key.algorithm, "ECDSA")) + throw unusable("ECDSA"); + const expected = getNamedCurve(alg); + const actual = key.algorithm.namedCurve; + if (actual !== expected) + throw unusable(expected, "algorithm.namedCurve"); + break; + } + default: + throw new TypeError("CryptoKey does not support this operation"); + } + checkUsage(key, usages); + } + function checkEncCryptoKey(key, alg, ...usages) { + switch (alg) { + case "A128GCM": + case "A192GCM": + case "A256GCM": { + if (!isAlgorithm(key.algorithm, "AES-GCM")) + throw unusable("AES-GCM"); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, "algorithm.length"); + break; + } + case "A128KW": + case "A192KW": + case "A256KW": { + if (!isAlgorithm(key.algorithm, "AES-KW")) + throw unusable("AES-KW"); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, "algorithm.length"); + break; + } + case "ECDH": { + switch (key.algorithm.name) { + case "ECDH": + case "X25519": + case "X448": + break; + default: + throw unusable("ECDH, X25519, or X448"); + } + break; + } + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": + if (!isAlgorithm(key.algorithm, "PBKDF2")) + throw unusable("PBKDF2"); + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": { + if (!isAlgorithm(key.algorithm, "RSA-OAEP")) + throw unusable("RSA-OAEP"); + const expected = parseInt(alg.slice(9), 10) || 1; + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + default: + throw new TypeError("CryptoKey does not support this operation"); + } + checkUsage(key, usages); + } + + // dist/browser/lib/invalid_key_input.js + function message(msg, actual, ...types2) { + if (types2.length > 2) { + const last = types2.pop(); + msg += `one of type ${types2.join(", ")}, or ${last}.`; + } else if (types2.length === 2) { + msg += `one of type ${types2[0]} or ${types2[1]}.`; + } else { + msg += `of type ${types2[0]}.`; + } + if (actual == null) { + msg += ` Received ${actual}`; + } else if (typeof actual === "function" && actual.name) { + msg += ` Received function ${actual.name}`; + } else if (typeof actual === "object" && actual != null) { + if (actual.constructor && actual.constructor.name) { + msg += ` Received an instance of ${actual.constructor.name}`; + } + } + return msg; + } + var invalid_key_input_default = (actual, ...types2) => { + return message("Key must be ", actual, ...types2); + }; + function withAlg(alg, actual, ...types2) { + return message(`Key for the ${alg} algorithm must be `, actual, ...types2); + } + + // dist/browser/runtime/is_key_like.js + var is_key_like_default = (key) => { + return isCryptoKey(key); + }; + var types = ["CryptoKey"]; + + // dist/browser/runtime/decrypt.js + async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); + } + const keySize = parseInt(enc.slice(1, 4), 10); + const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["decrypt"]); + const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { + hash: `SHA-${keySize << 1}`, + name: "HMAC" + }, false, ["sign"]); + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); + const expectedTag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); + let macCheckPassed; + try { + macCheckPassed = timing_safe_equal_default(tag, expectedTag); + } catch (_a) { + } + if (!macCheckPassed) { + throw new JWEDecryptionFailed(); + } + let plaintext; + try { + plaintext = new Uint8Array(await webcrypto_default.subtle.decrypt({ iv, name: "AES-CBC" }, encKey, ciphertext)); + } catch (_b) { + } + if (!plaintext) { + throw new JWEDecryptionFailed(); + } + return plaintext; + } + async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { + let encKey; + if (cek instanceof Uint8Array) { + encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["decrypt"]); + } else { + checkEncCryptoKey(cek, enc, "decrypt"); + encKey = cek; + } + try { + return new Uint8Array(await webcrypto_default.subtle.decrypt({ + additionalData: aad, + iv, + name: "AES-GCM", + tagLength: 128 + }, encKey, concat(ciphertext, tag))); + } catch (_a) { + throw new JWEDecryptionFailed(); + } + } + var decrypt = async (enc, cek, ciphertext, iv, tag, aad) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); + } + check_iv_length_default(enc, iv); + switch (enc) { + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); + return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad); + case "A128GCM": + case "A192GCM": + case "A256GCM": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); + return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); + default: + throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); + } + }; + var decrypt_default = decrypt; + + // dist/browser/runtime/zlib.js + var inflate = async () => { + throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.'); + }; + var deflate = async () => { + throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.'); + }; + + // dist/browser/lib/is_disjoint.js + var isDisjoint = (...headers) => { + const sources = headers.filter(Boolean); + if (sources.length === 0 || sources.length === 1) { + return true; + } + let acc; + for (const header of sources) { + const parameters = Object.keys(header); + if (!acc || acc.size === 0) { + acc = new Set(parameters); + continue; + } + for (const parameter of parameters) { + if (acc.has(parameter)) { + return false; + } + acc.add(parameter); + } + } + return true; + }; + var is_disjoint_default = isDisjoint; + + // dist/browser/lib/is_object.js + function isObjectLike(value) { + return typeof value === "object" && value !== null; + } + function isObject(input) { + if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") { + return false; + } + if (Object.getPrototypeOf(input) === null) { + return true; + } + let proto = input; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + return Object.getPrototypeOf(input) === proto; + } + + // dist/browser/runtime/bogus.js + var bogusWebCrypto = [ + { hash: "SHA-256", name: "HMAC" }, + true, + ["sign"] + ]; + var bogus_default = bogusWebCrypto; + + // dist/browser/runtime/aeskw.js + function checkKeySize(key, alg) { + if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) { + throw new TypeError(`Invalid key size for alg: ${alg}`); + } + } + function getCryptoKey(key, alg, usage) { + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, usage); + return key; + } + if (key instanceof Uint8Array) { + return webcrypto_default.subtle.importKey("raw", key, "AES-KW", true, [usage]); + } + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); + } + var wrap = async (alg, key, cek) => { + const cryptoKey = await getCryptoKey(key, alg, "wrapKey"); + checkKeySize(cryptoKey, alg); + const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, cryptoKey, "AES-KW")); + }; + var unwrap = async (alg, key, encryptedKey) => { + const cryptoKey = await getCryptoKey(key, alg, "unwrapKey"); + checkKeySize(cryptoKey, alg); + const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, cryptoKey, "AES-KW", ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); + }; + + // dist/browser/runtime/ecdhes.js + async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { + if (!isCryptoKey(publicKey)) { + throw new TypeError(invalid_key_input_default(publicKey, ...types)); + } + checkEncCryptoKey(publicKey, "ECDH"); + if (!isCryptoKey(privateKey)) { + throw new TypeError(invalid_key_input_default(privateKey, ...types)); + } + checkEncCryptoKey(privateKey, "ECDH", "deriveBits"); + const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); + let length; + if (publicKey.algorithm.name === "X25519") { + length = 256; + } else if (publicKey.algorithm.name === "X448") { + length = 448; + } else { + length = Math.ceil(parseInt(publicKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3; + } + const sharedSecret = new Uint8Array(await webcrypto_default.subtle.deriveBits({ + name: publicKey.algorithm.name, + public: publicKey + }, privateKey, length)); + return concatKdf(sharedSecret, keyLength, value); + } + async function generateEpk(key) { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + return webcrypto_default.subtle.generateKey(key.algorithm, true, ["deriveBits"]); + } + function ecdhAllowed(key) { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + return ["P-256", "P-384", "P-521"].includes(key.algorithm.namedCurve) || key.algorithm.name === "X25519" || key.algorithm.name === "X448"; + } + + // dist/browser/lib/check_p2s.js + function checkP2s(p2s2) { + if (!(p2s2 instanceof Uint8Array) || p2s2.length < 8) { + throw new JWEInvalid("PBES2 Salt Input must be 8 or more octets"); + } + } + + // dist/browser/runtime/pbes2kw.js + function getCryptoKey2(key, alg) { + if (key instanceof Uint8Array) { + return webcrypto_default.subtle.importKey("raw", key, "PBKDF2", false, ["deriveBits"]); + } + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, "deriveBits", "deriveKey"); + return key; + } + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); + } + async function deriveKey2(p2s2, alg, p2c, key) { + checkP2s(p2s2); + const salt = p2s(alg, p2s2); + const keylen = parseInt(alg.slice(13, 16), 10); + const subtleAlg = { + hash: `SHA-${alg.slice(8, 11)}`, + iterations: p2c, + name: "PBKDF2", + salt + }; + const wrapAlg = { + length: keylen, + name: "AES-KW" + }; + const cryptoKey = await getCryptoKey2(key, alg); + if (cryptoKey.usages.includes("deriveBits")) { + return new Uint8Array(await webcrypto_default.subtle.deriveBits(subtleAlg, cryptoKey, keylen)); + } + if (cryptoKey.usages.includes("deriveKey")) { + return webcrypto_default.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ["wrapKey", "unwrapKey"]); + } + throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"'); + } + var encrypt = async (alg, key, cek, p2c = 2048, p2s2 = random_default(new Uint8Array(16))) => { + const derived = await deriveKey2(p2s2, alg, p2c, key); + const encryptedKey = await wrap(alg.slice(-6), derived, cek); + return { encryptedKey, p2c, p2s: encode(p2s2) }; + }; + var decrypt2 = async (alg, key, encryptedKey, p2c, p2s2) => { + const derived = await deriveKey2(p2s2, alg, p2c, key); + return unwrap(alg.slice(-6), derived, encryptedKey); + }; + + // dist/browser/runtime/subtle_rsaes.js + function subtleRsaEs(alg) { + switch (alg) { + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + return "RSA-OAEP"; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } + } + + // dist/browser/runtime/check_key_length.js + var check_key_length_default = (alg, key) => { + if (alg.startsWith("RS") || alg.startsWith("PS")) { + const { modulusLength } = key.algorithm; + if (typeof modulusLength !== "number" || modulusLength < 2048) { + throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); + } + } + }; + + // dist/browser/runtime/rsaes.js + var encrypt2 = async (alg, key, cek) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + checkEncCryptoKey(key, alg, "encrypt", "wrapKey"); + check_key_length_default(alg, key); + if (key.usages.includes("encrypt")) { + return new Uint8Array(await webcrypto_default.subtle.encrypt(subtleRsaEs(alg), key, cek)); + } + if (key.usages.includes("wrapKey")) { + const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, key, subtleRsaEs(alg))); + } + throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation'); + }; + var decrypt3 = async (alg, key, encryptedKey) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + checkEncCryptoKey(key, alg, "decrypt", "unwrapKey"); + check_key_length_default(alg, key); + if (key.usages.includes("decrypt")) { + return new Uint8Array(await webcrypto_default.subtle.decrypt(subtleRsaEs(alg), key, encryptedKey)); + } + if (key.usages.includes("unwrapKey")) { + const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, key, subtleRsaEs(alg), ...bogus_default); + return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek)); + } + throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation'); + }; + + // dist/browser/lib/cek.js + function bitLength2(alg) { + switch (alg) { + case "A128GCM": + return 128; + case "A192GCM": + return 192; + case "A256GCM": + case "A128CBC-HS256": + return 256; + case "A192CBC-HS384": + return 384; + case "A256CBC-HS512": + return 512; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } + } + var cek_default = (alg) => random_default(new Uint8Array(bitLength2(alg) >> 3)); + + // dist/browser/lib/format_pem.js + var format_pem_default = (b64, descriptor) => { + const newlined = (b64.match(/.{1,64}/g) || []).join("\n"); + return `-----BEGIN ${descriptor}----- +${newlined} +-----END ${descriptor}-----`; + }; + + // dist/browser/runtime/asn1.js + var genericExport = async (keyType, keyFormat, key) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + if (!key.extractable) { + throw new TypeError("CryptoKey is not extractable"); + } + if (key.type !== keyType) { + throw new TypeError(`key is not a ${keyType} key`); + } + return format_pem_default(encodeBase64(new Uint8Array(await webcrypto_default.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`); + }; + var toSPKI = (key) => { + return genericExport("public", "spki", key); + }; + var toPKCS8 = (key) => { + return genericExport("private", "pkcs8", key); + }; + var findOid = (keyData, oid, from = 0) => { + if (from === 0) { + oid.unshift(oid.length); + oid.unshift(6); + } + let i = keyData.indexOf(oid[0], from); + if (i === -1) + return false; + const sub = keyData.subarray(i, i + oid.length); + if (sub.length !== oid.length) + return false; + return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1); + }; + var getNamedCurve2 = (keyData) => { + switch (true) { + case findOid(keyData, [42, 134, 72, 206, 61, 3, 1, 7]): + return "P-256"; + case findOid(keyData, [43, 129, 4, 0, 34]): + return "P-384"; + case findOid(keyData, [43, 129, 4, 0, 35]): + return "P-521"; + case findOid(keyData, [43, 101, 110]): + return "X25519"; + case findOid(keyData, [43, 101, 111]): + return "X448"; + case findOid(keyData, [43, 101, 112]): + return "Ed25519"; + case findOid(keyData, [43, 101, 113]): + return "Ed448"; + default: + throw new JOSENotSupported("Invalid or unsupported EC Key Curve or OKP Key Sub Type"); + } + }; + var genericImport = async (replace, keyFormat, pem, alg, options) => { + var _a, _b; + let algorithm; + let keyUsages; + const keyData = new Uint8Array(atob(pem.replace(replace, "")).split("").map((c) => c.charCodeAt(0))); + const isPublic = keyFormat === "spki"; + switch (alg) { + case "PS256": + case "PS384": + case "PS512": + algorithm = { name: "RSA-PSS", hash: `SHA-${alg.slice(-3)}` }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "RS256": + case "RS384": + case "RS512": + algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.slice(-3)}` }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + algorithm = { + name: "RSA-OAEP", + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}` + }; + keyUsages = isPublic ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"]; + break; + case "ES256": + algorithm = { name: "ECDSA", namedCurve: "P-256" }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "ES384": + algorithm = { name: "ECDSA", namedCurve: "P-384" }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "ES512": + algorithm = { name: "ECDSA", namedCurve: "P-521" }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + const namedCurve = getNamedCurve2(keyData); + algorithm = namedCurve.startsWith("P-") ? { name: "ECDH", namedCurve } : { name: namedCurve }; + keyUsages = isPublic ? [] : ["deriveBits"]; + break; + } + case "EdDSA": + algorithm = { name: getNamedCurve2(keyData) }; + keyUsages = isPublic ? ["verify"] : ["sign"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value'); + } + try { + return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); + } catch (err) { + if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { + algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + return await webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages); + } + throw err; + } + }; + var fromPKCS8 = (pem, alg, options) => { + return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, "pkcs8", pem, alg, options); + }; + var fromSPKI = (pem, alg, options) => { + return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "spki", pem, alg, options); + }; + function getElement(seq) { + let result = []; + let next = 0; + while (next < seq.length) { + let nextPart = parseElement(seq.subarray(next)); + result.push(nextPart); + next += nextPart.byteLength; + } + return result; + } + function parseElement(bytes) { + let position = 0; + let tag = bytes[0] & 31; + position++; + if (tag === 31) { + tag = 0; + while (bytes[position] >= 128) { + tag = tag * 128 + bytes[position] - 128; + position++; + } + tag = tag * 128 + bytes[position] - 128; + position++; + } + let length = 0; + if (bytes[position] < 128) { + length = bytes[position]; + position++; + } else if (length === 128) { + length = 0; + while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { + if (length > bytes.byteLength) { + throw new TypeError("invalid indefinite form length"); + } + length++; + } + const byteLength2 = position + length + 2; + return { + byteLength: byteLength2, + contents: bytes.subarray(position, position + length), + raw: bytes.subarray(0, byteLength2) + }; + } else { + let numberOfDigits = bytes[position] & 127; + position++; + length = 0; + for (let i = 0; i < numberOfDigits; i++) { + length = length * 256 + bytes[position]; + position++; + } + } + const byteLength = position + length; + return { + byteLength, + contents: bytes.subarray(position, byteLength), + raw: bytes.subarray(0, byteLength) + }; + } + function spkiFromX509(buf) { + const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents); + return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 160 ? 6 : 5].raw); + } + function getSPKI(x509) { + const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ""); + const raw = decodeBase64(pem); + return format_pem_default(spkiFromX509(raw), "PUBLIC KEY"); + } + var fromX509 = (pem, alg, options) => { + let spki; + try { + spki = getSPKI(pem); + } catch (cause) { + throw new TypeError("failed to parse the X.509 certificate", { cause }); + } + return fromSPKI(spki, alg, options); + }; + + // dist/browser/runtime/jwk_to_key.js + function subtleMapping(jwk) { + let algorithm; + let keyUsages; + switch (jwk.kty) { + case "oct": { + switch (jwk.alg) { + case "HS256": + case "HS384": + case "HS512": + algorithm = { name: "HMAC", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = ["sign", "verify"]; + break; + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`); + case "A128GCM": + case "A192GCM": + case "A256GCM": + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": + algorithm = { name: "AES-GCM" }; + keyUsages = ["encrypt", "decrypt"]; + break; + case "A128KW": + case "A192KW": + case "A256KW": + algorithm = { name: "AES-KW" }; + keyUsages = ["wrapKey", "unwrapKey"]; + break; + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": + algorithm = { name: "PBKDF2" }; + keyUsages = ["deriveBits"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "RSA": { + switch (jwk.alg) { + case "PS256": + case "PS384": + case "PS512": + algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "RS256": + case "RS384": + case "RS512": + algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + algorithm = { + name: "RSA-OAEP", + hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}` + }; + keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "EC": { + switch (jwk.alg) { + case "ES256": + algorithm = { name: "ECDSA", namedCurve: "P-256" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ES384": + algorithm = { name: "ECDSA", namedCurve: "P-384" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ES512": + algorithm = { name: "ECDSA", namedCurve: "P-521" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": + algorithm = { name: "ECDH", namedCurve: jwk.crv }; + keyUsages = jwk.d ? ["deriveBits"] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "OKP": { + switch (jwk.alg) { + case "EdDSA": + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ["deriveBits"] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); + } + return { algorithm, keyUsages }; + } + var parse = async (jwk) => { + var _a, _b; + if (!jwk.alg) { + throw new TypeError('"alg" argument is required when "jwk.alg" is not present'); + } + const { algorithm, keyUsages } = subtleMapping(jwk); + const rest = [ + algorithm, + (_a = jwk.ext) !== null && _a !== void 0 ? _a : false, + (_b = jwk.key_ops) !== null && _b !== void 0 ? _b : keyUsages + ]; + if (algorithm.name === "PBKDF2") { + return webcrypto_default.subtle.importKey("raw", decode(jwk.k), ...rest); + } + const keyData = { ...jwk }; + delete keyData.alg; + delete keyData.use; + try { + return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); + } catch (err) { + if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { + rest[0] = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + return await webcrypto_default.subtle.importKey("jwk", keyData, ...rest); + } + throw err; + } + }; + var jwk_to_key_default = parse; + + // dist/browser/key/import.js + async function importSPKI(spki, alg, options) { + if (typeof spki !== "string" || spki.indexOf("-----BEGIN PUBLIC KEY-----") !== 0) { + throw new TypeError('"spki" must be SPKI formatted string'); + } + return fromSPKI(spki, alg, options); + } + async function importX509(x509, alg, options) { + if (typeof x509 !== "string" || x509.indexOf("-----BEGIN CERTIFICATE-----") !== 0) { + throw new TypeError('"x509" must be X.509 formatted string'); + } + return fromX509(x509, alg, options); + } + async function importPKCS8(pkcs8, alg, options) { + if (typeof pkcs8 !== "string" || pkcs8.indexOf("-----BEGIN PRIVATE KEY-----") !== 0) { + throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); + } + return fromPKCS8(pkcs8, alg, options); + } + async function importJWK(jwk, alg, octAsKeyObject) { + var _a; + if (!isObject(jwk)) { + throw new TypeError("JWK must be an object"); + } + alg || (alg = jwk.alg); + switch (jwk.kty) { + case "oct": + if (typeof jwk.k !== "string" || !jwk.k) { + throw new TypeError('missing "k" (Key Value) Parameter value'); + } + octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : octAsKeyObject = jwk.ext !== true; + if (octAsKeyObject) { + return jwk_to_key_default({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); + } + return decode(jwk.k); + case "RSA": + if (jwk.oth !== void 0) { + throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); + } + case "EC": + case "OKP": + return jwk_to_key_default({ ...jwk, alg }); + default: + throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); + } + } + + // dist/browser/lib/check_key_type.js + var symmetricTypeCheck = (alg, key) => { + if (key instanceof Uint8Array) + return; + if (!is_key_like_default(key)) { + throw new TypeError(withAlg(alg, key, ...types, "Uint8Array")); + } + if (key.type !== "secret") { + throw new TypeError(`${types.join(" or ")} instances for symmetric algorithms must be of type "secret"`); + } + }; + var asymmetricTypeCheck = (alg, key, usage) => { + if (!is_key_like_default(key)) { + throw new TypeError(withAlg(alg, key, ...types)); + } + if (key.type === "secret") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`); + } + if (usage === "sign" && key.type === "public") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`); + } + if (usage === "decrypt" && key.type === "public") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`); + } + if (key.algorithm && usage === "verify" && key.type === "private") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`); + } + if (key.algorithm && usage === "encrypt" && key.type === "private") { + throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`); + } + }; + var checkKeyType = (alg, key, usage) => { + const symmetric = alg.startsWith("HS") || alg === "dir" || alg.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(alg); + if (symmetric) { + symmetricTypeCheck(alg, key); + } else { + asymmetricTypeCheck(alg, key, usage); + } + }; + var check_key_type_default = checkKeyType; + + // dist/browser/runtime/encrypt.js + async function cbcEncrypt(enc, plaintext, cek, iv, aad) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, "Uint8Array")); + } + const keySize = parseInt(enc.slice(1, 4), 10); + const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["encrypt"]); + const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), { + hash: `SHA-${keySize << 1}`, + name: "HMAC" + }, false, ["sign"]); + const ciphertext = new Uint8Array(await webcrypto_default.subtle.encrypt({ + iv, + name: "AES-CBC" + }, encKey, plaintext)); + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); + const tag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)); + return { ciphertext, tag }; + } + async function gcmEncrypt(enc, plaintext, cek, iv, aad) { + let encKey; + if (cek instanceof Uint8Array) { + encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["encrypt"]); + } else { + checkEncCryptoKey(cek, enc, "encrypt"); + encKey = cek; + } + const encrypted = new Uint8Array(await webcrypto_default.subtle.encrypt({ + additionalData: aad, + iv, + name: "AES-GCM", + tagLength: 128 + }, encKey, plaintext)); + const tag = encrypted.slice(-16); + const ciphertext = encrypted.slice(0, -16); + return { ciphertext, tag }; + } + var encrypt3 = async (enc, plaintext, cek, iv, aad) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array")); + } + check_iv_length_default(enc, iv); + switch (enc) { + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(-3), 10)); + return cbcEncrypt(enc, plaintext, cek, iv, aad); + case "A128GCM": + case "A192GCM": + case "A256GCM": + if (cek instanceof Uint8Array) + check_cek_length_default(cek, parseInt(enc.slice(1, 4), 10)); + return gcmEncrypt(enc, plaintext, cek, iv, aad); + default: + throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm"); + } + }; + var encrypt_default = encrypt3; + + // dist/browser/lib/aesgcmkw.js + async function wrap2(alg, key, cek, iv) { + const jweAlgorithm = alg.slice(0, 7); + iv || (iv = iv_default(jweAlgorithm)); + const { ciphertext: encryptedKey, tag } = await encrypt_default(jweAlgorithm, cek, key, iv, new Uint8Array(0)); + return { encryptedKey, iv: encode(iv), tag: encode(tag) }; + } + async function unwrap2(alg, key, encryptedKey, iv, tag) { + const jweAlgorithm = alg.slice(0, 7); + return decrypt_default(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); + } + + // dist/browser/lib/decrypt_key_management.js + async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { + check_key_type_default(alg, key, "decrypt"); + switch (alg) { + case "dir": { + if (encryptedKey !== void 0) + throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); + return key; + } + case "ECDH-ES": + if (encryptedKey !== void 0) + throw new JWEInvalid("Encountered unexpected JWE Encrypted Key"); + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + if (!isObject(joseHeader.epk)) + throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); + if (!ecdhAllowed(key)) + throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); + const epk = await importJWK(joseHeader.epk, alg); + let partyUInfo; + let partyVInfo; + if (joseHeader.apu !== void 0) { + if (typeof joseHeader.apu !== "string") + throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); + partyUInfo = decode(joseHeader.apu); + } + if (joseHeader.apv !== void 0) { + if (typeof joseHeader.apv !== "string") + throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); + partyVInfo = decode(joseHeader.apv); + } + const sharedSecret = await deriveKey(epk, key, alg === "ECDH-ES" ? joseHeader.enc : alg, alg === "ECDH-ES" ? bitLength2(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); + if (alg === "ECDH-ES") + return sharedSecret; + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + return unwrap(alg.slice(-6), sharedSecret, encryptedKey); + } + case "RSA1_5": + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + return decrypt3(alg, key, encryptedKey); + } + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + if (typeof joseHeader.p2c !== "number") + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); + const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 1e4; + if (joseHeader.p2c > p2cLimit) + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); + if (typeof joseHeader.p2s !== "string") + throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); + return decrypt2(alg, key, encryptedKey, joseHeader.p2c, decode(joseHeader.p2s)); + } + case "A128KW": + case "A192KW": + case "A256KW": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + return unwrap(alg, key, encryptedKey); + } + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": { + if (encryptedKey === void 0) + throw new JWEInvalid("JWE Encrypted Key missing"); + if (typeof joseHeader.iv !== "string") + throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); + if (typeof joseHeader.tag !== "string") + throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); + const iv = decode(joseHeader.iv); + const tag = decode(joseHeader.tag); + return unwrap2(alg, key, encryptedKey, iv, tag); + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } + } + var decrypt_key_management_default = decryptKeyManagement; + + // dist/browser/lib/validate_crit.js + function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { + if (joseHeader.crit !== void 0 && protectedHeader.crit === void 0) { + throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); + } + if (!protectedHeader || protectedHeader.crit === void 0) { + return /* @__PURE__ */ new Set(); + } + if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) { + throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); + } + let recognized; + if (recognizedOption !== void 0) { + recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); + } else { + recognized = recognizedDefault; + } + for (const parameter of protectedHeader.crit) { + if (!recognized.has(parameter)) { + throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); + } + if (joseHeader[parameter] === void 0) { + throw new Err(`Extension Header Parameter "${parameter}" is missing`); + } else if (recognized.get(parameter) && protectedHeader[parameter] === void 0) { + throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); + } + } + return new Set(protectedHeader.crit); + } + var validate_crit_default = validateCrit; + + // dist/browser/lib/validate_algorithms.js + var validateAlgorithms = (option, algorithms) => { + if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) { + throw new TypeError(`"${option}" option must be an array of strings`); + } + if (!algorithms) { + return void 0; + } + return new Set(algorithms); + }; + var validate_algorithms_default = validateAlgorithms; + + // dist/browser/jwe/flattened/decrypt.js + async function flattenedDecrypt(jwe, key, options) { + var _a; + if (!isObject(jwe)) { + throw new JWEInvalid("Flattened JWE must be an object"); + } + if (jwe.protected === void 0 && jwe.header === void 0 && jwe.unprotected === void 0) { + throw new JWEInvalid("JOSE Header missing"); + } + if (typeof jwe.iv !== "string") { + throw new JWEInvalid("JWE Initialization Vector missing or incorrect type"); + } + if (typeof jwe.ciphertext !== "string") { + throw new JWEInvalid("JWE Ciphertext missing or incorrect type"); + } + if (typeof jwe.tag !== "string") { + throw new JWEInvalid("JWE Authentication Tag missing or incorrect type"); + } + if (jwe.protected !== void 0 && typeof jwe.protected !== "string") { + throw new JWEInvalid("JWE Protected Header incorrect type"); + } + if (jwe.encrypted_key !== void 0 && typeof jwe.encrypted_key !== "string") { + throw new JWEInvalid("JWE Encrypted Key incorrect type"); + } + if (jwe.aad !== void 0 && typeof jwe.aad !== "string") { + throw new JWEInvalid("JWE AAD incorrect type"); + } + if (jwe.header !== void 0 && !isObject(jwe.header)) { + throw new JWEInvalid("JWE Shared Unprotected Header incorrect type"); + } + if (jwe.unprotected !== void 0 && !isObject(jwe.unprotected)) { + throw new JWEInvalid("JWE Per-Recipient Unprotected Header incorrect type"); + } + let parsedProt; + if (jwe.protected) { + try { + const protectedHeader2 = decode(jwe.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader2)); + } catch (_b) { + throw new JWEInvalid("JWE Protected Header is invalid"); + } + } + if (!is_disjoint_default(parsedProt, jwe.header, jwe.unprotected)) { + throw new JWEInvalid("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint"); + } + const joseHeader = { + ...parsedProt, + ...jwe.header, + ...jwe.unprotected + }; + validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + if (joseHeader.zip !== void 0) { + if (!parsedProt || !parsedProt.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== "DEF") { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWEInvalid("missing JWE Algorithm (alg) in JWE Header"); + } + if (typeof enc !== "string" || !enc) { + throw new JWEInvalid("missing JWE Encryption Algorithm (enc) in JWE Header"); + } + const keyManagementAlgorithms = options && validate_algorithms_default("keyManagementAlgorithms", options.keyManagementAlgorithms); + const contentEncryptionAlgorithms = options && validate_algorithms_default("contentEncryptionAlgorithms", options.contentEncryptionAlgorithms); + if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { + throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); + } + let encryptedKey; + if (jwe.encrypted_key !== void 0) { + encryptedKey = decode(jwe.encrypted_key); + } + let resolvedKey = false; + if (typeof key === "function") { + key = await key(parsedProt, jwe); + resolvedKey = true; + } + let cek; + try { + cek = await decrypt_key_management_default(alg, key, encryptedKey, joseHeader, options); + } catch (err) { + if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { + throw err; + } + cek = cek_default(enc); + } + const iv = decode(jwe.iv); + const tag = decode(jwe.tag); + const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ""); + let additionalData; + if (jwe.aad !== void 0) { + additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(jwe.aad)); + } else { + additionalData = protectedHeader; + } + let plaintext = await decrypt_default(enc, cek, decode(jwe.ciphertext), iv, tag, additionalData); + if (joseHeader.zip === "DEF") { + plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); + } + const result = { plaintext }; + if (jwe.protected !== void 0) { + result.protectedHeader = parsedProt; + } + if (jwe.aad !== void 0) { + result.additionalAuthenticatedData = decode(jwe.aad); + } + if (jwe.unprotected !== void 0) { + result.sharedUnprotectedHeader = jwe.unprotected; + } + if (jwe.header !== void 0) { + result.unprotectedHeader = jwe.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; + } + + // dist/browser/jwe/compact/decrypt.js + async function compactDecrypt(jwe, key, options) { + if (jwe instanceof Uint8Array) { + jwe = decoder.decode(jwe); + } + if (typeof jwe !== "string") { + throw new JWEInvalid("Compact JWE must be a string or Uint8Array"); + } + const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length } = jwe.split("."); + if (length !== 5) { + throw new JWEInvalid("Invalid Compact JWE"); + } + const decrypted = await flattenedDecrypt({ + ciphertext, + iv: iv || void 0, + protected: protectedHeader || void 0, + tag: tag || void 0, + encrypted_key: encryptedKey || void 0 + }, key, options); + const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: decrypted.key }; + } + return result; + } + + // dist/browser/jwe/general/decrypt.js + async function generalDecrypt(jwe, key, options) { + if (!isObject(jwe)) { + throw new JWEInvalid("General JWE must be an object"); + } + if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { + throw new JWEInvalid("JWE Recipients missing or incorrect type"); + } + if (!jwe.recipients.length) { + throw new JWEInvalid("JWE Recipients has no members"); + } + for (const recipient of jwe.recipients) { + try { + return await flattenedDecrypt({ + aad: jwe.aad, + ciphertext: jwe.ciphertext, + encrypted_key: recipient.encrypted_key, + header: recipient.header, + iv: jwe.iv, + protected: jwe.protected, + tag: jwe.tag, + unprotected: jwe.unprotected + }, key, options); + } catch (_a) { + } + } + throw new JWEDecryptionFailed(); + } + + // dist/browser/runtime/key_to_jwk.js + var keyToJWK = async (key) => { + if (key instanceof Uint8Array) { + return { + kty: "oct", + k: encode(key) + }; + } + if (!isCryptoKey(key)) { + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); + } + if (!key.extractable) { + throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK"); + } + const { ext, key_ops, alg, use, ...jwk } = await webcrypto_default.subtle.exportKey("jwk", key); + return jwk; + }; + var key_to_jwk_default = keyToJWK; + + // dist/browser/key/export.js + async function exportSPKI(key) { + return toSPKI(key); + } + async function exportPKCS8(key) { + return toPKCS8(key); + } + async function exportJWK(key) { + return key_to_jwk_default(key); + } + + // dist/browser/lib/encrypt_key_management.js + async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { + let encryptedKey; + let parameters; + let cek; + check_key_type_default(alg, key, "encrypt"); + switch (alg) { + case "dir": { + cek = key; + break; + } + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + if (!ecdhAllowed(key)) { + throw new JOSENotSupported("ECDH with the provided key is not allowed or not supported by your javascript runtime"); + } + const { apu, apv } = providedParameters; + let { epk: ephemeralKey } = providedParameters; + ephemeralKey || (ephemeralKey = (await generateEpk(key)).privateKey); + const { x, y, crv, kty } = await exportJWK(ephemeralKey); + const sharedSecret = await deriveKey(key, ephemeralKey, alg === "ECDH-ES" ? enc : alg, alg === "ECDH-ES" ? bitLength2(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); + parameters = { epk: { x, crv, kty } }; + if (kty === "EC") + parameters.epk.y = y; + if (apu) + parameters.apu = encode(apu); + if (apv) + parameters.apv = encode(apv); + if (alg === "ECDH-ES") { + cek = sharedSecret; + break; + } + cek = providedCek || cek_default(enc); + const kwAlg = alg.slice(-6); + encryptedKey = await wrap(kwAlg, sharedSecret, cek); + break; + } + case "RSA1_5": + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": { + cek = providedCek || cek_default(enc); + encryptedKey = await encrypt2(alg, key, cek); + break; + } + case "PBES2-HS256+A128KW": + case "PBES2-HS384+A192KW": + case "PBES2-HS512+A256KW": { + cek = providedCek || cek_default(enc); + const { p2c, p2s: p2s2 } = providedParameters; + ({ encryptedKey, ...parameters } = await encrypt(alg, key, cek, p2c, p2s2)); + break; + } + case "A128KW": + case "A192KW": + case "A256KW": { + cek = providedCek || cek_default(enc); + encryptedKey = await wrap(alg, key, cek); + break; + } + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": { + cek = providedCek || cek_default(enc); + const { iv } = providedParameters; + ({ encryptedKey, ...parameters } = await wrap2(alg, key, cek, iv)); + break; + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } + return { cek, encryptedKey, parameters }; + } + var encrypt_key_management_default = encryptKeyManagement; + + // dist/browser/jwe/flattened/encrypt.js + var unprotected = Symbol(); + var FlattenedEncrypt = class { + constructor(plaintext) { + if (!(plaintext instanceof Uint8Array)) { + throw new TypeError("plaintext must be an instance of Uint8Array"); + } + this._plaintext = plaintext; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError("setKeyManagementParameters can only be called once"); + } + this._keyManagementParameters = parameters; + return this; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._sharedUnprotectedHeader) { + throw new TypeError("setSharedUnprotectedHeader can only be called once"); + } + this._sharedUnprotectedHeader = sharedUnprotectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError("setContentEncryptionKey can only be called once"); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError("setInitializationVector can only be called once"); + } + this._iv = iv; + return this; + } + async encrypt(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { + throw new JWEInvalid("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()"); + } + if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { + throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...this._sharedUnprotectedHeader + }; + validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== void 0) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== "DEF") { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (typeof enc !== "string" || !enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + let encryptedKey; + if (alg === "dir") { + if (this._cek) { + throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption"); + } + } else if (alg === "ECDH-ES") { + if (this._cek) { + throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement"); + } + } + let cek; + { + let parameters; + ({ cek, encryptedKey, parameters } = await encrypt_key_management_default(alg, enc, key, this._cek, this._keyManagementParameters)); + if (parameters) { + if (options && unprotected in options) { + if (!this._unprotectedHeader) { + this.setUnprotectedHeader(parameters); + } else { + this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; + } + } else { + if (!this._protectedHeader) { + this.setProtectedHeader(parameters); + } else { + this._protectedHeader = { ...this._protectedHeader, ...parameters }; + } + } + } + } + this._iv || (this._iv = iv_default(enc)); + let additionalData; + let protectedHeader; + let aadMember; + if (this._protectedHeader) { + protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); + } else { + protectedHeader = encoder.encode(""); + } + if (this._aad) { + aadMember = encode(this._aad); + additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(aadMember)); + } else { + additionalData = protectedHeader; + } + let ciphertext; + let tag; + if (joseHeader.zip === "DEF") { + const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); + ({ ciphertext, tag } = await encrypt_default(enc, deflated, cek, this._iv, additionalData)); + } else { + ({ ciphertext, tag } = await encrypt_default(enc, this._plaintext, cek, this._iv, additionalData)); + } + const jwe = { + ciphertext: encode(ciphertext), + iv: encode(this._iv), + tag: encode(tag) + }; + if (encryptedKey) { + jwe.encrypted_key = encode(encryptedKey); + } + if (aadMember) { + jwe.aad = aadMember; + } + if (this._protectedHeader) { + jwe.protected = decoder.decode(protectedHeader); + } + if (this._sharedUnprotectedHeader) { + jwe.unprotected = this._sharedUnprotectedHeader; + } + if (this._unprotectedHeader) { + jwe.header = this._unprotectedHeader; + } + return jwe; + } + }; + + // dist/browser/jwe/general/encrypt.js + var IndividualRecipient = class { + constructor(enc, key, options) { + this.parent = enc; + this.key = key; + this.options = options; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addRecipient(...args) { + return this.parent.addRecipient(...args); + } + encrypt(...args) { + return this.parent.encrypt(...args); + } + done() { + return this.parent; + } + }; + var GeneralEncrypt = class { + constructor(plaintext) { + this._recipients = []; + this._plaintext = plaintext; + } + addRecipient(key, options) { + const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); + this._recipients.push(recipient); + return recipient; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError("setSharedUnprotectedHeader can only be called once"); + } + this._unprotectedHeader = sharedUnprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + async encrypt(options) { + var _a, _b, _c; + if (!this._recipients.length) { + throw new JWEInvalid("at least one recipient must be added"); + } + options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; + if (this._recipients.length === 1) { + const [recipient] = this._recipients; + const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).encrypt(recipient.key, { ...recipient.options, ...options }); + let jwe2 = { + ciphertext: flattened.ciphertext, + iv: flattened.iv, + recipients: [{}], + tag: flattened.tag + }; + if (flattened.aad) + jwe2.aad = flattened.aad; + if (flattened.protected) + jwe2.protected = flattened.protected; + if (flattened.unprotected) + jwe2.unprotected = flattened.unprotected; + if (flattened.encrypted_key) + jwe2.recipients[0].encrypted_key = flattened.encrypted_key; + if (flattened.header) + jwe2.recipients[0].header = flattened.header; + return jwe2; + } + let enc; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { + throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint"); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader + }; + const { alg } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (alg === "dir" || alg === "ECDH-ES") { + throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); + } + if (typeof joseHeader.enc !== "string" || !joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + if (!enc) { + enc = joseHeader.enc; + } else if (enc !== joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); + } + validate_crit_default(JWEInvalid, /* @__PURE__ */ new Map(), recipient.options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== void 0) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + } + } + const cek = cek_default(enc); + let jwe = { + ciphertext: "", + iv: "", + recipients: [], + tag: "" + }; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + const target = {}; + jwe.recipients.push(target); + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader + }; + const p2c = joseHeader.alg.startsWith("PBES2") ? 2048 + i : void 0; + if (i === 0) { + const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setContentEncryptionKey(cek).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).setKeyManagementParameters({ p2c }).encrypt(recipient.key, { + ...recipient.options, + ...options, + [unprotected]: true + }); + jwe.ciphertext = flattened.ciphertext; + jwe.iv = flattened.iv; + jwe.tag = flattened.tag; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + target.encrypted_key = flattened.encrypted_key; + if (flattened.header) + target.header = flattened.header; + continue; + } + const { encryptedKey, parameters } = await encrypt_key_management_default(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); + target.encrypted_key = encode(encryptedKey); + if (recipient.unprotectedHeader || parameters) + target.header = { ...recipient.unprotectedHeader, ...parameters }; + } + return jwe; + } + }; + + // dist/browser/runtime/subtle_dsa.js + function subtleDsa(alg, algorithm) { + const hash = `SHA-${alg.slice(-3)}`; + switch (alg) { + case "HS256": + case "HS384": + case "HS512": + return { hash, name: "HMAC" }; + case "PS256": + case "PS384": + case "PS512": + return { hash, name: "RSA-PSS", saltLength: alg.slice(-3) >> 3 }; + case "RS256": + case "RS384": + case "RS512": + return { hash, name: "RSASSA-PKCS1-v1_5" }; + case "ES256": + case "ES384": + case "ES512": + return { hash, name: "ECDSA", namedCurve: algorithm.namedCurve }; + case "EdDSA": + if (isCloudflareWorkers() && algorithm.name === "NODE-ED25519") { + return { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + } + return { name: algorithm.name }; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } + } + + // dist/browser/runtime/get_sign_verify_key.js + function getCryptoKey3(alg, key, usage) { + if (isCryptoKey(key)) { + checkSigCryptoKey(key, alg, usage); + return key; + } + if (key instanceof Uint8Array) { + if (!alg.startsWith("HS")) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + return webcrypto_default.subtle.importKey("raw", key, { hash: `SHA-${alg.slice(-3)}`, name: "HMAC" }, false, [usage]); + } + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array")); + } + + // dist/browser/runtime/verify.js + var verify = async (alg, key, signature, data) => { + const cryptoKey = await getCryptoKey3(alg, key, "verify"); + check_key_length_default(alg, cryptoKey); + const algorithm = subtleDsa(alg, cryptoKey.algorithm); + try { + return await webcrypto_default.subtle.verify(algorithm, cryptoKey, signature, data); + } catch (_a) { + return false; + } + }; + var verify_default = verify; + + // dist/browser/jws/flattened/verify.js + async function flattenedVerify(jws, key, options) { + var _a; + if (!isObject(jws)) { + throw new JWSInvalid("Flattened JWS must be an object"); + } + if (jws.protected === void 0 && jws.header === void 0) { + throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); + } + if (jws.protected !== void 0 && typeof jws.protected !== "string") { + throw new JWSInvalid("JWS Protected Header incorrect type"); + } + if (jws.payload === void 0) { + throw new JWSInvalid("JWS Payload missing"); + } + if (typeof jws.signature !== "string") { + throw new JWSInvalid("JWS Signature missing or incorrect type"); + } + if (jws.header !== void 0 && !isObject(jws.header)) { + throw new JWSInvalid("JWS Unprotected Header incorrect type"); + } + let parsedProt = {}; + if (jws.protected) { + try { + const protectedHeader = decode(jws.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader)); + } catch (_b) { + throw new JWSInvalid("JWS Protected Header is invalid"); + } + } + if (!is_disjoint_default(parsedProt, jws.header)) { + throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); + } + const joseHeader = { + ...parsedProt, + ...jws.header + }; + const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + let b64 = true; + if (extensions.has("b64")) { + b64 = parsedProt.b64; + if (typeof b64 !== "boolean") { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + const algorithms = options && validate_algorithms_default("algorithms", options.algorithms); + if (algorithms && !algorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (b64) { + if (typeof jws.payload !== "string") { + throw new JWSInvalid("JWS Payload must be a string"); + } + } else if (typeof jws.payload !== "string" && !(jws.payload instanceof Uint8Array)) { + throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance"); + } + let resolvedKey = false; + if (typeof key === "function") { + key = await key(parsedProt, jws); + resolvedKey = true; + } + check_key_type_default(alg, key, "verify"); + const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ""), encoder.encode("."), typeof jws.payload === "string" ? encoder.encode(jws.payload) : jws.payload); + const signature = decode(jws.signature); + const verified = await verify_default(alg, key, signature, data); + if (!verified) { + throw new JWSSignatureVerificationFailed(); + } + let payload; + if (b64) { + payload = decode(jws.payload); + } else if (typeof jws.payload === "string") { + payload = encoder.encode(jws.payload); + } else { + payload = jws.payload; + } + const result = { payload }; + if (jws.protected !== void 0) { + result.protectedHeader = parsedProt; + } + if (jws.header !== void 0) { + result.unprotectedHeader = jws.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; + } + + // dist/browser/jws/compact/verify.js + async function compactVerify(jws, key, options) { + if (jws instanceof Uint8Array) { + jws = decoder.decode(jws); + } + if (typeof jws !== "string") { + throw new JWSInvalid("Compact JWS must be a string or Uint8Array"); + } + const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split("."); + if (length !== 3) { + throw new JWSInvalid("Invalid Compact JWS"); + } + const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); + const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: verified.key }; + } + return result; + } + + // dist/browser/jws/general/verify.js + async function generalVerify(jws, key, options) { + if (!isObject(jws)) { + throw new JWSInvalid("General JWS must be an object"); + } + if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { + throw new JWSInvalid("JWS Signatures missing or incorrect type"); + } + for (const signature of jws.signatures) { + try { + return await flattenedVerify({ + header: signature.header, + payload: jws.payload, + protected: signature.protected, + signature: signature.signature + }, key, options); + } catch (_a) { + } + } + throw new JWSSignatureVerificationFailed(); + } + + // dist/browser/lib/epoch.js + var epoch_default = (date) => Math.floor(date.getTime() / 1e3); + + // dist/browser/lib/secs.js + var minute = 60; + var hour = minute * 60; + var day = hour * 24; + var week = day * 7; + var year = day * 365.25; + var REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; + var secs_default = (str) => { + const matched = REGEX.exec(str); + if (!matched) { + throw new TypeError("Invalid time period format"); + } + const value = parseFloat(matched[1]); + const unit = matched[2].toLowerCase(); + switch (unit) { + case "sec": + case "secs": + case "second": + case "seconds": + case "s": + return Math.round(value); + case "minute": + case "minutes": + case "min": + case "mins": + case "m": + return Math.round(value * minute); + case "hour": + case "hours": + case "hr": + case "hrs": + case "h": + return Math.round(value * hour); + case "day": + case "days": + case "d": + return Math.round(value * day); + case "week": + case "weeks": + case "w": + return Math.round(value * week); + default: + return Math.round(value * year); + } + }; + + // dist/browser/lib/jwt_claims_set.js + var normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ""); + var checkAudiencePresence = (audPayload, audOption) => { + if (typeof audPayload === "string") { + return audOption.includes(audPayload); + } + if (Array.isArray(audPayload)) { + return audOption.some(Set.prototype.has.bind(new Set(audPayload))); + } + return false; + }; + var jwt_claims_set_default = (protectedHeader, encodedPayload, options = {}) => { + const { typ } = options; + if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { + throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', "typ", "check_failed"); + } + let payload; + try { + payload = JSON.parse(decoder.decode(encodedPayload)); + } catch (_a) { + } + if (!isObject(payload)) { + throw new JWTInvalid("JWT Claims Set must be a top-level JSON object"); + } + const { issuer } = options; + if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { + throw new JWTClaimValidationFailed('unexpected "iss" claim value', "iss", "check_failed"); + } + const { subject } = options; + if (subject && payload.sub !== subject) { + throw new JWTClaimValidationFailed('unexpected "sub" claim value', "sub", "check_failed"); + } + const { audience } = options; + if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) { + throw new JWTClaimValidationFailed('unexpected "aud" claim value', "aud", "check_failed"); + } + let tolerance; + switch (typeof options.clockTolerance) { + case "string": + tolerance = secs_default(options.clockTolerance); + break; + case "number": + tolerance = options.clockTolerance; + break; + case "undefined": + tolerance = 0; + break; + default: + throw new TypeError("Invalid clockTolerance option type"); + } + const { currentDate } = options; + const now = epoch_default(currentDate || /* @__PURE__ */ new Date()); + if ((payload.iat !== void 0 || options.maxTokenAge) && typeof payload.iat !== "number") { + throw new JWTClaimValidationFailed('"iat" claim must be a number', "iat", "invalid"); + } + if (payload.nbf !== void 0) { + if (typeof payload.nbf !== "number") { + throw new JWTClaimValidationFailed('"nbf" claim must be a number', "nbf", "invalid"); + } + if (payload.nbf > now + tolerance) { + throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', "nbf", "check_failed"); + } + } + if (payload.exp !== void 0) { + if (typeof payload.exp !== "number") { + throw new JWTClaimValidationFailed('"exp" claim must be a number', "exp", "invalid"); + } + if (payload.exp <= now - tolerance) { + throw new JWTExpired('"exp" claim timestamp check failed', "exp", "check_failed"); + } + } + if (options.maxTokenAge) { + const age = now - payload.iat; + const max = typeof options.maxTokenAge === "number" ? options.maxTokenAge : secs_default(options.maxTokenAge); + if (age - tolerance > max) { + throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', "iat", "check_failed"); + } + if (age < 0 - tolerance) { + throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', "iat", "check_failed"); + } + } + return payload; + }; + + // dist/browser/jwt/verify.js + async function jwtVerify(jwt, key, options) { + var _a; + const verified = await compactVerify(jwt, key, options); + if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes("b64")) && verified.protectedHeader.b64 === false) { + throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); + } + const payload = jwt_claims_set_default(verified.protectedHeader, verified.payload, options); + const result = { payload, protectedHeader: verified.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: verified.key }; + } + return result; + } + + // dist/browser/jwt/decrypt.js + async function jwtDecrypt(jwt, key, options) { + const decrypted = await compactDecrypt(jwt, key, options); + const payload = jwt_claims_set_default(decrypted.protectedHeader, decrypted.plaintext, options); + const { protectedHeader } = decrypted; + if (protectedHeader.iss !== void 0 && protectedHeader.iss !== payload.iss) { + throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', "iss", "mismatch"); + } + if (protectedHeader.sub !== void 0 && protectedHeader.sub !== payload.sub) { + throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', "sub", "mismatch"); + } + if (protectedHeader.aud !== void 0 && JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { + throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', "aud", "mismatch"); + } + const result = { payload, protectedHeader }; + if (typeof key === "function") { + return { ...result, key: decrypted.key }; + } + return result; + } + + // dist/browser/jwe/compact/encrypt.js + var CompactEncrypt = class { + constructor(plaintext) { + this._flattened = new FlattenedEncrypt(plaintext); + } + setContentEncryptionKey(cek) { + this._flattened.setContentEncryptionKey(cek); + return this; + } + setInitializationVector(iv) { + this._flattened.setInitializationVector(iv); + return this; + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + setKeyManagementParameters(parameters) { + this._flattened.setKeyManagementParameters(parameters); + return this; + } + async encrypt(key, options) { + const jwe = await this._flattened.encrypt(key, options); + return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join("."); + } + }; + + // dist/browser/runtime/sign.js + var sign = async (alg, key, data) => { + const cryptoKey = await getCryptoKey3(alg, key, "sign"); + check_key_length_default(alg, cryptoKey); + const signature = await webcrypto_default.subtle.sign(subtleDsa(alg, cryptoKey.algorithm), cryptoKey, data); + return new Uint8Array(signature); + }; + var sign_default = sign; + + // dist/browser/jws/flattened/sign.js + var FlattenedSign = class { + constructor(payload) { + if (!(payload instanceof Uint8Array)) { + throw new TypeError("payload must be an instance of Uint8Array"); + } + this._payload = payload; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + async sign(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader) { + throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()"); + } + if (!is_disjoint_default(this._protectedHeader, this._unprotectedHeader)) { + throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader + }; + const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + let b64 = true; + if (extensions.has("b64")) { + b64 = this._protectedHeader.b64; + if (typeof b64 !== "boolean") { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + check_key_type_default(alg, key, "sign"); + let payload = this._payload; + if (b64) { + payload = encoder.encode(encode(payload)); + } + let protectedHeader; + if (this._protectedHeader) { + protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader))); + } else { + protectedHeader = encoder.encode(""); + } + const data = concat(protectedHeader, encoder.encode("."), payload); + const signature = await sign_default(alg, key, data); + const jws = { + signature: encode(signature), + payload: "" + }; + if (b64) { + jws.payload = decoder.decode(payload); + } + if (this._unprotectedHeader) { + jws.header = this._unprotectedHeader; + } + if (this._protectedHeader) { + jws.protected = decoder.decode(protectedHeader); + } + return jws; + } + }; + + // dist/browser/jws/compact/sign.js + var CompactSign = class { + constructor(payload) { + this._flattened = new FlattenedSign(payload); + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + async sign(key, options) { + const jws = await this._flattened.sign(key, options); + if (jws.payload === void 0) { + throw new TypeError("use the flattened module for creating JWS with b64: false"); + } + return `${jws.protected}.${jws.payload}.${jws.signature}`; + } + }; + + // dist/browser/jws/general/sign.js + var IndividualSignature = class { + constructor(sig, key, options) { + this.parent = sig; + this.key = key; + this.options = options; + } + setProtectedHeader(protectedHeader) { + if (this.protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this.protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError("setUnprotectedHeader can only be called once"); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addSignature(...args) { + return this.parent.addSignature(...args); + } + sign(...args) { + return this.parent.sign(...args); + } + done() { + return this.parent; + } + }; + var GeneralSign = class { + constructor(payload) { + this._signatures = []; + this._payload = payload; + } + addSignature(key, options) { + const signature = new IndividualSignature(this, key, options); + this._signatures.push(signature); + return signature; + } + async sign() { + if (!this._signatures.length) { + throw new JWSInvalid("at least one signature must be added"); + } + const jws = { + signatures: [], + payload: "" + }; + for (let i = 0; i < this._signatures.length; i++) { + const signature = this._signatures[i]; + const flattened = new FlattenedSign(this._payload); + flattened.setProtectedHeader(signature.protectedHeader); + flattened.setUnprotectedHeader(signature.unprotectedHeader); + const { payload, ...rest } = await flattened.sign(signature.key, signature.options); + if (i === 0) { + jws.payload = payload; + } else if (jws.payload !== payload) { + throw new JWSInvalid("inconsistent use of JWS Unencoded Payload Option (RFC7797)"); + } + jws.signatures.push(rest); + } + return jws; + } + }; + + // dist/browser/jwt/produce.js + var ProduceJWT = class { + constructor(payload) { + if (!isObject(payload)) { + throw new TypeError("JWT Claims Set MUST be an object"); + } + this._payload = payload; + } + setIssuer(issuer) { + this._payload = { ...this._payload, iss: issuer }; + return this; + } + setSubject(subject) { + this._payload = { ...this._payload, sub: subject }; + return this; + } + setAudience(audience) { + this._payload = { ...this._payload, aud: audience }; + return this; + } + setJti(jwtId) { + this._payload = { ...this._payload, jti: jwtId }; + return this; + } + setNotBefore(input) { + if (typeof input === "number") { + this._payload = { ...this._payload, nbf: input }; + } else { + this._payload = { ...this._payload, nbf: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; + } + return this; + } + setExpirationTime(input) { + if (typeof input === "number") { + this._payload = { ...this._payload, exp: input }; + } else { + this._payload = { ...this._payload, exp: epoch_default(/* @__PURE__ */ new Date()) + secs_default(input) }; + } + return this; + } + setIssuedAt(input) { + if (typeof input === "undefined") { + this._payload = { ...this._payload, iat: epoch_default(/* @__PURE__ */ new Date()) }; + } else { + this._payload = { ...this._payload, iat: input }; + } + return this; + } + }; + + // dist/browser/jwt/sign.js + var SignJWT = class extends ProduceJWT { + setProtectedHeader(protectedHeader) { + this._protectedHeader = protectedHeader; + return this; + } + async sign(key, options) { + var _a; + const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); + sig.setProtectedHeader(this._protectedHeader); + if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && this._protectedHeader.crit.includes("b64") && this._protectedHeader.b64 === false) { + throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); + } + return sig.sign(key, options); + } + }; + + // dist/browser/jwt/encrypt.js + var EncryptJWT = class extends ProduceJWT { + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError("setProtectedHeader can only be called once"); + } + this._protectedHeader = protectedHeader; + return this; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError("setKeyManagementParameters can only be called once"); + } + this._keyManagementParameters = parameters; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError("setContentEncryptionKey can only be called once"); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError("setInitializationVector can only be called once"); + } + this._iv = iv; + return this; + } + replicateIssuerAsHeader() { + this._replicateIssuerAsHeader = true; + return this; + } + replicateSubjectAsHeader() { + this._replicateSubjectAsHeader = true; + return this; + } + replicateAudienceAsHeader() { + this._replicateAudienceAsHeader = true; + return this; + } + async encrypt(key, options) { + const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); + if (this._replicateIssuerAsHeader) { + this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; + } + if (this._replicateSubjectAsHeader) { + this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; + } + if (this._replicateAudienceAsHeader) { + this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; + } + enc.setProtectedHeader(this._protectedHeader); + if (this._iv) { + enc.setInitializationVector(this._iv); + } + if (this._cek) { + enc.setContentEncryptionKey(this._cek); + } + if (this._keyManagementParameters) { + enc.setKeyManagementParameters(this._keyManagementParameters); + } + return enc.encrypt(key, options); + } + }; + + // dist/browser/jwk/thumbprint.js + var check = (value, description) => { + if (typeof value !== "string" || !value) { + throw new JWKInvalid(`${description} missing or invalid`); + } + }; + async function calculateJwkThumbprint(jwk, digestAlgorithm) { + if (!isObject(jwk)) { + throw new TypeError("JWK must be an object"); + } + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; + if (digestAlgorithm !== "sha256" && digestAlgorithm !== "sha384" && digestAlgorithm !== "sha512") { + throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); + } + let components; + switch (jwk.kty) { + case "EC": + check(jwk.crv, '"crv" (Curve) Parameter'); + check(jwk.x, '"x" (X Coordinate) Parameter'); + check(jwk.y, '"y" (Y Coordinate) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; + break; + case "OKP": + check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); + check(jwk.x, '"x" (Public Key) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; + break; + case "RSA": + check(jwk.e, '"e" (Exponent) Parameter'); + check(jwk.n, '"n" (Modulus) Parameter'); + components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; + break; + case "oct": + check(jwk.k, '"k" (Key Value) Parameter'); + components = { k: jwk.k, kty: jwk.kty }; + break; + default: + throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); + } + const data = encoder.encode(JSON.stringify(components)); + return encode(await digest_default(digestAlgorithm, data)); + } + async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : digestAlgorithm = "sha256"; + const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); + return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; + } + + // dist/browser/jwk/embedded.js + async function EmbeddedJWK(protectedHeader, token) { + const joseHeader = { + ...protectedHeader, + ...token.header + }; + if (!isObject(joseHeader.jwk)) { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); + } + const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); + if (key instanceof Uint8Array || key.type !== "public") { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); + } + return key; + } + + // dist/browser/jwks/local.js + function getKtyFromAlg(alg) { + switch (typeof alg === "string" && alg.slice(0, 2)) { + case "RS": + case "PS": + return "RSA"; + case "ES": + return "EC"; + case "Ed": + return "OKP"; + default: + throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); + } + } + function isJWKSLike(jwks) { + return jwks && typeof jwks === "object" && Array.isArray(jwks.keys) && jwks.keys.every(isJWKLike); + } + function isJWKLike(key) { + return isObject(key); + } + function clone(obj) { + if (typeof structuredClone === "function") { + return structuredClone(obj); + } + return JSON.parse(JSON.stringify(obj)); + } + var LocalJWKSet = class { + constructor(jwks) { + this._cached = /* @__PURE__ */ new WeakMap(); + if (!isJWKSLike(jwks)) { + throw new JWKSInvalid("JSON Web Key Set malformed"); + } + this._jwks = clone(jwks); + } + async getKey(protectedHeader, token) { + const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; + const kty = getKtyFromAlg(alg); + const candidates = this._jwks.keys.filter((jwk2) => { + let candidate = kty === jwk2.kty; + if (candidate && typeof kid === "string") { + candidate = kid === jwk2.kid; + } + if (candidate && typeof jwk2.alg === "string") { + candidate = alg === jwk2.alg; + } + if (candidate && typeof jwk2.use === "string") { + candidate = jwk2.use === "sig"; + } + if (candidate && Array.isArray(jwk2.key_ops)) { + candidate = jwk2.key_ops.includes("verify"); + } + if (candidate && alg === "EdDSA") { + candidate = jwk2.crv === "Ed25519" || jwk2.crv === "Ed448"; + } + if (candidate) { + switch (alg) { + case "ES256": + candidate = jwk2.crv === "P-256"; + break; + case "ES256K": + candidate = jwk2.crv === "secp256k1"; + break; + case "ES384": + candidate = jwk2.crv === "P-384"; + break; + case "ES512": + candidate = jwk2.crv === "P-521"; + break; + } + } + return candidate; + }); + const { 0: jwk, length } = candidates; + if (length === 0) { + throw new JWKSNoMatchingKey(); + } else if (length !== 1) { + const error = new JWKSMultipleMatchingKeys(); + const { _cached } = this; + error[Symbol.asyncIterator] = async function* () { + for (const jwk2 of candidates) { + try { + yield await importWithAlgCache(_cached, jwk2, alg); + } catch (_a) { + continue; + } + } + }; + throw error; + } + return importWithAlgCache(this._cached, jwk, alg); + } + }; + async function importWithAlgCache(cache, jwk, alg) { + const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); + if (cached[alg] === void 0) { + const keyObject = await importJWK({ ...jwk, ext: true }, alg); + if (keyObject.type !== "public") { + throw new JWKSInvalid("JSON Web Key Set members must be public keys"); + } + cached[alg] = keyObject; + } + return cached[alg]; + } + function createLocalJWKSet(jwks) { + return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); + } + + // dist/browser/runtime/fetch_jwks.js + var fetchJwks = async (url, timeout, options) => { + let controller; + let id; + let timedOut = false; + if (typeof AbortController === "function") { + controller = new AbortController(); + id = setTimeout(() => { + timedOut = true; + controller.abort(); + }, timeout); + } + const response = await fetch(url.href, { + signal: controller ? controller.signal : void 0, + redirect: "manual", + headers: options.headers + }).catch((err) => { + if (timedOut) + throw new JWKSTimeout(); + throw err; + }); + if (id !== void 0) + clearTimeout(id); + if (response.status !== 200) { + throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response"); + } + try { + return await response.json(); + } catch (_a) { + throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON"); + } + }; + var fetch_jwks_default = fetchJwks; + + // dist/browser/jwks/remote.js + var RemoteJWKSet = class extends LocalJWKSet { + constructor(url, options) { + super({ keys: [] }); + this._jwks = void 0; + if (!(url instanceof URL)) { + throw new TypeError("url must be an instance of URL"); + } + this._url = new URL(url.href); + this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; + this._timeoutDuration = typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === "number" ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5e3; + this._cooldownDuration = typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === "number" ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 3e4; + this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === "number" ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 6e5; + } + coolingDown() { + return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cooldownDuration : false; + } + fresh() { + return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cacheMaxAge : false; + } + async getKey(protectedHeader, token) { + if (!this._jwks || !this.fresh()) { + await this.reload(); + } + try { + return await super.getKey(protectedHeader, token); + } catch (err) { + if (err instanceof JWKSNoMatchingKey) { + if (this.coolingDown() === false) { + await this.reload(); + return super.getKey(protectedHeader, token); + } + } + throw err; + } + } + async reload() { + if (this._pendingFetch && isCloudflareWorkers()) { + return new Promise((resolve) => { + const isDone = () => { + if (this._pendingFetch === void 0) { + resolve(); + } else { + setTimeout(isDone, 5); + } + }; + isDone(); + }); + } + if (!this._pendingFetch) { + this._pendingFetch = fetch_jwks_default(this._url, this._timeoutDuration, this._options).then((json) => { + if (!isJWKSLike(json)) { + throw new JWKSInvalid("JSON Web Key Set malformed"); + } + this._jwks = { keys: json.keys }; + this._jwksTimestamp = Date.now(); + this._pendingFetch = void 0; + }).catch((err) => { + this._pendingFetch = void 0; + throw err; + }); + } + await this._pendingFetch; + } + }; + function createRemoteJWKSet(url, options) { + return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); + } + + // dist/browser/jwt/unsecured.js + var UnsecuredJWT = class extends ProduceJWT { + encode() { + const header = encode(JSON.stringify({ alg: "none" })); + const payload = encode(JSON.stringify(this._payload)); + return `${header}.${payload}.`; + } + static decode(jwt, options) { + if (typeof jwt !== "string") { + throw new JWTInvalid("Unsecured JWT must be a string"); + } + const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split("."); + if (length !== 3 || signature !== "") { + throw new JWTInvalid("Invalid Unsecured JWT"); + } + let header; + try { + header = JSON.parse(decoder.decode(decode(encodedHeader))); + if (header.alg !== "none") + throw new Error(); + } catch (_a) { + throw new JWTInvalid("Invalid Unsecured JWT"); + } + const payload = jwt_claims_set_default(header, decode(encodedPayload), options); + return { payload, header }; + } + }; + + // dist/browser/util/base64url.js + var base64url_exports2 = {}; + __export(base64url_exports2, { + decode: () => decode2, + encode: () => encode2 + }); + var encode2 = encode; + var decode2 = decode; + + // dist/browser/util/decode_protected_header.js + function decodeProtectedHeader(token) { + let protectedB64u; + if (typeof token === "string") { + const parts = token.split("."); + if (parts.length === 3 || parts.length === 5) { + [protectedB64u] = parts; + } + } else if (typeof token === "object" && token) { + if ("protected" in token) { + protectedB64u = token.protected; + } else { + throw new TypeError("Token does not contain a Protected Header"); + } + } + try { + if (typeof protectedB64u !== "string" || !protectedB64u) { + throw new Error(); + } + const result = JSON.parse(decoder.decode(decode2(protectedB64u))); + if (!isObject(result)) { + throw new Error(); + } + return result; + } catch (_a) { + throw new TypeError("Invalid Token or Protected Header formatting"); + } + } + + // dist/browser/util/decode_jwt.js + function decodeJwt(jwt) { + if (typeof jwt !== "string") + throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string"); + const { 1: payload, length } = jwt.split("."); + if (length === 5) + throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded"); + if (length !== 3) + throw new JWTInvalid("Invalid JWT"); + if (!payload) + throw new JWTInvalid("JWTs must contain a payload"); + let decoded; + try { + decoded = decode2(payload); + } catch (_a) { + throw new JWTInvalid("Failed to parse the base64url encoded payload"); + } + let result; + try { + result = JSON.parse(decoder.decode(decoded)); + } catch (_b) { + throw new JWTInvalid("Failed to parse the decoded payload as JSON"); + } + if (!isObject(result)) + throw new JWTInvalid("Invalid JWT Claims Set"); + return result; + } + + // dist/browser/runtime/generate.js + async function generateSecret(alg, options) { + var _a; + let length; + let algorithm; + let keyUsages; + switch (alg) { + case "HS256": + case "HS384": + case "HS512": + length = parseInt(alg.slice(-3), 10); + algorithm = { name: "HMAC", hash: `SHA-${length}`, length }; + keyUsages = ["sign", "verify"]; + break; + case "A128CBC-HS256": + case "A192CBC-HS384": + case "A256CBC-HS512": + length = parseInt(alg.slice(-3), 10); + return random_default(new Uint8Array(length >> 3)); + case "A128KW": + case "A192KW": + case "A256KW": + length = parseInt(alg.slice(1, 4), 10); + algorithm = { name: "AES-KW", length }; + keyUsages = ["wrapKey", "unwrapKey"]; + break; + case "A128GCMKW": + case "A192GCMKW": + case "A256GCMKW": + case "A128GCM": + case "A192GCM": + case "A256GCM": + length = parseInt(alg.slice(1, 4), 10); + algorithm = { name: "AES-GCM", length }; + keyUsages = ["encrypt", "decrypt"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + return webcrypto_default.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); + } + function getModulusLengthOption(options) { + var _a; + const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; + if (typeof modulusLength !== "number" || modulusLength < 2048) { + throw new JOSENotSupported("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used"); + } + return modulusLength; + } + async function generateKeyPair(alg, options) { + var _a, _b, _c, _d; + let algorithm; + let keyUsages; + switch (alg) { + case "PS256": + case "PS384": + case "PS512": + algorithm = { + name: "RSA-PSS", + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: getModulusLengthOption(options) + }; + keyUsages = ["sign", "verify"]; + break; + case "RS256": + case "RS384": + case "RS512": + algorithm = { + name: "RSASSA-PKCS1-v1_5", + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: getModulusLengthOption(options) + }; + keyUsages = ["sign", "verify"]; + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + algorithm = { + name: "RSA-OAEP", + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: getModulusLengthOption(options) + }; + keyUsages = ["decrypt", "unwrapKey", "encrypt", "wrapKey"]; + break; + case "ES256": + algorithm = { name: "ECDSA", namedCurve: "P-256" }; + keyUsages = ["sign", "verify"]; + break; + case "ES384": + algorithm = { name: "ECDSA", namedCurve: "P-384" }; + keyUsages = ["sign", "verify"]; + break; + case "ES512": + algorithm = { name: "ECDSA", namedCurve: "P-521" }; + keyUsages = ["sign", "verify"]; + break; + case "EdDSA": + keyUsages = ["sign", "verify"]; + const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : "Ed25519"; + switch (crv) { + case "Ed25519": + case "Ed448": + algorithm = { name: crv }; + break; + default: + throw new JOSENotSupported("Invalid or unsupported crv option provided"); + } + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": { + keyUsages = ["deriveKey", "deriveBits"]; + const crv2 = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : "P-256"; + switch (crv2) { + case "P-256": + case "P-384": + case "P-521": { + algorithm = { name: "ECDH", namedCurve: crv2 }; + break; + } + case "X25519": + case "X448": + algorithm = { name: crv2 }; + break; + default: + throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448"); + } + break; + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + try { + return await webcrypto_default.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages); + } catch (err) { + if (algorithm.name === "Ed25519" && (err === null || err === void 0 ? void 0 : err.name) === "NotSupportedError" && isCloudflareWorkers()) { + algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" }; + return await webcrypto_default.subtle.generateKey(algorithm, (_d = options === null || options === void 0 ? void 0 : options.extractable) !== null && _d !== void 0 ? _d : false, keyUsages); + } + throw err; + } + } + + // dist/browser/key/generate_key_pair.js + async function generateKeyPair2(alg, options) { + return generateKeyPair(alg, options); + } + + // dist/browser/key/generate_secret.js + async function generateSecret2(alg, options) { + return generateSecret(alg, options); + } + + exports.CompactEncrypt = CompactEncrypt; + exports.CompactSign = CompactSign; + exports.EmbeddedJWK = EmbeddedJWK; + exports.EncryptJWT = EncryptJWT; + exports.FlattenedEncrypt = FlattenedEncrypt; + exports.FlattenedSign = FlattenedSign; + exports.GeneralEncrypt = GeneralEncrypt; + exports.GeneralSign = GeneralSign; + exports.SignJWT = SignJWT; + exports.UnsecuredJWT = UnsecuredJWT; + exports.base64url = base64url_exports2; + exports.calculateJwkThumbprint = calculateJwkThumbprint; + exports.calculateJwkThumbprintUri = calculateJwkThumbprintUri; + exports.compactDecrypt = compactDecrypt; + exports.compactVerify = compactVerify; + exports.createLocalJWKSet = createLocalJWKSet; + exports.createRemoteJWKSet = createRemoteJWKSet; + exports.decodeJwt = decodeJwt; + exports.decodeProtectedHeader = decodeProtectedHeader; + exports.errors = errors_exports; + exports.exportJWK = exportJWK; + exports.exportPKCS8 = exportPKCS8; + exports.exportSPKI = exportSPKI; + exports.flattenedDecrypt = flattenedDecrypt; + exports.flattenedVerify = flattenedVerify; + exports.generalDecrypt = generalDecrypt; + exports.generalVerify = generalVerify; + exports.generateKeyPair = generateKeyPair2; + exports.generateSecret = generateSecret2; + exports.importJWK = importJWK; + exports.importPKCS8 = importPKCS8; + exports.importSPKI = importSPKI; + exports.importX509 = importX509; + exports.jwtDecrypt = jwtDecrypt; + exports.jwtVerify = jwtVerify; + +})); diff --git a/dist/browser/index.umd.min.js b/dist/browser/index.umd.min.js new file mode 100644 index 0000000000..cccfe2676d --- /dev/null +++ b/dist/browser/index.umd.min.js @@ -0,0 +1,5 @@ +(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports):typeof define==='function'&&define.amd?define(['exports'],f):(g=typeof globalThis!=='undefined'?globalThis:g||self,f(g.jose={}));})(this,(function(exports){'use strict';var qt=Object.defineProperty;var ct=(e,t)=>{for(var r in t)qt(e,r,{get:t[r],enumerable:!0});};var f=crypto,b=e=>e instanceof CryptoKey;var Zt=async(e,t)=>{let r=`SHA-${e.slice(-3)}`;return new Uint8Array(await f.subtle.digest(r,t))},Ke=Zt;var E=new TextEncoder,v=new TextDecoder,xe=2**32;function W(...e){let t=e.reduce((o,{length:a})=>o+a,0),r=new Uint8Array(t),n=0;return e.forEach(o=>{r.set(o,n),n+=o.length;}),r}function dt(e,t){return W(E.encode(e),new Uint8Array([0]),t)}function ke(e,t,r){if(t<0||t>=xe)throw new RangeError(`value must be >= 0 and <= ${xe-1}. Received ${t}`);e.set([t>>>24,t>>>16,t>>>8,t&255],r);}function He(e){let t=Math.floor(e/xe),r=e%xe,n=new Uint8Array(8);return ke(n,t,0),ke(n,r,4),n}function Ce(e){let t=new Uint8Array(4);return ke(t,e),t}function Pe(e){return W(Ce(e.length),e)}async function pt(e,t,r){let n=Math.ceil((t>>3)/32),o=new Uint8Array(n*32);for(let a=0;a>3)}var We=e=>{let t=e;typeof t=="string"&&(t=E.encode(t));let r=32768,n=[];for(let o=0;oWe(e).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_"),Be=e=>{let t=atob(e),r=new Uint8Array(t.length);for(let n=0;n{let t=e;t instanceof Uint8Array&&(t=v.decode(t)),t=t.replace(/-/g,"+").replace(/_/g,"/").replace(/\s/g,"");try{return Be(t)}catch(r){throw new TypeError("The input to be decoded is not correctly encoded.")}};var ft={};ct(ft,{JOSEAlgNotAllowed:()=>B,JOSEError:()=>C,JOSENotSupported:()=>l,JWEDecryptionFailed:()=>M,JWEInvalid:()=>u,JWKInvalid:()=>pe,JWKSInvalid:()=>L,JWKSMultipleMatchingKeys:()=>ue,JWKSNoMatchingKey:()=>q,JWKSTimeout:()=>fe,JWSInvalid:()=>h,JWSSignatureVerificationFailed:()=>Z,JWTClaimValidationFailed:()=>J,JWTExpired:()=>re,JWTInvalid:()=>H});var C=class extends Error{static get code(){return "ERR_JOSE_GENERIC"}constructor(t){var r;super(t),this.code="ERR_JOSE_GENERIC",this.name=this.constructor.name,(r=Error.captureStackTrace)===null||r===void 0||r.call(Error,this,this.constructor);}},J=class extends C{static get code(){return "ERR_JWT_CLAIM_VALIDATION_FAILED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_CLAIM_VALIDATION_FAILED",this.claim=r,this.reason=n;}},re=class extends C{static get code(){return "ERR_JWT_EXPIRED"}constructor(t,r="unspecified",n="unspecified"){super(t),this.code="ERR_JWT_EXPIRED",this.claim=r,this.reason=n;}},B=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_ALG_NOT_ALLOWED";}static get code(){return "ERR_JOSE_ALG_NOT_ALLOWED"}},l=class extends C{constructor(){super(...arguments),this.code="ERR_JOSE_NOT_SUPPORTED";}static get code(){return "ERR_JOSE_NOT_SUPPORTED"}},M=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_DECRYPTION_FAILED",this.message="decryption operation failed";}static get code(){return "ERR_JWE_DECRYPTION_FAILED"}},u=class extends C{constructor(){super(...arguments),this.code="ERR_JWE_INVALID";}static get code(){return "ERR_JWE_INVALID"}},h=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_INVALID";}static get code(){return "ERR_JWS_INVALID"}},H=class extends C{constructor(){super(...arguments),this.code="ERR_JWT_INVALID";}static get code(){return "ERR_JWT_INVALID"}},pe=class extends C{constructor(){super(...arguments),this.code="ERR_JWK_INVALID";}static get code(){return "ERR_JWK_INVALID"}},L=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_INVALID";}static get code(){return "ERR_JWKS_INVALID"}},q=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_NO_MATCHING_KEY",this.message="no applicable key found in the JSON Web Key Set";}static get code(){return "ERR_JWKS_NO_MATCHING_KEY"}},ue=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_MULTIPLE_MATCHING_KEYS",this.message="multiple matching keys found in the JSON Web Key Set";}static get code(){return "ERR_JWKS_MULTIPLE_MATCHING_KEYS"}},fe=class extends C{constructor(){super(...arguments),this.code="ERR_JWKS_TIMEOUT",this.message="request timed out";}static get code(){return "ERR_JWKS_TIMEOUT"}},Z=class extends C{constructor(){super(...arguments),this.code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED",this.message="signature verification failed";}static get code(){return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"}};var $=f.getRandomValues.bind(f);function Le(e){switch(e){case"A128GCM":case"A128GCMKW":case"A192GCM":case"A192GCMKW":case"A256GCM":case"A256GCMKW":return 96;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return 128;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var Je=e=>$(new Uint8Array(Le(e)>>3));var Qt=(e,t)=>{if(t.length<<3!==Le(e))throw new u("Invalid Initialization Vector length")},Te=Qt;var jt=(e,t)=>{let r=e.byteLength<<3;if(r!==t)throw new u(`Invalid Content Encryption Key length. Expected ${t} bits, got ${r} bits`)},ne=jt;var er=(e,t)=>{if(!(e instanceof Uint8Array))throw new TypeError("First argument must be a buffer");if(!(t instanceof Uint8Array))throw new TypeError("Second argument must be a buffer");if(e.length!==t.length)throw new TypeError("Input buffers must have the same length");let r=e.length,n=0,o=-1;for(;++oe.usages.includes(r))){let r="CryptoKey does not support this operation, its usages must include ";if(t.length>2){let n=t.pop();r+=`one of ${t.join(", ")}, or ${n}.`;}else t.length===2?r+=`one of ${t[0]} or ${t[1]}.`:r+=`${t[0]}.`;throw new TypeError(r)}}function ht(e,t,...r){switch(t){case"HS256":case"HS384":case"HS512":{if(!N(e.algorithm,"HMAC"))throw P("HMAC");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"RS256":case"RS384":case"RS512":{if(!N(e.algorithm,"RSASSA-PKCS1-v1_5"))throw P("RSASSA-PKCS1-v1_5");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"PS256":case"PS384":case"PS512":{if(!N(e.algorithm,"RSA-PSS"))throw P("RSA-PSS");let n=parseInt(t.slice(2),10);if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}case"EdDSA":{if(e.algorithm.name!=="Ed25519"&&e.algorithm.name!=="Ed448"){if(D()){if(N(e.algorithm,"NODE-ED25519"))break;throw P("Ed25519, Ed448, or NODE-ED25519")}throw P("Ed25519 or Ed448")}break}case"ES256":case"ES384":case"ES512":{if(!N(e.algorithm,"ECDSA"))throw P("ECDSA");let n=tr(t);if(e.algorithm.namedCurve!==n)throw P(n,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r);}function I(e,t,...r){switch(t){case"A128GCM":case"A192GCM":case"A256GCM":{if(!N(e.algorithm,"AES-GCM"))throw P("AES-GCM");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"A128KW":case"A192KW":case"A256KW":{if(!N(e.algorithm,"AES-KW"))throw P("AES-KW");let n=parseInt(t.slice(1,4),10);if(e.algorithm.length!==n)throw P(n,"algorithm.length");break}case"ECDH":{switch(e.algorithm.name){case"ECDH":case"X25519":case"X448":break;default:throw P("ECDH, X25519, or X448")}break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":if(!N(e.algorithm,"PBKDF2"))throw P("PBKDF2");break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(!N(e.algorithm,"RSA-OAEP"))throw P("RSA-OAEP");let n=parseInt(t.slice(9),10)||1;if(Ie(e.algorithm.hash)!==n)throw P(`SHA-${n}`,"algorithm.hash");break}default:throw new TypeError("CryptoKey does not support this operation")}mt(e,r);}function yt(e,t,...r){if(r.length>2){let n=r.pop();e+=`one of type ${r.join(", ")}, or ${n}.`;}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t=="function"&&t.name?e+=` Received function ${t.name}`:typeof t=="object"&&t!=null&&t.constructor&&t.constructor.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var A=(e,...t)=>yt("Key must be ",e,...t);function $e(e,t,...r){return yt(`Key for the ${e} algorithm must be `,t,...r)}var Ge=e=>b(e),y=["CryptoKey"];async function rr(e,t,r,n,o,a){if(!(t instanceof Uint8Array))throw new TypeError(A(t,"Uint8Array"));let i=parseInt(e.slice(1,4),10),s=await f.subtle.importKey("raw",t.subarray(i>>3),"AES-CBC",!1,["decrypt"]),c=await f.subtle.importKey("raw",t.subarray(0,i>>3),{hash:`SHA-${i<<1}`,name:"HMAC"},!1,["sign"]),d=W(a,n,r,He(a.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",c,d)).slice(0,i>>3)),m;try{m=lt(o,p);}catch(T){}if(!m)throw new M;let K;try{K=new Uint8Array(await f.subtle.decrypt({iv:n,name:"AES-CBC"},s,r));}catch(T){}if(!K)throw new M;return K}async function nr(e,t,r,n,o,a){let i;t instanceof Uint8Array?i=await f.subtle.importKey("raw",t,"AES-GCM",!1,["decrypt"]):(I(t,e,"decrypt"),i=t);try{return new Uint8Array(await f.subtle.decrypt({additionalData:a,iv:n,name:"AES-GCM",tagLength:128},i,W(r,o)))}catch(s){throw new M}}var or=async(e,t,r,n,o,a)=>{if(!b(t)&&!(t instanceof Uint8Array))throw new TypeError(A(t,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(-3),10)),rr(e,t,r,n,o,a);case"A128GCM":case"A192GCM":case"A256GCM":return t instanceof Uint8Array&&ne(t,parseInt(e.slice(1,4),10)),nr(e,t,r,n,o,a);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},De=or;var wt=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.')},Et=async()=>{throw new l('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.')};var ar=(...e)=>{let t=e.filter(Boolean);if(t.length===0||t.length===1)return !0;let r;for(let n of t){let o=Object.keys(n);if(!r||r.size===0){r=new Set(o);continue}for(let a of o){if(r.has(a))return !1;r.add(a);}}return !0},R=ar;function ir(e){return typeof e=="object"&&e!==null}function w(e){if(!ir(e)||Object.prototype.toString.call(e)!=="[object Object]")return !1;if(Object.getPrototypeOf(e)===null)return !0;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}var sr=[{hash:"SHA-256",name:"HMAC"},!0,["sign"]],oe=sr;function gt(e,t){if(e.algorithm.length!==parseInt(t.slice(1,4),10))throw new TypeError(`Invalid key size for alg: ${t}`)}function St(e,t,r){if(b(e))return I(e,t,r),e;if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"AES-KW",!0,[r]);throw new TypeError(A(e,...y,"Uint8Array"))}var le=async(e,t,r)=>{let n=await St(t,e,"wrapKey");gt(n,e);let o=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",o,n,"AES-KW"))},me=async(e,t,r)=>{let n=await St(t,e,"unwrapKey");gt(n,e);let o=await f.subtle.unwrapKey("raw",r,n,"AES-KW",...oe);return new Uint8Array(await f.subtle.exportKey("raw",o))};async function Re(e,t,r,n,o=new Uint8Array(0),a=new Uint8Array(0)){if(!b(e))throw new TypeError(A(e,...y));if(I(e,"ECDH"),!b(t))throw new TypeError(A(t,...y));I(t,"ECDH","deriveBits");let i=W(Pe(E.encode(r)),Pe(o),Pe(a),Ce(n)),s;e.algorithm.name==="X25519"?s=256:e.algorithm.name==="X448"?s=448:s=Math.ceil(parseInt(e.algorithm.namedCurve.substr(-3),10)/8)<<3;let c=new Uint8Array(await f.subtle.deriveBits({name:e.algorithm.name,public:e},t,s));return pt(c,n,i)}async function At(e){if(!b(e))throw new TypeError(A(e,...y));return f.subtle.generateKey(e.algorithm,!0,["deriveBits"])}function Oe(e){if(!b(e))throw new TypeError(A(e,...y));return ["P-256","P-384","P-521"].includes(e.algorithm.namedCurve)||e.algorithm.name==="X25519"||e.algorithm.name==="X448"}function Ve(e){if(!(e instanceof Uint8Array)||e.length<8)throw new u("PBES2 Salt Input must be 8 or more octets")}function cr(e,t){if(e instanceof Uint8Array)return f.subtle.importKey("raw",e,"PBKDF2",!1,["deriveBits"]);if(b(e))return I(e,t,"deriveBits","deriveKey"),e;throw new TypeError(A(e,...y,"Uint8Array"))}async function _t(e,t,r,n){Ve(e);let o=dt(t,e),a=parseInt(t.slice(13,16),10),i={hash:`SHA-${t.slice(8,11)}`,iterations:r,name:"PBKDF2",salt:o},s={length:a,name:"AES-KW"},c=await cr(n,t);if(c.usages.includes("deriveBits"))return new Uint8Array(await f.subtle.deriveBits(i,c,a));if(c.usages.includes("deriveKey"))return f.subtle.deriveKey(i,c,s,!1,["wrapKey","unwrapKey"]);throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"')}var vt=async(e,t,r,n=2048,o=$(new Uint8Array(16)))=>{let a=await _t(o,e,n,t);return {encryptedKey:await le(e.slice(-6),a,r),p2c:n,p2s:g(o)}},Kt=async(e,t,r,n,o)=>{let a=await _t(o,e,n,t);return me(e.slice(-6),a,r)};function ae(e){switch(e){case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":return "RSA-OAEP";default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}var Q=(e,t)=>{if(e.startsWith("RS")||e.startsWith("PS")){let{modulusLength:r}=t.algorithm;if(typeof r!="number"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}};var xt=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"encrypt","wrapKey"),Q(e,t),t.usages.includes("encrypt"))return new Uint8Array(await f.subtle.encrypt(ae(e),t,r));if(t.usages.includes("wrapKey")){let n=await f.subtle.importKey("raw",r,...oe);return new Uint8Array(await f.subtle.wrapKey("raw",n,t,ae(e)))}throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation')},Ht=async(e,t,r)=>{if(!b(t))throw new TypeError(A(t,...y));if(I(t,e,"decrypt","unwrapKey"),Q(e,t),t.usages.includes("decrypt"))return new Uint8Array(await f.subtle.decrypt(ae(e),t,r));if(t.usages.includes("unwrapKey")){let n=await f.subtle.unwrapKey("raw",r,t,ae(e),...oe);return new Uint8Array(await f.subtle.exportKey("raw",n))}throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation')};function he(e){switch(e){case"A128GCM":return 128;case"A192GCM":return 192;case"A256GCM":case"A128CBC-HS256":return 256;case"A192CBC-HS384":return 384;case"A256CBC-HS512":return 512;default:throw new l(`Unsupported JWE Algorithm: ${e}`)}}var O=e=>$(new Uint8Array(he(e)>>3));var Fe=(e,t)=>{let r=(e.match(/.{1,64}/g)||[]).join(` +`);return `-----BEGIN ${t}----- +${r} +-----END ${t}-----`};var Wt=async(e,t,r)=>{if(!b(r))throw new TypeError(A(r,...y));if(!r.extractable)throw new TypeError("CryptoKey is not extractable");if(r.type!==e)throw new TypeError(`key is not a ${e} key`);return Fe(We(new Uint8Array(await f.subtle.exportKey(t,r))),`${e.toUpperCase()} KEY`)},Jt=e=>Wt("public","spki",e),Tt=e=>Wt("private","pkcs8",e),G=(e,t,r=0)=>{r===0&&(t.unshift(t.length),t.unshift(6));let n=e.indexOf(t[0],r);if(n===-1)return !1;let o=e.subarray(n,n+t.length);return o.length!==t.length?!1:o.every((a,i)=>a===t[i])||G(e,t,n+1)},Ct=e=>{switch(!0){case G(e,[42,134,72,206,61,3,1,7]):return "P-256";case G(e,[43,129,4,0,34]):return "P-384";case G(e,[43,129,4,0,35]):return "P-521";case G(e,[43,101,110]):return "X25519";case G(e,[43,101,111]):return "X448";case G(e,[43,101,112]):return "Ed25519";case G(e,[43,101,113]):return "Ed448";default:throw new l("Invalid or unsupported EC Key Curve or OKP Key Sub Type")}},It=async(e,t,r,n,o)=>{var a,i;let s,c,d=new Uint8Array(atob(r.replace(e,"")).split("").map(m=>m.charCodeAt(0))),p=t==="spki";switch(n){case"PS256":case"PS384":case"PS512":s={name:"RSA-PSS",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RS256":case"RS384":case"RS512":s={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${n.slice(-3)}`},c=p?["verify"]:["sign"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":s={name:"RSA-OAEP",hash:`SHA-${parseInt(n.slice(-3),10)||1}`},c=p?["encrypt","wrapKey"]:["decrypt","unwrapKey"];break;case"ES256":s={name:"ECDSA",namedCurve:"P-256"},c=p?["verify"]:["sign"];break;case"ES384":s={name:"ECDSA",namedCurve:"P-384"},c=p?["verify"]:["sign"];break;case"ES512":s={name:"ECDSA",namedCurve:"P-521"},c=p?["verify"]:["sign"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{let m=Ct(d);s=m.startsWith("P-")?{name:"ECDH",namedCurve:m}:{name:m},c=p?[]:["deriveBits"];break}case"EdDSA":s={name:Ct(d)},c=p?["verify"]:["sign"];break;default:throw new l('Invalid or unsupported "alg" (Algorithm) value')}try{return await f.subtle.importKey(t,d,s,(a=o==null?void 0:o.extractable)!==null&&a!==void 0?a:!1,c)}catch(m){if(s.name==="Ed25519"&&(m==null?void 0:m.name)==="NotSupportedError"&&D())return s={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey(t,d,s,(i=o==null?void 0:o.extractable)!==null&&i!==void 0?i:!1,c);throw m}},Dt=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g,"pkcs8",e,t,r),ze=(e,t,r)=>It(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g,"spki",e,t,r);function Pt(e){let t=[],r=0;for(;r=128;)r=r*128+e[t]-128,t++;r=r*128+e[t]-128,t++;}let n=0;if(e[t]<128)n=e[t],t++;else if(n===128){for(n=0;e[t+n]!==0||e[t+n+1]!==0;){if(n>e.byteLength)throw new TypeError("invalid indefinite form length");n++;}let a=t+n+2;return {byteLength:a,contents:e.subarray(t,t+n),raw:e.subarray(0,a)}}else {let a=e[t]&127;t++,n=0;for(let i=0;i{let n;try{n=pr(e);}catch(o){throw new TypeError("failed to parse the X.509 certificate",{cause:o})}return ze(n,t,r)};function ur(e){let t,r;switch(e.kty){case"oct":{switch(e.alg){case"HS256":case"HS384":case"HS512":t={name:"HMAC",hash:`SHA-${e.alg.slice(-3)}`},r=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":throw new l(`${e.alg} keys cannot be imported as CryptoKey instances`);case"A128GCM":case"A192GCM":case"A256GCM":case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":t={name:"AES-GCM"},r=["encrypt","decrypt"];break;case"A128KW":case"A192KW":case"A256KW":t={name:"AES-KW"},r=["wrapKey","unwrapKey"];break;case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":t={name:"PBKDF2"},r=["deriveBits"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"RSA":{switch(e.alg){case"PS256":case"PS384":case"PS512":t={name:"RSA-PSS",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":t={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":t={name:"RSA-OAEP",hash:`SHA-${parseInt(e.alg.slice(-3),10)||1}`},r=e.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"EC":{switch(e.alg){case"ES256":t={name:"ECDSA",namedCurve:"P-256"},r=e.d?["sign"]:["verify"];break;case"ES384":t={name:"ECDSA",namedCurve:"P-384"},r=e.d?["sign"]:["verify"];break;case"ES512":t={name:"ECDSA",namedCurve:"P-521"},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:"ECDH",namedCurve:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"OKP":{switch(e.alg){case"EdDSA":t={name:e.crv},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}default:throw new l('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return {algorithm:t,keyUsages:r}}var fr=async e=>{var t,r;if(!e.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');let{algorithm:n,keyUsages:o}=ur(e),a=[n,(t=e.ext)!==null&&t!==void 0?t:!1,(r=e.key_ops)!==null&&r!==void 0?r:o];if(n.name==="PBKDF2")return f.subtle.importKey("raw",S(e.k),...a);let i={...e};delete i.alg,delete i.use;try{return await f.subtle.importKey("jwk",i,...a)}catch(s){if(n.name==="Ed25519"&&(s==null?void 0:s.name)==="NotSupportedError"&&D())return a[0]={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.importKey("jwk",i,...a);throw s}},Xe=fr;async function lr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PUBLIC KEY-----")!==0)throw new TypeError('"spki" must be SPKI formatted string');return ze(e,t,r)}async function mr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN CERTIFICATE-----")!==0)throw new TypeError('"x509" must be X.509 formatted string');return Ot(e,t,r)}async function hr(e,t,r){if(typeof e!="string"||e.indexOf("-----BEGIN PRIVATE KEY-----")!==0)throw new TypeError('"pkcs8" must be PKCS#8 formatted string');return Dt(e,t,r)}async function j(e,t,r){var n;if(!w(e))throw new TypeError("JWK must be an object");switch(t||(t=e.alg),e.kty){case"oct":if(typeof e.k!="string"||!e.k)throw new TypeError('missing "k" (Key Value) Parameter value');return r!=null||(r=e.ext!==!0),r?Xe({...e,alg:t,ext:(n=e.ext)!==null&&n!==void 0?n:!1}):S(e.k);case"RSA":if(e.oth!==void 0)throw new l('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');case"EC":case"OKP":return Xe({...e,alg:t});default:throw new l('Unsupported "kty" (Key Type) Parameter value')}}var yr=(e,t)=>{if(!(t instanceof Uint8Array)){if(!Ge(t))throw new TypeError($e(e,t,...y,"Uint8Array"));if(t.type!=="secret")throw new TypeError(`${y.join(" or ")} instances for symmetric algorithms must be of type "secret"`)}},wr=(e,t,r)=>{if(!Ge(t))throw new TypeError($e(e,t,...y));if(t.type==="secret")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`);if(r==="sign"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`);if(r==="decrypt"&&t.type==="public")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`);if(t.algorithm&&r==="verify"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`);if(t.algorithm&&r==="encrypt"&&t.type==="private")throw new TypeError(`${y.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`)},Er=(e,t,r)=>{e.startsWith("HS")||e==="dir"||e.startsWith("PBES2")||/^A\d{3}(?:GCM)?KW$/.test(e)?yr(e,t):wr(e,t,r);},V=Er;async function gr(e,t,r,n,o){if(!(r instanceof Uint8Array))throw new TypeError(A(r,"Uint8Array"));let a=parseInt(e.slice(1,4),10),i=await f.subtle.importKey("raw",r.subarray(a>>3),"AES-CBC",!1,["encrypt"]),s=await f.subtle.importKey("raw",r.subarray(0,a>>3),{hash:`SHA-${a<<1}`,name:"HMAC"},!1,["sign"]),c=new Uint8Array(await f.subtle.encrypt({iv:n,name:"AES-CBC"},i,t)),d=W(o,n,c,He(o.length<<3)),p=new Uint8Array((await f.subtle.sign("HMAC",s,d)).slice(0,a>>3));return {ciphertext:c,tag:p}}async function Sr(e,t,r,n,o){let a;r instanceof Uint8Array?a=await f.subtle.importKey("raw",r,"AES-GCM",!1,["encrypt"]):(I(r,e,"encrypt"),a=r);let i=new Uint8Array(await f.subtle.encrypt({additionalData:o,iv:n,name:"AES-GCM",tagLength:128},a,t)),s=i.slice(-16);return {ciphertext:i.slice(0,-16),tag:s}}var Ar=async(e,t,r,n,o)=>{if(!b(r)&&!(r instanceof Uint8Array))throw new TypeError(A(r,...y,"Uint8Array"));switch(Te(e,n),e){case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(-3),10)),gr(e,t,r,n,o);case"A128GCM":case"A192GCM":case"A256GCM":return r instanceof Uint8Array&&ne(r,parseInt(e.slice(1,4),10)),Sr(e,t,r,n,o);default:throw new l("Unsupported JWE Content Encryption Algorithm")}},ye=Ar;async function Ut(e,t,r,n){let o=e.slice(0,7);n||(n=Je(o));let{ciphertext:a,tag:i}=await ye(o,r,t,n,new Uint8Array(0));return {encryptedKey:a,iv:g(n),tag:g(i)}}async function Mt(e,t,r,n,o){let a=e.slice(0,7);return De(a,t,r,n,o,new Uint8Array(0))}async function br(e,t,r,n,o){switch(V(e,t,"decrypt"),e){case"dir":{if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");return t}case"ECDH-ES":if(r!==void 0)throw new u("Encountered unexpected JWE Encrypted Key");case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!w(n.epk))throw new u('JOSE Header "epk" (Ephemeral Public Key) missing or invalid');if(!Oe(t))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let a=await j(n.epk,e),i,s;if(n.apu!==void 0){if(typeof n.apu!="string")throw new u('JOSE Header "apu" (Agreement PartyUInfo) invalid');i=S(n.apu);}if(n.apv!==void 0){if(typeof n.apv!="string")throw new u('JOSE Header "apv" (Agreement PartyVInfo) invalid');s=S(n.apv);}let c=await Re(a,t,e==="ECDH-ES"?n.enc:e,e==="ECDH-ES"?he(n.enc):parseInt(e.slice(-5,-2),10),i,s);if(e==="ECDH-ES")return c;if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e.slice(-6),c,r)}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{if(r===void 0)throw new u("JWE Encrypted Key missing");return Ht(e,t,r)}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.p2c!="number")throw new u('JOSE Header "p2c" (PBES2 Count) missing or invalid');let a=(o==null?void 0:o.maxPBES2Count)||1e4;if(n.p2c>a)throw new u('JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds');if(typeof n.p2s!="string")throw new u('JOSE Header "p2s" (PBES2 Salt) missing or invalid');return Kt(e,t,r,n.p2c,S(n.p2s))}case"A128KW":case"A192KW":case"A256KW":{if(r===void 0)throw new u("JWE Encrypted Key missing");return me(e,t,r)}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{if(r===void 0)throw new u("JWE Encrypted Key missing");if(typeof n.iv!="string")throw new u('JOSE Header "iv" (Initialization Vector) missing or invalid');if(typeof n.tag!="string")throw new u('JOSE Header "tag" (Authentication Tag) missing or invalid');let a=S(n.iv),i=S(n.tag);return Mt(e,t,r,a,i)}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}}var Nt=br;function _r(e,t,r,n,o){if(o.crit!==void 0&&n.crit===void 0)throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');if(!n||n.crit===void 0)return new Set;if(!Array.isArray(n.crit)||n.crit.length===0||n.crit.some(i=>typeof i!="string"||i.length===0))throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let a;r!==void 0?a=new Map([...Object.entries(r),...t.entries()]):a=t;for(let i of n.crit){if(!a.has(i))throw new l(`Extension Header Parameter "${i}" is not recognized`);if(o[i]===void 0)throw new e(`Extension Header Parameter "${i}" is missing`);if(a.get(i)&&n[i]===void 0)throw new e(`Extension Header Parameter "${i}" MUST be integrity protected`)}return new Set(n.crit)}var U=_r;var vr=(e,t)=>{if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!="string")))throw new TypeError(`"${e}" option must be an array of strings`);if(t)return new Set(t)},we=vr;async function Ee(e,t,r){var n;if(!w(e))throw new u("Flattened JWE must be an object");if(e.protected===void 0&&e.header===void 0&&e.unprotected===void 0)throw new u("JOSE Header missing");if(typeof e.iv!="string")throw new u("JWE Initialization Vector missing or incorrect type");if(typeof e.ciphertext!="string")throw new u("JWE Ciphertext missing or incorrect type");if(typeof e.tag!="string")throw new u("JWE Authentication Tag missing or incorrect type");if(e.protected!==void 0&&typeof e.protected!="string")throw new u("JWE Protected Header incorrect type");if(e.encrypted_key!==void 0&&typeof e.encrypted_key!="string")throw new u("JWE Encrypted Key incorrect type");if(e.aad!==void 0&&typeof e.aad!="string")throw new u("JWE AAD incorrect type");if(e.header!==void 0&&!w(e.header))throw new u("JWE Shared Unprotected Header incorrect type");if(e.unprotected!==void 0&&!w(e.unprotected))throw new u("JWE Per-Recipient Unprotected Header incorrect type");let o;if(e.protected)try{let Y=S(e.protected);o=JSON.parse(v.decode(Y));}catch(Y){throw new u("JWE Protected Header is invalid")}if(!R(o,e.header,e.unprotected))throw new u("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint");let a={...o,...e.header,...e.unprotected};if(U(u,new Map,r==null?void 0:r.crit,o,a),a.zip!==void 0){if(!o||!o.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(a.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:i,enc:s}=a;if(typeof i!="string"||!i)throw new u("missing JWE Algorithm (alg) in JWE Header");if(typeof s!="string"||!s)throw new u("missing JWE Encryption Algorithm (enc) in JWE Header");let c=r&&we("keyManagementAlgorithms",r.keyManagementAlgorithms),d=r&&we("contentEncryptionAlgorithms",r.contentEncryptionAlgorithms);if(c&&!c.has(i))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(d&&!d.has(s))throw new B('"enc" (Encryption Algorithm) Header Parameter not allowed');let p;e.encrypted_key!==void 0&&(p=S(e.encrypted_key));let m=!1;typeof t=="function"&&(t=await t(o,e),m=!0);let K;try{K=await Nt(i,t,p,a,r);}catch(Y){if(Y instanceof TypeError||Y instanceof u||Y instanceof l)throw Y;K=O(s);}let T=S(e.iv),x=S(e.tag),_=E.encode((n=e.protected)!==null&&n!==void 0?n:""),k;e.aad!==void 0?k=W(_,E.encode("."),E.encode(e.aad)):k=_;let Ne=await De(s,K,S(e.ciphertext),T,x,k);a.zip==="DEF"&&(Ne=await((r==null?void 0:r.inflateRaw)||wt)(Ne));let te={plaintext:Ne};return e.protected!==void 0&&(te.protectedHeader=o),e.aad!==void 0&&(te.additionalAuthenticatedData=S(e.aad)),e.unprotected!==void 0&&(te.sharedUnprotectedHeader=e.unprotected),e.header!==void 0&&(te.unprotectedHeader=e.header),m?{...te,key:t}:te}async function Ye(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new u("Compact JWE must be a string or Uint8Array");let{0:n,1:o,2:a,3:i,4:s,length:c}=e.split(".");if(c!==5)throw new u("Invalid Compact JWE");let d=await Ee({ciphertext:i,iv:a||void 0,protected:n||void 0,tag:s||void 0,encrypted_key:o||void 0},t,r),p={plaintext:d.plaintext,protectedHeader:d.protectedHeader};return typeof t=="function"?{...p,key:d.key}:p}async function Kr(e,t,r){if(!w(e))throw new u("General JWE must be an object");if(!Array.isArray(e.recipients)||!e.recipients.every(w))throw new u("JWE Recipients missing or incorrect type");if(!e.recipients.length)throw new u("JWE Recipients has no members");for(let n of e.recipients)try{return await Ee({aad:e.aad,ciphertext:e.ciphertext,encrypted_key:n.encrypted_key,header:n.header,iv:e.iv,protected:e.protected,tag:e.tag,unprotected:e.unprotected},t,r)}catch(o){}throw new M}var xr=async e=>{if(e instanceof Uint8Array)return {kty:"oct",k:g(e)};if(!b(e))throw new TypeError(A(e,...y,"Uint8Array"));if(!e.extractable)throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");let{ext:t,key_ops:r,alg:n,use:o,...a}=await f.subtle.exportKey("jwk",e);return a},kt=xr;async function Hr(e){return Jt(e)}async function Cr(e){return Tt(e)}async function qe(e){return kt(e)}async function Pr(e,t,r,n,o={}){let a,i,s;switch(V(e,r,"encrypt"),e){case"dir":{s=r;break}case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{if(!Oe(r))throw new l("ECDH with the provided key is not allowed or not supported by your javascript runtime");let{apu:c,apv:d}=o,{epk:p}=o;p||(p=(await At(r)).privateKey);let{x:m,y:K,crv:T,kty:x}=await qe(p),_=await Re(r,p,e==="ECDH-ES"?t:e,e==="ECDH-ES"?he(t):parseInt(e.slice(-5,-2),10),c,d);if(i={epk:{x:m,crv:T,kty:x}},x==="EC"&&(i.epk.y=K),c&&(i.apu=g(c)),d&&(i.apv=g(d)),e==="ECDH-ES"){s=_;break}s=n||O(t);let k=e.slice(-6);a=await le(k,_,s);break}case"RSA1_5":case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":{s=n||O(t),a=await xt(e,r,s);break}case"PBES2-HS256+A128KW":case"PBES2-HS384+A192KW":case"PBES2-HS512+A256KW":{s=n||O(t);let{p2c:c,p2s:d}=o;({encryptedKey:a,...i}=await vt(e,r,s,c,d));break}case"A128KW":case"A192KW":case"A256KW":{s=n||O(t),a=await le(e,r,s);break}case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":{s=n||O(t);let{iv:c}=o;({encryptedKey:a,...i}=await Ut(e,r,s,c));break}default:throw new l('Invalid or unsupported "alg" (JWE Algorithm) header value')}return {cek:s,encryptedKey:a,parameters:i}}var Ue=Pr;var Ze=Symbol(),F=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("plaintext must be an instance of Uint8Array");this._plaintext=t;}setKeyManagementParameters(t){if(this._keyManagementParameters)throw new TypeError("setKeyManagementParameters can only be called once");return this._keyManagementParameters=t,this}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._sharedUnprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._sharedUnprotectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}setContentEncryptionKey(t){if(this._cek)throw new TypeError("setContentEncryptionKey can only be called once");return this._cek=t,this}setInitializationVector(t){if(this._iv)throw new TypeError("setInitializationVector can only be called once");return this._iv=t,this}async encrypt(t,r){if(!this._protectedHeader&&!this._unprotectedHeader&&!this._sharedUnprotectedHeader)throw new u("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()");if(!R(this._protectedHeader,this._unprotectedHeader,this._sharedUnprotectedHeader))throw new u("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader,...this._sharedUnprotectedHeader};if(U(u,new Map,r==null?void 0:r.crit,this._protectedHeader,n),n.zip!==void 0){if(!this._protectedHeader||!this._protectedHeader.zip)throw new u('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');if(n.zip!=="DEF")throw new l('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value')}let{alg:o,enc:a}=n;if(typeof o!="string"||!o)throw new u('JWE "alg" (Algorithm) Header Parameter missing or invalid');if(typeof a!="string"||!a)throw new u('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');let i;if(o==="dir"){if(this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption")}else if(o==="ECDH-ES"&&this._cek)throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement");let s;{let x;(({cek:s,encryptedKey:i,parameters:x}=await Ue(o,a,t,this._cek,this._keyManagementParameters))),x&&(r&&Ze in r?this._unprotectedHeader?this._unprotectedHeader={...this._unprotectedHeader,...x}:this.setUnprotectedHeader(x):this._protectedHeader?this._protectedHeader={...this._protectedHeader,...x}:this.setProtectedHeader(x));}this._iv||(this._iv=Je(a));let c,d,p;this._protectedHeader?d=E.encode(g(JSON.stringify(this._protectedHeader))):d=E.encode(""),this._aad?(p=g(this._aad),c=W(d,E.encode("."),E.encode(p))):c=d;let m,K;if(n.zip==="DEF"){let x=await((r==null?void 0:r.deflateRaw)||Et)(this._plaintext);({ciphertext:m,tag:K}=await ye(a,x,s,this._iv,c));}else ({ciphertext:m,tag:K}=await ye(a,this._plaintext,s,this._iv,c));let T={ciphertext:g(m),iv:g(this._iv),tag:g(K)};return i&&(T.encrypted_key=g(i)),p&&(T.aad=p),this._protectedHeader&&(T.protected=v.decode(d)),this._sharedUnprotectedHeader&&(T.unprotected=this._sharedUnprotectedHeader),this._unprotectedHeader&&(T.header=this._unprotectedHeader),T}};var Qe=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n;}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addRecipient(...t){return this.parent.addRecipient(...t)}encrypt(...t){return this.parent.encrypt(...t)}done(){return this.parent}},je=class{constructor(t){this._recipients=[],this._plaintext=t;}addRecipient(t,r){let n=new Qe(this,t,{crit:r==null?void 0:r.crit});return this._recipients.push(n),n}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setSharedUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setSharedUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}setAdditionalAuthenticatedData(t){return this._aad=t,this}async encrypt(t){var r,n,o;if(!this._recipients.length)throw new u("at least one recipient must be added");if(t={deflateRaw:t==null?void 0:t.deflateRaw},this._recipients.length===1){let[c]=this._recipients,d=await new F(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(c.unprotectedHeader).encrypt(c.key,{...c.options,...t}),p={ciphertext:d.ciphertext,iv:d.iv,recipients:[{}],tag:d.tag};return d.aad&&(p.aad=d.aad),d.protected&&(p.protected=d.protected),d.unprotected&&(p.unprotected=d.unprotected),d.encrypted_key&&(p.recipients[0].encrypted_key=d.encrypted_key),d.header&&(p.recipients[0].header=d.header),p}let a;for(let c=0;c>3};case"RS256":case"RS384":case"RS512":return {hash:r,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return {hash:r,name:"ECDSA",namedCurve:t.namedCurve};case"EdDSA":return D()&&t.name==="NODE-ED25519"?{name:"NODE-ED25519",namedCurve:"NODE-ED25519"}:{name:t.name};default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}function Se(e,t,r){if(b(t))return ht(t,e,r),t;if(t instanceof Uint8Array){if(!e.startsWith("HS"))throw new TypeError(A(t,...y));return f.subtle.importKey("raw",t,{hash:`SHA-${e.slice(-3)}`,name:"HMAC"},!1,[r])}throw new TypeError(A(t,...y,"Uint8Array"))}var Wr=async(e,t,r,n)=>{let o=await Se(e,t,"verify");Q(e,o);let a=ge(e,o.algorithm);try{return await f.subtle.verify(a,o,r,n)}catch(i){return !1}},Bt=Wr;async function Ae(e,t,r){var n;if(!w(e))throw new h("Flattened JWS must be an object");if(e.protected===void 0&&e.header===void 0)throw new h('Flattened JWS must have either of the "protected" or "header" members');if(e.protected!==void 0&&typeof e.protected!="string")throw new h("JWS Protected Header incorrect type");if(e.payload===void 0)throw new h("JWS Payload missing");if(typeof e.signature!="string")throw new h("JWS Signature missing or incorrect type");if(e.header!==void 0&&!w(e.header))throw new h("JWS Unprotected Header incorrect type");let o={};if(e.protected)try{let k=S(e.protected);o=JSON.parse(v.decode(k));}catch(k){throw new h("JWS Protected Header is invalid")}if(!R(o,e.header))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let a={...o,...e.header},i=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,o,a),s=!0;if(i.has("b64")&&(s=o.b64,typeof s!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:c}=a;if(typeof c!="string"||!c)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');let d=r&&we("algorithms",r.algorithms);if(d&&!d.has(c))throw new B('"alg" (Algorithm) Header Parameter not allowed');if(s){if(typeof e.payload!="string")throw new h("JWS Payload must be a string")}else if(typeof e.payload!="string"&&!(e.payload instanceof Uint8Array))throw new h("JWS Payload must be a string or an Uint8Array instance");let p=!1;typeof t=="function"&&(t=await t(o,e),p=!0),V(c,t,"verify");let m=W(E.encode((n=e.protected)!==null&&n!==void 0?n:""),E.encode("."),typeof e.payload=="string"?E.encode(e.payload):e.payload),K=S(e.signature);if(!await Bt(c,t,K,m))throw new Z;let x;s?x=S(e.payload):typeof e.payload=="string"?x=E.encode(e.payload):x=e.payload;let _={payload:x};return e.protected!==void 0&&(_.protectedHeader=o),e.header!==void 0&&(_.unprotectedHeader=e.header),p?{..._,key:t}:_}async function et(e,t,r){if(e instanceof Uint8Array&&(e=v.decode(e)),typeof e!="string")throw new h("Compact JWS must be a string or Uint8Array");let{0:n,1:o,2:a,length:i}=e.split(".");if(i!==3)throw new h("Invalid Compact JWS");let s=await Ae({payload:o,protected:n,signature:a},t,r),c={payload:s.payload,protectedHeader:s.protectedHeader};return typeof t=="function"?{...c,key:s.key}:c}async function Jr(e,t,r){if(!w(e))throw new h("General JWS must be an object");if(!Array.isArray(e.signatures)||!e.signatures.every(w))throw new h("JWS Signatures missing or incorrect type");for(let n of e.signatures)try{return await Ae({header:n.header,payload:e.payload,protected:n.protected,signature:n.signature},t,r)}catch(o){}throw new Z}var ie=e=>Math.floor(e.getTime()/1e3);var Tr=/^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i,se=e=>{let t=Tr.exec(e);if(!t)throw new TypeError("Invalid time period format");let r=parseFloat(t[1]);switch(t[2].toLowerCase()){case"sec":case"secs":case"second":case"seconds":case"s":return Math.round(r);case"minute":case"minutes":case"min":case"mins":case"m":return Math.round(r*60);case"hour":case"hours":case"hr":case"hrs":case"h":return Math.round(r*3600);case"day":case"days":case"d":return Math.round(r*86400);case"week":case"weeks":case"w":return Math.round(r*604800);default:return Math.round(r*31557600)}};var Lt=e=>e.toLowerCase().replace(/^application\//,""),Ir=(e,t)=>typeof e=="string"?t.includes(e):Array.isArray(e)?t.some(Set.prototype.has.bind(new Set(e))):!1,ce=(e,t,r={})=>{let{typ:n}=r;if(n&&(typeof e.typ!="string"||Lt(e.typ)!==Lt(n)))throw new J('unexpected "typ" JWT header value',"typ","check_failed");let o;try{o=JSON.parse(v.decode(t));}catch(m){}if(!w(o))throw new H("JWT Claims Set must be a top-level JSON object");let{issuer:a}=r;if(a&&!(Array.isArray(a)?a:[a]).includes(o.iss))throw new J('unexpected "iss" claim value',"iss","check_failed");let{subject:i}=r;if(i&&o.sub!==i)throw new J('unexpected "sub" claim value',"sub","check_failed");let{audience:s}=r;if(s&&!Ir(o.aud,typeof s=="string"?[s]:s))throw new J('unexpected "aud" claim value',"aud","check_failed");let c;switch(typeof r.clockTolerance){case"string":c=se(r.clockTolerance);break;case"number":c=r.clockTolerance;break;case"undefined":c=0;break;default:throw new TypeError("Invalid clockTolerance option type")}let{currentDate:d}=r,p=ie(d||new Date);if((o.iat!==void 0||r.maxTokenAge)&&typeof o.iat!="number")throw new J('"iat" claim must be a number',"iat","invalid");if(o.nbf!==void 0){if(typeof o.nbf!="number")throw new J('"nbf" claim must be a number',"nbf","invalid");if(o.nbf>p+c)throw new J('"nbf" claim timestamp check failed',"nbf","check_failed")}if(o.exp!==void 0){if(typeof o.exp!="number")throw new J('"exp" claim must be a number',"exp","invalid");if(o.exp<=p-c)throw new re('"exp" claim timestamp check failed',"exp","check_failed")}if(r.maxTokenAge){let m=p-o.iat,K=typeof r.maxTokenAge=="number"?r.maxTokenAge:se(r.maxTokenAge);if(m-c>K)throw new re('"iat" claim timestamp check failed (too far in the past)',"iat","check_failed");if(m<0-c)throw new J('"iat" claim timestamp check failed (it should be in the past)',"iat","check_failed")}return o};async function Dr(e,t,r){var n;let o=await et(e,t,r);if(!((n=o.protectedHeader.crit)===null||n===void 0)&&n.includes("b64")&&o.protectedHeader.b64===!1)throw new H("JWTs MUST NOT use unencoded payload");let i={payload:ce(o.protectedHeader,o.payload,r),protectedHeader:o.protectedHeader};return typeof t=="function"?{...i,key:o.key}:i}async function Rr(e,t,r){let n=await Ye(e,t,r),o=ce(n.protectedHeader,n.plaintext,r),{protectedHeader:a}=n;if(a.iss!==void 0&&a.iss!==o.iss)throw new J('replicated "iss" claim header parameter mismatch',"iss","mismatch");if(a.sub!==void 0&&a.sub!==o.sub)throw new J('replicated "sub" claim header parameter mismatch',"sub","mismatch");if(a.aud!==void 0&&JSON.stringify(a.aud)!==JSON.stringify(o.aud))throw new J('replicated "aud" claim header parameter mismatch',"aud","mismatch");let i={payload:o,protectedHeader:a};return typeof t=="function"?{...i,key:n.key}:i}var be=class{constructor(t){this._flattened=new F(t);}setContentEncryptionKey(t){return this._flattened.setContentEncryptionKey(t),this}setInitializationVector(t){return this._flattened.setInitializationVector(t),this}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}setKeyManagementParameters(t){return this._flattened.setKeyManagementParameters(t),this}async encrypt(t,r){let n=await this._flattened.encrypt(t,r);return [n.protected,n.encrypted_key,n.iv,n.ciphertext,n.tag].join(".")}};var Or=async(e,t,r)=>{let n=await Se(e,t,"sign");Q(e,n);let o=await f.subtle.sign(ge(e,n.algorithm),n,r);return new Uint8Array(o)},$t=Or;var ee=class{constructor(t){if(!(t instanceof Uint8Array))throw new TypeError("payload must be an instance of Uint8Array");this._payload=t;}setProtectedHeader(t){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=t,this}setUnprotectedHeader(t){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=t,this}async sign(t,r){if(!this._protectedHeader&&!this._unprotectedHeader)throw new h("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");if(!R(this._protectedHeader,this._unprotectedHeader))throw new h("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let n={...this._protectedHeader,...this._unprotectedHeader},o=U(h,new Map([["b64",!0]]),r==null?void 0:r.crit,this._protectedHeader,n),a=!0;if(o.has("b64")&&(a=this._protectedHeader.b64,typeof a!="boolean"))throw new h('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:i}=n;if(typeof i!="string"||!i)throw new h('JWS "alg" (Algorithm) Header Parameter missing or invalid');V(i,t,"sign");let s=this._payload;a&&(s=E.encode(g(s)));let c;this._protectedHeader?c=E.encode(g(JSON.stringify(this._protectedHeader))):c=E.encode("");let d=W(c,E.encode("."),s),p=await $t(i,t,d),m={signature:g(p),payload:""};return a&&(m.payload=v.decode(s)),this._unprotectedHeader&&(m.header=this._unprotectedHeader),this._protectedHeader&&(m.protected=v.decode(c)),m}};var _e=class{constructor(t){this._flattened=new ee(t);}setProtectedHeader(t){return this._flattened.setProtectedHeader(t),this}async sign(t,r){let n=await this._flattened.sign(t,r);if(n.payload===void 0)throw new TypeError("use the flattened module for creating JWS with b64: false");return `${n.protected}.${n.payload}.${n.signature}`}};var tt=class{constructor(t,r,n){this.parent=t,this.key=r,this.options=n;}setProtectedHeader(t){if(this.protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this.protectedHeader=t,this}setUnprotectedHeader(t){if(this.unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this.unprotectedHeader=t,this}addSignature(...t){return this.parent.addSignature(...t)}sign(...t){return this.parent.sign(...t)}done(){return this.parent}},rt=class{constructor(t){this._signatures=[],this._payload=t;}addSignature(t,r){let n=new tt(this,t,r);return this._signatures.push(n),n}async sign(){if(!this._signatures.length)throw new h("at least one signature must be added");let t={signatures:[],payload:""};for(let r=0;r{if(typeof e!="string"||!e)throw new pe(`${t} missing or invalid`)};async function Gt(e,t){if(!w(e))throw new TypeError("JWK must be an object");if(t!=null||(t="sha256"),t!=="sha256"&&t!=="sha384"&&t!=="sha512")throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"');let r;switch(e.kty){case"EC":X(e.crv,'"crv" (Curve) Parameter'),X(e.x,'"x" (X Coordinate) Parameter'),X(e.y,'"y" (Y Coordinate) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x,y:e.y};break;case"OKP":X(e.crv,'"crv" (Subtype of Key Pair) Parameter'),X(e.x,'"x" (Public Key) Parameter'),r={crv:e.crv,kty:e.kty,x:e.x};break;case"RSA":X(e.e,'"e" (Exponent) Parameter'),X(e.n,'"n" (Modulus) Parameter'),r={e:e.e,kty:e.kty,n:e.n};break;case"oct":X(e.k,'"k" (Key Value) Parameter'),r={k:e.k,kty:e.kty};break;default:throw new l('"kty" (Key Type) Parameter missing or unsupported')}let n=E.encode(JSON.stringify(r));return g(await Ke(t,n))}async function Ur(e,t){t!=null||(t="sha256");let r=await Gt(e,t);return `urn:ietf:params:oauth:jwk-thumbprint:sha-${t.slice(-3)}:${r}`}async function Mr(e,t){let r={...e,...t.header};if(!w(r.jwk))throw new h('"jwk" (JSON Web Key) Header Parameter must be a JSON object');let n=await j({...r.jwk,ext:!0},r.alg,!0);if(n instanceof Uint8Array||n.type!=="public")throw new h('"jwk" (JSON Web Key) Header Parameter must be a public key');return n}function Nr(e){switch(typeof e=="string"&&e.slice(0,2)){case"RS":case"PS":return "RSA";case"ES":return "EC";case"Ed":return "OKP";default:throw new l('Unsupported "alg" value for a JSON Web Key Set')}}function at(e){return e&&typeof e=="object"&&Array.isArray(e.keys)&&e.keys.every(kr)}function kr(e){return w(e)}function Br(e){return typeof structuredClone=="function"?structuredClone(e):JSON.parse(JSON.stringify(e))}var de=class{constructor(t){if(this._cached=new WeakMap,!at(t))throw new L("JSON Web Key Set malformed");this._jwks=Br(t);}async getKey(t,r){let{alg:n,kid:o}={...t,...r==null?void 0:r.header},a=Nr(n),i=this._jwks.keys.filter(d=>{let p=a===d.kty;if(p&&typeof o=="string"&&(p=o===d.kid),p&&typeof d.alg=="string"&&(p=n===d.alg),p&&typeof d.use=="string"&&(p=d.use==="sig"),p&&Array.isArray(d.key_ops)&&(p=d.key_ops.includes("verify")),p&&n==="EdDSA"&&(p=d.crv==="Ed25519"||d.crv==="Ed448"),p)switch(n){case"ES256":p=d.crv==="P-256";break;case"ES256K":p=d.crv==="secp256k1";break;case"ES384":p=d.crv==="P-384";break;case"ES512":p=d.crv==="P-521";break}return p}),{0:s,length:c}=i;if(c===0)throw new q;if(c!==1){let d=new ue,{_cached:p}=this;throw d[Symbol.asyncIterator]=async function*(){for(let m of i)try{yield await Vt(p,m,n);}catch(K){continue}},d}return Vt(this._cached,s,n)}};async function Vt(e,t,r){let n=e.get(t)||e.set(t,{}).get(t);if(n[r]===void 0){let o=await j({...t,ext:!0},r);if(o.type!=="public")throw new L("JSON Web Key Set members must be public keys");n[r]=o;}return n[r]}function Lr(e){return de.prototype.getKey.bind(new de(e))}var $r=async(e,t,r)=>{let n,o,a=!1;typeof AbortController=="function"&&(n=new AbortController,o=setTimeout(()=>{a=!0,n.abort();},t));let i=await fetch(e.href,{signal:n?n.signal:void 0,redirect:"manual",headers:r.headers}).catch(s=>{throw a?new fe:s});if(o!==void 0&&clearTimeout(o),i.status!==200)throw new C("Expected 200 OK from the JSON Web Key Set HTTP response");try{return await i.json()}catch(s){throw new C("Failed to parse the JSON Web Key Set HTTP response as JSON")}},Ft=$r;var Me=class extends de{constructor(t,r){if(super({keys:[]}),this._jwks=void 0,!(t instanceof URL))throw new TypeError("url must be an instance of URL");this._url=new URL(t.href),this._options={agent:r==null?void 0:r.agent,headers:r==null?void 0:r.headers},this._timeoutDuration=typeof(r==null?void 0:r.timeoutDuration)=="number"?r==null?void 0:r.timeoutDuration:5e3,this._cooldownDuration=typeof(r==null?void 0:r.cooldownDuration)=="number"?r==null?void 0:r.cooldownDuration:3e4,this._cacheMaxAge=typeof(r==null?void 0:r.cacheMaxAge)=="number"?r==null?void 0:r.cacheMaxAge:6e5;}coolingDown(){return typeof this._jwksTimestamp=="number"?Date.now(){let r=()=>{this._pendingFetch===void 0?t():setTimeout(r,5);};r();});this._pendingFetch||(this._pendingFetch=Ft(this._url,this._timeoutDuration,this._options).then(t=>{if(!at(t))throw new L("JSON Web Key Set malformed");this._jwks={keys:t.keys},this._jwksTimestamp=Date.now(),this._pendingFetch=void 0;}).catch(t=>{throw this._pendingFetch=void 0,t})),await this._pendingFetch;}};function Gr(e,t){return Me.prototype.getKey.bind(new Me(e,t))}var it=class extends z{encode(){let t=g(JSON.stringify({alg:"none"})),r=g(JSON.stringify(this._payload));return `${t}.${r}.`}static decode(t,r){if(typeof t!="string")throw new H("Unsecured JWT must be a string");let{0:n,1:o,2:a,length:i}=t.split(".");if(i!==3||a!=="")throw new H("Invalid Unsecured JWT");let s;try{if(s=JSON.parse(v.decode(S(n))),s.alg!=="none")throw new Error}catch(d){throw new H("Invalid Unsecured JWT")}return {payload:ce(s,S(o),r),header:s}}};var zt={};ct(zt,{decode:()=>ve,encode:()=>Vr});var Vr=g,ve=S;function Fr(e){let t;if(typeof e=="string"){let r=e.split(".");(r.length===3||r.length===5)&&([t]=r);}else if(typeof e=="object"&&e)if("protected"in e)t=e.protected;else throw new TypeError("Token does not contain a Protected Header");try{if(typeof t!="string"||!t)throw new Error;let r=JSON.parse(v.decode(ve(t)));if(!w(r))throw new Error;return r}catch(r){throw new TypeError("Invalid Token or Protected Header formatting")}}function zr(e){if(typeof e!="string")throw new H("JWTs must use Compact JWS serialization, JWT must be a string");let{1:t,length:r}=e.split(".");if(r===5)throw new H("Only JWTs using Compact JWS serialization can be decoded");if(r!==3)throw new H("Invalid JWT");if(!t)throw new H("JWTs must contain a payload");let n;try{n=ve(t);}catch(a){throw new H("Failed to parse the base64url encoded payload")}let o;try{o=JSON.parse(v.decode(n));}catch(a){throw new H("Failed to parse the decoded payload as JSON")}if(!w(o))throw new H("Invalid JWT Claims Set");return o}async function Xt(e,t){var r;let n,o,a;switch(e){case"HS256":case"HS384":case"HS512":n=parseInt(e.slice(-3),10),o={name:"HMAC",hash:`SHA-${n}`,length:n},a=["sign","verify"];break;case"A128CBC-HS256":case"A192CBC-HS384":case"A256CBC-HS512":return n=parseInt(e.slice(-3),10),$(new Uint8Array(n>>3));case"A128KW":case"A192KW":case"A256KW":n=parseInt(e.slice(1,4),10),o={name:"AES-KW",length:n},a=["wrapKey","unwrapKey"];break;case"A128GCMKW":case"A192GCMKW":case"A256GCMKW":case"A128GCM":case"A192GCM":case"A256GCM":n=parseInt(e.slice(1,4),10),o={name:"AES-GCM",length:n},a=["encrypt","decrypt"];break;default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}return f.subtle.generateKey(o,(r=t==null?void 0:t.extractable)!==null&&r!==void 0?r:!1,a)}function st(e){var t;let r=(t=e==null?void 0:e.modulusLength)!==null&&t!==void 0?t:2048;if(typeof r!="number"||r<2048)throw new l("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used");return r}async function Yt(e,t){var r,n,o,a;let i,s;switch(e){case"PS256":case"PS384":case"PS512":i={name:"RSA-PSS",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RS256":case"RS384":case"RS512":i={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["sign","verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":i={name:"RSA-OAEP",hash:`SHA-${parseInt(e.slice(-3),10)||1}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:st(t)},s=["decrypt","unwrapKey","encrypt","wrapKey"];break;case"ES256":i={name:"ECDSA",namedCurve:"P-256"},s=["sign","verify"];break;case"ES384":i={name:"ECDSA",namedCurve:"P-384"},s=["sign","verify"];break;case"ES512":i={name:"ECDSA",namedCurve:"P-521"},s=["sign","verify"];break;case"EdDSA":s=["sign","verify"];let c=(r=t==null?void 0:t.crv)!==null&&r!==void 0?r:"Ed25519";switch(c){case"Ed25519":case"Ed448":i={name:c};break;default:throw new l("Invalid or unsupported crv option provided")}break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{s=["deriveKey","deriveBits"];let d=(n=t==null?void 0:t.crv)!==null&&n!==void 0?n:"P-256";switch(d){case"P-256":case"P-384":case"P-521":{i={name:"ECDH",namedCurve:d};break}case"X25519":case"X448":i={name:d};break;default:throw new l("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448")}break}default:throw new l('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}try{return await f.subtle.generateKey(i,(o=t==null?void 0:t.extractable)!==null&&o!==void 0?o:!1,s)}catch(c){if(i.name==="Ed25519"&&(c==null?void 0:c.name)==="NotSupportedError"&&D())return i={name:"NODE-ED25519",namedCurve:"NODE-ED25519"},await f.subtle.generateKey(i,(a=t==null?void 0:t.extractable)!==null&&a!==void 0?a:!1,s);throw c}}async function Xr(e,t){return Yt(e,t)}async function Yr(e,t){return Xt(e,t)} +exports.CompactEncrypt=be;exports.CompactSign=_e;exports.EmbeddedJWK=Mr;exports.EncryptJWT=ot;exports.FlattenedEncrypt=F;exports.FlattenedSign=ee;exports.GeneralEncrypt=je;exports.GeneralSign=rt;exports.SignJWT=nt;exports.UnsecuredJWT=it;exports.base64url=zt;exports.calculateJwkThumbprint=Gt;exports.calculateJwkThumbprintUri=Ur;exports.compactDecrypt=Ye;exports.compactVerify=et;exports.createLocalJWKSet=Lr;exports.createRemoteJWKSet=Gr;exports.decodeJwt=zr;exports.decodeProtectedHeader=Fr;exports.errors=ft;exports.exportJWK=qe;exports.exportPKCS8=Cr;exports.exportSPKI=Hr;exports.flattenedDecrypt=Ee;exports.flattenedVerify=Ae;exports.generalDecrypt=Kr;exports.generalVerify=Jr;exports.generateKeyPair=Xr;exports.generateSecret=Yr;exports.importJWK=j;exports.importPKCS8=hr;exports.importSPKI=lr;exports.importX509=mr;exports.jwtDecrypt=Rr;exports.jwtVerify=Dr;})); \ No newline at end of file diff --git a/dist/browser/jwe/compact/decrypt.js b/dist/browser/jwe/compact/decrypt.js new file mode 100644 index 0000000000..129aeb6e39 --- /dev/null +++ b/dist/browser/jwe/compact/decrypt.js @@ -0,0 +1,27 @@ +import { flattenedDecrypt } from '../flattened/decrypt.js'; +import { JWEInvalid } from '../../util/errors.js'; +import { decoder } from '../../lib/buffer_utils.js'; +export async function compactDecrypt(jwe, key, options) { + if (jwe instanceof Uint8Array) { + jwe = decoder.decode(jwe); + } + if (typeof jwe !== 'string') { + throw new JWEInvalid('Compact JWE must be a string or Uint8Array'); + } + const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.'); + if (length !== 5) { + throw new JWEInvalid('Invalid Compact JWE'); + } + const decrypted = await flattenedDecrypt({ + ciphertext, + iv: (iv || undefined), + protected: protectedHeader || undefined, + tag: (tag || undefined), + encrypted_key: encryptedKey || undefined, + }, key, options); + const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: decrypted.key }; + } + return result; +} diff --git a/dist/browser/jwe/compact/encrypt.js b/dist/browser/jwe/compact/encrypt.js new file mode 100644 index 0000000000..e689139465 --- /dev/null +++ b/dist/browser/jwe/compact/encrypt.js @@ -0,0 +1,26 @@ +import { FlattenedEncrypt } from '../flattened/encrypt.js'; +export class CompactEncrypt { + constructor(plaintext) { + this._flattened = new FlattenedEncrypt(plaintext); + } + setContentEncryptionKey(cek) { + this._flattened.setContentEncryptionKey(cek); + return this; + } + setInitializationVector(iv) { + this._flattened.setInitializationVector(iv); + return this; + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + setKeyManagementParameters(parameters) { + this._flattened.setKeyManagementParameters(parameters); + return this; + } + async encrypt(key, options) { + const jwe = await this._flattened.encrypt(key, options); + return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.'); + } +} diff --git a/dist/browser/jwe/flattened/decrypt.js b/dist/browser/jwe/flattened/decrypt.js new file mode 100644 index 0000000000..2373a48f54 --- /dev/null +++ b/dist/browser/jwe/flattened/decrypt.js @@ -0,0 +1,137 @@ +import { decode as base64url } from '../../runtime/base64url.js'; +import decrypt from '../../runtime/decrypt.js'; +import { inflate } from '../../runtime/zlib.js'; +import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import isObject from '../../lib/is_object.js'; +import decryptKeyManagement from '../../lib/decrypt_key_management.js'; +import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; +import generateCek from '../../lib/cek.js'; +import validateCrit from '../../lib/validate_crit.js'; +import validateAlgorithms from '../../lib/validate_algorithms.js'; +export async function flattenedDecrypt(jwe, key, options) { + var _a; + if (!isObject(jwe)) { + throw new JWEInvalid('Flattened JWE must be an object'); + } + if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { + throw new JWEInvalid('JOSE Header missing'); + } + if (typeof jwe.iv !== 'string') { + throw new JWEInvalid('JWE Initialization Vector missing or incorrect type'); + } + if (typeof jwe.ciphertext !== 'string') { + throw new JWEInvalid('JWE Ciphertext missing or incorrect type'); + } + if (typeof jwe.tag !== 'string') { + throw new JWEInvalid('JWE Authentication Tag missing or incorrect type'); + } + if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { + throw new JWEInvalid('JWE Protected Header incorrect type'); + } + if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { + throw new JWEInvalid('JWE Encrypted Key incorrect type'); + } + if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { + throw new JWEInvalid('JWE AAD incorrect type'); + } + if (jwe.header !== undefined && !isObject(jwe.header)) { + throw new JWEInvalid('JWE Shared Unprotected Header incorrect type'); + } + if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) { + throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type'); + } + let parsedProt; + if (jwe.protected) { + try { + const protectedHeader = base64url(jwe.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader)); + } + catch (_b) { + throw new JWEInvalid('JWE Protected Header is invalid'); + } + } + if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) { + throw new JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...parsedProt, + ...jwe.header, + ...jwe.unprotected, + }; + validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + if (joseHeader.zip !== undefined) { + if (!parsedProt || !parsedProt.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== 'DEF') { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header'); + } + if (typeof enc !== 'string' || !enc) { + throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header'); + } + const keyManagementAlgorithms = options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms); + const contentEncryptionAlgorithms = options && + validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms); + if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { + throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); + } + let encryptedKey; + if (jwe.encrypted_key !== undefined) { + encryptedKey = base64url(jwe.encrypted_key); + } + let resolvedKey = false; + if (typeof key === 'function') { + key = await key(parsedProt, jwe); + resolvedKey = true; + } + let cek; + try { + cek = await decryptKeyManagement(alg, key, encryptedKey, joseHeader, options); + } + catch (err) { + if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { + throw err; + } + cek = generateCek(enc); + } + const iv = base64url(jwe.iv); + const tag = base64url(jwe.tag); + const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ''); + let additionalData; + if (jwe.aad !== undefined) { + additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(jwe.aad)); + } + else { + additionalData = protectedHeader; + } + let plaintext = await decrypt(enc, cek, base64url(jwe.ciphertext), iv, tag, additionalData); + if (joseHeader.zip === 'DEF') { + plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); + } + const result = { plaintext }; + if (jwe.protected !== undefined) { + result.protectedHeader = parsedProt; + } + if (jwe.aad !== undefined) { + result.additionalAuthenticatedData = base64url(jwe.aad); + } + if (jwe.unprotected !== undefined) { + result.sharedUnprotectedHeader = jwe.unprotected; + } + if (jwe.header !== undefined) { + result.unprotectedHeader = jwe.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} diff --git a/dist/browser/jwe/flattened/encrypt.js b/dist/browser/jwe/flattened/encrypt.js new file mode 100644 index 0000000000..1e60ecd8c4 --- /dev/null +++ b/dist/browser/jwe/flattened/encrypt.js @@ -0,0 +1,175 @@ +import { encode as base64url } from '../../runtime/base64url.js'; +import encrypt from '../../runtime/encrypt.js'; +import { deflate } from '../../runtime/zlib.js'; +import generateIv from '../../lib/iv.js'; +import encryptKeyManagement from '../../lib/encrypt_key_management.js'; +import { JOSENotSupported, JWEInvalid } from '../../util/errors.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; +import validateCrit from '../../lib/validate_crit.js'; +export const unprotected = Symbol(); +export class FlattenedEncrypt { + constructor(plaintext) { + if (!(plaintext instanceof Uint8Array)) { + throw new TypeError('plaintext must be an instance of Uint8Array'); + } + this._plaintext = plaintext; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once'); + } + this._keyManagementParameters = parameters; + return this; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._sharedUnprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once'); + } + this._sharedUnprotectedHeader = sharedUnprotectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once'); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once'); + } + this._iv = iv; + return this; + } + async encrypt(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { + throw new JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()'); + } + if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { + throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...this._sharedUnprotectedHeader, + }; + validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== 'DEF') { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (typeof enc !== 'string' || !enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + let encryptedKey; + if (alg === 'dir') { + if (this._cek) { + throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption'); + } + } + else if (alg === 'ECDH-ES') { + if (this._cek) { + throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement'); + } + } + let cek; + { + let parameters; + ({ cek, encryptedKey, parameters } = await encryptKeyManagement(alg, enc, key, this._cek, this._keyManagementParameters)); + if (parameters) { + if (options && unprotected in options) { + if (!this._unprotectedHeader) { + this.setUnprotectedHeader(parameters); + } + else { + this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; + } + } + else { + if (!this._protectedHeader) { + this.setProtectedHeader(parameters); + } + else { + this._protectedHeader = { ...this._protectedHeader, ...parameters }; + } + } + } + } + this._iv || (this._iv = generateIv(enc)); + let additionalData; + let protectedHeader; + let aadMember; + if (this._protectedHeader) { + protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); + } + else { + protectedHeader = encoder.encode(''); + } + if (this._aad) { + aadMember = base64url(this._aad); + additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember)); + } + else { + additionalData = protectedHeader; + } + let ciphertext; + let tag; + if (joseHeader.zip === 'DEF') { + const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); + ({ ciphertext, tag } = await encrypt(enc, deflated, cek, this._iv, additionalData)); + } + else { + ; + ({ ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData)); + } + const jwe = { + ciphertext: base64url(ciphertext), + iv: base64url(this._iv), + tag: base64url(tag), + }; + if (encryptedKey) { + jwe.encrypted_key = base64url(encryptedKey); + } + if (aadMember) { + jwe.aad = aadMember; + } + if (this._protectedHeader) { + jwe.protected = decoder.decode(protectedHeader); + } + if (this._sharedUnprotectedHeader) { + jwe.unprotected = this._sharedUnprotectedHeader; + } + if (this._unprotectedHeader) { + jwe.header = this._unprotectedHeader; + } + return jwe; + } +} diff --git a/dist/browser/jwe/general/decrypt.js b/dist/browser/jwe/general/decrypt.js new file mode 100644 index 0000000000..d21b6d1fa8 --- /dev/null +++ b/dist/browser/jwe/general/decrypt.js @@ -0,0 +1,31 @@ +import { flattenedDecrypt } from '../flattened/decrypt.js'; +import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.js'; +import isObject from '../../lib/is_object.js'; +export async function generalDecrypt(jwe, key, options) { + if (!isObject(jwe)) { + throw new JWEInvalid('General JWE must be an object'); + } + if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { + throw new JWEInvalid('JWE Recipients missing or incorrect type'); + } + if (!jwe.recipients.length) { + throw new JWEInvalid('JWE Recipients has no members'); + } + for (const recipient of jwe.recipients) { + try { + return await flattenedDecrypt({ + aad: jwe.aad, + ciphertext: jwe.ciphertext, + encrypted_key: recipient.encrypted_key, + header: recipient.header, + iv: jwe.iv, + protected: jwe.protected, + tag: jwe.tag, + unprotected: jwe.unprotected, + }, key, options); + } + catch (_a) { + } + } + throw new JWEDecryptionFailed(); +} diff --git a/dist/browser/jwe/general/encrypt.js b/dist/browser/jwe/general/encrypt.js new file mode 100644 index 0000000000..3ee53dec44 --- /dev/null +++ b/dist/browser/jwe/general/encrypt.js @@ -0,0 +1,178 @@ +import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.js'; +import { JWEInvalid } from '../../util/errors.js'; +import generateCek from '../../lib/cek.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import encryptKeyManagement from '../../lib/encrypt_key_management.js'; +import { encode as base64url } from '../../runtime/base64url.js'; +import validateCrit from '../../lib/validate_crit.js'; +class IndividualRecipient { + constructor(enc, key, options) { + this.parent = enc; + this.key = key; + this.options = options; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addRecipient(...args) { + return this.parent.addRecipient(...args); + } + encrypt(...args) { + return this.parent.encrypt(...args); + } + done() { + return this.parent; + } +} +export class GeneralEncrypt { + constructor(plaintext) { + this._recipients = []; + this._plaintext = plaintext; + } + addRecipient(key, options) { + const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); + this._recipients.push(recipient); + return recipient; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = sharedUnprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + async encrypt(options) { + var _a, _b, _c; + if (!this._recipients.length) { + throw new JWEInvalid('at least one recipient must be added'); + } + options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; + if (this._recipients.length === 1) { + const [recipient] = this._recipients; + const flattened = await new FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader) + .encrypt(recipient.key, { ...recipient.options, ...options }); + let jwe = { + ciphertext: flattened.ciphertext, + iv: flattened.iv, + recipients: [{}], + tag: flattened.tag, + }; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + if (flattened.encrypted_key) + jwe.recipients[0].encrypted_key = flattened.encrypted_key; + if (flattened.header) + jwe.recipients[0].header = flattened.header; + return jwe; + } + let enc; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { + throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + }; + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (alg === 'dir' || alg === 'ECDH-ES') { + throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); + } + if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + if (!enc) { + enc = joseHeader.enc; + } + else if (enc !== joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); + } + validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + } + } + const cek = generateCek(enc); + let jwe = { + ciphertext: '', + iv: '', + recipients: [], + tag: '', + }; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + const target = {}; + jwe.recipients.push(target); + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + }; + const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined; + if (i === 0) { + const flattened = await new FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setContentEncryptionKey(cek) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader) + .setKeyManagementParameters({ p2c }) + .encrypt(recipient.key, { + ...recipient.options, + ...options, + [unprotected]: true, + }); + jwe.ciphertext = flattened.ciphertext; + jwe.iv = flattened.iv; + jwe.tag = flattened.tag; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + target.encrypted_key = flattened.encrypted_key; + if (flattened.header) + target.header = flattened.header; + continue; + } + const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || + ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || + ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); + target.encrypted_key = base64url(encryptedKey); + if (recipient.unprotectedHeader || parameters) + target.header = { ...recipient.unprotectedHeader, ...parameters }; + } + return jwe; + } +} diff --git a/dist/browser/jwk/embedded.js b/dist/browser/jwk/embedded.js new file mode 100644 index 0000000000..58db282552 --- /dev/null +++ b/dist/browser/jwk/embedded.js @@ -0,0 +1,17 @@ +import { importJWK } from '../key/import.js'; +import isObject from '../lib/is_object.js'; +import { JWSInvalid } from '../util/errors.js'; +export async function EmbeddedJWK(protectedHeader, token) { + const joseHeader = { + ...protectedHeader, + ...token.header, + }; + if (!isObject(joseHeader.jwk)) { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); + } + const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); + if (key instanceof Uint8Array || key.type !== 'public') { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); + } + return key; +} diff --git a/dist/browser/jwk/thumbprint.js b/dist/browser/jwk/thumbprint.js new file mode 100644 index 0000000000..49f86b1743 --- /dev/null +++ b/dist/browser/jwk/thumbprint.js @@ -0,0 +1,53 @@ +import digest from '../runtime/digest.js'; +import { encode as base64url } from '../runtime/base64url.js'; +import { JOSENotSupported, JWKInvalid } from '../util/errors.js'; +import { encoder } from '../lib/buffer_utils.js'; +import isObject from '../lib/is_object.js'; +const check = (value, description) => { + if (typeof value !== 'string' || !value) { + throw new JWKInvalid(`${description} missing or invalid`); + } +}; +export async function calculateJwkThumbprint(jwk, digestAlgorithm) { + if (!isObject(jwk)) { + throw new TypeError('JWK must be an object'); + } + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); + if (digestAlgorithm !== 'sha256' && + digestAlgorithm !== 'sha384' && + digestAlgorithm !== 'sha512') { + throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); + } + let components; + switch (jwk.kty) { + case 'EC': + check(jwk.crv, '"crv" (Curve) Parameter'); + check(jwk.x, '"x" (X Coordinate) Parameter'); + check(jwk.y, '"y" (Y Coordinate) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; + break; + case 'OKP': + check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); + check(jwk.x, '"x" (Public Key) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; + break; + case 'RSA': + check(jwk.e, '"e" (Exponent) Parameter'); + check(jwk.n, '"n" (Modulus) Parameter'); + components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; + break; + case 'oct': + check(jwk.k, '"k" (Key Value) Parameter'); + components = { k: jwk.k, kty: jwk.kty }; + break; + default: + throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); + } + const data = encoder.encode(JSON.stringify(components)); + return base64url(await digest(digestAlgorithm, data)); +} +export async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); + const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); + return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; +} diff --git a/dist/browser/jwks/local.js b/dist/browser/jwks/local.js new file mode 100644 index 0000000000..a6763bb49f --- /dev/null +++ b/dist/browser/jwks/local.js @@ -0,0 +1,113 @@ +import { importJWK } from '../key/import.js'; +import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js'; +import isObject from '../lib/is_object.js'; +function getKtyFromAlg(alg) { + switch (typeof alg === 'string' && alg.slice(0, 2)) { + case 'RS': + case 'PS': + return 'RSA'; + case 'ES': + return 'EC'; + case 'Ed': + return 'OKP'; + default: + throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); + } +} +export function isJWKSLike(jwks) { + return (jwks && + typeof jwks === 'object' && + Array.isArray(jwks.keys) && + jwks.keys.every(isJWKLike)); +} +function isJWKLike(key) { + return isObject(key); +} +function clone(obj) { + if (typeof structuredClone === 'function') { + return structuredClone(obj); + } + return JSON.parse(JSON.stringify(obj)); +} +export class LocalJWKSet { + constructor(jwks) { + this._cached = new WeakMap(); + if (!isJWKSLike(jwks)) { + throw new JWKSInvalid('JSON Web Key Set malformed'); + } + this._jwks = clone(jwks); + } + async getKey(protectedHeader, token) { + const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; + const kty = getKtyFromAlg(alg); + const candidates = this._jwks.keys.filter((jwk) => { + let candidate = kty === jwk.kty; + if (candidate && typeof kid === 'string') { + candidate = kid === jwk.kid; + } + if (candidate && typeof jwk.alg === 'string') { + candidate = alg === jwk.alg; + } + if (candidate && typeof jwk.use === 'string') { + candidate = jwk.use === 'sig'; + } + if (candidate && Array.isArray(jwk.key_ops)) { + candidate = jwk.key_ops.includes('verify'); + } + if (candidate && alg === 'EdDSA') { + candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'; + } + if (candidate) { + switch (alg) { + case 'ES256': + candidate = jwk.crv === 'P-256'; + break; + case 'ES256K': + candidate = jwk.crv === 'secp256k1'; + break; + case 'ES384': + candidate = jwk.crv === 'P-384'; + break; + case 'ES512': + candidate = jwk.crv === 'P-521'; + break; + } + } + return candidate; + }); + const { 0: jwk, length } = candidates; + if (length === 0) { + throw new JWKSNoMatchingKey(); + } + else if (length !== 1) { + const error = new JWKSMultipleMatchingKeys(); + const { _cached } = this; + error[Symbol.asyncIterator] = async function* () { + for (const jwk of candidates) { + try { + yield await importWithAlgCache(_cached, jwk, alg); + } + catch (_a) { + continue; + } + } + }; + throw error; + } + return importWithAlgCache(this._cached, jwk, alg); + } +} +async function importWithAlgCache(cache, jwk, alg) { + const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); + if (cached[alg] === undefined) { + const keyObject = await importJWK({ ...jwk, ext: true }, alg); + if (keyObject.type !== 'public') { + throw new JWKSInvalid('JSON Web Key Set members must be public keys'); + } + cached[alg] = keyObject; + } + return cached[alg]; +} +export function createLocalJWKSet(jwks) { + return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); +} diff --git a/dist/browser/jwks/remote.js b/dist/browser/jwks/remote.js new file mode 100644 index 0000000000..574ccff83b --- /dev/null +++ b/dist/browser/jwks/remote.js @@ -0,0 +1,81 @@ +import fetchJwks from '../runtime/fetch_jwks.js'; +import { isCloudflareWorkers } from '../runtime/env.js'; +import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.js'; +import { isJWKSLike, LocalJWKSet } from './local.js'; +class RemoteJWKSet extends LocalJWKSet { + constructor(url, options) { + super({ keys: [] }); + this._jwks = undefined; + if (!(url instanceof URL)) { + throw new TypeError('url must be an instance of URL'); + } + this._url = new URL(url.href); + this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; + this._timeoutDuration = + typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000; + this._cooldownDuration = + typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000; + this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000; + } + coolingDown() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cooldownDuration + : false; + } + fresh() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cacheMaxAge + : false; + } + async getKey(protectedHeader, token) { + if (!this._jwks || !this.fresh()) { + await this.reload(); + } + try { + return await super.getKey(protectedHeader, token); + } + catch (err) { + if (err instanceof JWKSNoMatchingKey) { + if (this.coolingDown() === false) { + await this.reload(); + return super.getKey(protectedHeader, token); + } + } + throw err; + } + } + async reload() { + if (this._pendingFetch && isCloudflareWorkers()) { + return new Promise((resolve) => { + const isDone = () => { + if (this._pendingFetch === undefined) { + resolve(); + } + else { + setTimeout(isDone, 5); + } + }; + isDone(); + }); + } + if (!this._pendingFetch) { + this._pendingFetch = fetchJwks(this._url, this._timeoutDuration, this._options) + .then((json) => { + if (!isJWKSLike(json)) { + throw new JWKSInvalid('JSON Web Key Set malformed'); + } + this._jwks = { keys: json.keys }; + this._jwksTimestamp = Date.now(); + this._pendingFetch = undefined; + }) + .catch((err) => { + this._pendingFetch = undefined; + throw err; + }); + } + await this._pendingFetch; + } +} +export function createRemoteJWKSet(url, options) { + return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); +} diff --git a/dist/browser/jws/compact/sign.js b/dist/browser/jws/compact/sign.js new file mode 100644 index 0000000000..b8e5ba0e2b --- /dev/null +++ b/dist/browser/jws/compact/sign.js @@ -0,0 +1,17 @@ +import { FlattenedSign } from '../flattened/sign.js'; +export class CompactSign { + constructor(payload) { + this._flattened = new FlattenedSign(payload); + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + async sign(key, options) { + const jws = await this._flattened.sign(key, options); + if (jws.payload === undefined) { + throw new TypeError('use the flattened module for creating JWS with b64: false'); + } + return `${jws.protected}.${jws.payload}.${jws.signature}`; + } +} diff --git a/dist/browser/jws/compact/verify.js b/dist/browser/jws/compact/verify.js new file mode 100644 index 0000000000..c651ffb944 --- /dev/null +++ b/dist/browser/jws/compact/verify.js @@ -0,0 +1,21 @@ +import { flattenedVerify } from '../flattened/verify.js'; +import { JWSInvalid } from '../../util/errors.js'; +import { decoder } from '../../lib/buffer_utils.js'; +export async function compactVerify(jws, key, options) { + if (jws instanceof Uint8Array) { + jws = decoder.decode(jws); + } + if (typeof jws !== 'string') { + throw new JWSInvalid('Compact JWS must be a string or Uint8Array'); + } + const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.'); + if (length !== 3) { + throw new JWSInvalid('Invalid Compact JWS'); + } + const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); + const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: verified.key }; + } + return result; +} diff --git a/dist/browser/jws/flattened/sign.js b/dist/browser/jws/flattened/sign.js new file mode 100644 index 0000000000..76ae289654 --- /dev/null +++ b/dist/browser/jws/flattened/sign.js @@ -0,0 +1,81 @@ +import { encode as base64url } from '../../runtime/base64url.js'; +import sign from '../../runtime/sign.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import { JWSInvalid } from '../../util/errors.js'; +import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; +import checkKeyType from '../../lib/check_key_type.js'; +import validateCrit from '../../lib/validate_crit.js'; +export class FlattenedSign { + constructor(payload) { + if (!(payload instanceof Uint8Array)) { + throw new TypeError('payload must be an instance of Uint8Array'); + } + this._payload = payload; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + async sign(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader) { + throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); + } + if (!isDisjoint(this._protectedHeader, this._unprotectedHeader)) { + throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + }; + const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + let b64 = true; + if (extensions.has('b64')) { + b64 = this._protectedHeader.b64; + if (typeof b64 !== 'boolean') { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + checkKeyType(alg, key, 'sign'); + let payload = this._payload; + if (b64) { + payload = encoder.encode(base64url(payload)); + } + let protectedHeader; + if (this._protectedHeader) { + protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); + } + else { + protectedHeader = encoder.encode(''); + } + const data = concat(protectedHeader, encoder.encode('.'), payload); + const signature = await sign(alg, key, data); + const jws = { + signature: base64url(signature), + payload: '', + }; + if (b64) { + jws.payload = decoder.decode(payload); + } + if (this._unprotectedHeader) { + jws.header = this._unprotectedHeader; + } + if (this._protectedHeader) { + jws.protected = decoder.decode(protectedHeader); + } + return jws; + } +} diff --git a/dist/browser/jws/flattened/verify.js b/dist/browser/jws/flattened/verify.js new file mode 100644 index 0000000000..a55287ed8e --- /dev/null +++ b/dist/browser/jws/flattened/verify.js @@ -0,0 +1,104 @@ +import { decode as base64url } from '../../runtime/base64url.js'; +import verify from '../../runtime/verify.js'; +import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; +import { concat, encoder, decoder } from '../../lib/buffer_utils.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import isObject from '../../lib/is_object.js'; +import checkKeyType from '../../lib/check_key_type.js'; +import validateCrit from '../../lib/validate_crit.js'; +import validateAlgorithms from '../../lib/validate_algorithms.js'; +export async function flattenedVerify(jws, key, options) { + var _a; + if (!isObject(jws)) { + throw new JWSInvalid('Flattened JWS must be an object'); + } + if (jws.protected === undefined && jws.header === undefined) { + throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); + } + if (jws.protected !== undefined && typeof jws.protected !== 'string') { + throw new JWSInvalid('JWS Protected Header incorrect type'); + } + if (jws.payload === undefined) { + throw new JWSInvalid('JWS Payload missing'); + } + if (typeof jws.signature !== 'string') { + throw new JWSInvalid('JWS Signature missing or incorrect type'); + } + if (jws.header !== undefined && !isObject(jws.header)) { + throw new JWSInvalid('JWS Unprotected Header incorrect type'); + } + let parsedProt = {}; + if (jws.protected) { + try { + const protectedHeader = base64url(jws.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader)); + } + catch (_b) { + throw new JWSInvalid('JWS Protected Header is invalid'); + } + } + if (!isDisjoint(parsedProt, jws.header)) { + throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...parsedProt, + ...jws.header, + }; + const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + let b64 = true; + if (extensions.has('b64')) { + b64 = parsedProt.b64; + if (typeof b64 !== 'boolean') { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + const algorithms = options && validateAlgorithms('algorithms', options.algorithms); + if (algorithms && !algorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (b64) { + if (typeof jws.payload !== 'string') { + throw new JWSInvalid('JWS Payload must be a string'); + } + } + else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { + throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance'); + } + let resolvedKey = false; + if (typeof key === 'function') { + key = await key(parsedProt, jws); + resolvedKey = true; + } + checkKeyType(alg, key, 'verify'); + const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload); + const signature = base64url(jws.signature); + const verified = await verify(alg, key, signature, data); + if (!verified) { + throw new JWSSignatureVerificationFailed(); + } + let payload; + if (b64) { + payload = base64url(jws.payload); + } + else if (typeof jws.payload === 'string') { + payload = encoder.encode(jws.payload); + } + else { + payload = jws.payload; + } + const result = { payload }; + if (jws.protected !== undefined) { + result.protectedHeader = parsedProt; + } + if (jws.header !== undefined) { + result.unprotectedHeader = jws.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} diff --git a/dist/browser/jws/general/sign.js b/dist/browser/jws/general/sign.js new file mode 100644 index 0000000000..38d5a6d766 --- /dev/null +++ b/dist/browser/jws/general/sign.js @@ -0,0 +1,67 @@ +import { FlattenedSign } from '../flattened/sign.js'; +import { JWSInvalid } from '../../util/errors.js'; +class IndividualSignature { + constructor(sig, key, options) { + this.parent = sig; + this.key = key; + this.options = options; + } + setProtectedHeader(protectedHeader) { + if (this.protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this.protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addSignature(...args) { + return this.parent.addSignature(...args); + } + sign(...args) { + return this.parent.sign(...args); + } + done() { + return this.parent; + } +} +export class GeneralSign { + constructor(payload) { + this._signatures = []; + this._payload = payload; + } + addSignature(key, options) { + const signature = new IndividualSignature(this, key, options); + this._signatures.push(signature); + return signature; + } + async sign() { + if (!this._signatures.length) { + throw new JWSInvalid('at least one signature must be added'); + } + const jws = { + signatures: [], + payload: '', + }; + for (let i = 0; i < this._signatures.length; i++) { + const signature = this._signatures[i]; + const flattened = new FlattenedSign(this._payload); + flattened.setProtectedHeader(signature.protectedHeader); + flattened.setUnprotectedHeader(signature.unprotectedHeader); + const { payload, ...rest } = await flattened.sign(signature.key, signature.options); + if (i === 0) { + jws.payload = payload; + } + else if (jws.payload !== payload) { + throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)'); + } + jws.signatures.push(rest); + } + return jws; + } +} diff --git a/dist/browser/jws/general/verify.js b/dist/browser/jws/general/verify.js new file mode 100644 index 0000000000..459090afee --- /dev/null +++ b/dist/browser/jws/general/verify.js @@ -0,0 +1,24 @@ +import { flattenedVerify } from '../flattened/verify.js'; +import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; +import isObject from '../../lib/is_object.js'; +export async function generalVerify(jws, key, options) { + if (!isObject(jws)) { + throw new JWSInvalid('General JWS must be an object'); + } + if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { + throw new JWSInvalid('JWS Signatures missing or incorrect type'); + } + for (const signature of jws.signatures) { + try { + return await flattenedVerify({ + header: signature.header, + payload: jws.payload, + protected: signature.protected, + signature: signature.signature, + }, key, options); + } + catch (_a) { + } + } + throw new JWSSignatureVerificationFailed(); +} diff --git a/dist/browser/jwt/decrypt.js b/dist/browser/jwt/decrypt.js new file mode 100644 index 0000000000..1ec2be28f2 --- /dev/null +++ b/dist/browser/jwt/decrypt.js @@ -0,0 +1,23 @@ +import { compactDecrypt } from '../jwe/compact/decrypt.js'; +import jwtPayload from '../lib/jwt_claims_set.js'; +import { JWTClaimValidationFailed } from '../util/errors.js'; +export async function jwtDecrypt(jwt, key, options) { + const decrypted = await compactDecrypt(jwt, key, options); + const payload = jwtPayload(decrypted.protectedHeader, decrypted.plaintext, options); + const { protectedHeader } = decrypted; + if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { + throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', 'iss', 'mismatch'); + } + if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { + throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', 'sub', 'mismatch'); + } + if (protectedHeader.aud !== undefined && + JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { + throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch'); + } + const result = { payload, protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: decrypted.key }; + } + return result; +} diff --git a/dist/browser/jwt/encrypt.js b/dist/browser/jwt/encrypt.js new file mode 100644 index 0000000000..15252957ae --- /dev/null +++ b/dist/browser/jwt/encrypt.js @@ -0,0 +1,68 @@ +import { CompactEncrypt } from '../jwe/compact/encrypt.js'; +import { encoder } from '../lib/buffer_utils.js'; +import { ProduceJWT } from './produce.js'; +export class EncryptJWT extends ProduceJWT { + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once'); + } + this._keyManagementParameters = parameters; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once'); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once'); + } + this._iv = iv; + return this; + } + replicateIssuerAsHeader() { + this._replicateIssuerAsHeader = true; + return this; + } + replicateSubjectAsHeader() { + this._replicateSubjectAsHeader = true; + return this; + } + replicateAudienceAsHeader() { + this._replicateAudienceAsHeader = true; + return this; + } + async encrypt(key, options) { + const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); + if (this._replicateIssuerAsHeader) { + this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; + } + if (this._replicateSubjectAsHeader) { + this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; + } + if (this._replicateAudienceAsHeader) { + this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; + } + enc.setProtectedHeader(this._protectedHeader); + if (this._iv) { + enc.setInitializationVector(this._iv); + } + if (this._cek) { + enc.setContentEncryptionKey(this._cek); + } + if (this._keyManagementParameters) { + enc.setKeyManagementParameters(this._keyManagementParameters); + } + return enc.encrypt(key, options); + } +} diff --git a/dist/browser/jwt/produce.js b/dist/browser/jwt/produce.js new file mode 100644 index 0000000000..31c929a07c --- /dev/null +++ b/dist/browser/jwt/produce.js @@ -0,0 +1,54 @@ +import epoch from '../lib/epoch.js'; +import isObject from '../lib/is_object.js'; +import secs from '../lib/secs.js'; +export class ProduceJWT { + constructor(payload) { + if (!isObject(payload)) { + throw new TypeError('JWT Claims Set MUST be an object'); + } + this._payload = payload; + } + setIssuer(issuer) { + this._payload = { ...this._payload, iss: issuer }; + return this; + } + setSubject(subject) { + this._payload = { ...this._payload, sub: subject }; + return this; + } + setAudience(audience) { + this._payload = { ...this._payload, aud: audience }; + return this; + } + setJti(jwtId) { + this._payload = { ...this._payload, jti: jwtId }; + return this; + } + setNotBefore(input) { + if (typeof input === 'number') { + this._payload = { ...this._payload, nbf: input }; + } + else { + this._payload = { ...this._payload, nbf: epoch(new Date()) + secs(input) }; + } + return this; + } + setExpirationTime(input) { + if (typeof input === 'number') { + this._payload = { ...this._payload, exp: input }; + } + else { + this._payload = { ...this._payload, exp: epoch(new Date()) + secs(input) }; + } + return this; + } + setIssuedAt(input) { + if (typeof input === 'undefined') { + this._payload = { ...this._payload, iat: epoch(new Date()) }; + } + else { + this._payload = { ...this._payload, iat: input }; + } + return this; + } +} diff --git a/dist/browser/jwt/sign.js b/dist/browser/jwt/sign.js new file mode 100644 index 0000000000..62352fbfa2 --- /dev/null +++ b/dist/browser/jwt/sign.js @@ -0,0 +1,21 @@ +import { CompactSign } from '../jws/compact/sign.js'; +import { JWTInvalid } from '../util/errors.js'; +import { encoder } from '../lib/buffer_utils.js'; +import { ProduceJWT } from './produce.js'; +export class SignJWT extends ProduceJWT { + setProtectedHeader(protectedHeader) { + this._protectedHeader = protectedHeader; + return this; + } + async sign(key, options) { + var _a; + const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); + sig.setProtectedHeader(this._protectedHeader); + if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && + this._protectedHeader.crit.includes('b64') && + this._protectedHeader.b64 === false) { + throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); + } + return sig.sign(key, options); + } +} diff --git a/dist/browser/jwt/unsecured.js b/dist/browser/jwt/unsecured.js new file mode 100644 index 0000000000..b0276512fb --- /dev/null +++ b/dist/browser/jwt/unsecured.js @@ -0,0 +1,32 @@ +import * as base64url from '../runtime/base64url.js'; +import { decoder } from '../lib/buffer_utils.js'; +import { JWTInvalid } from '../util/errors.js'; +import jwtPayload from '../lib/jwt_claims_set.js'; +import { ProduceJWT } from './produce.js'; +export class UnsecuredJWT extends ProduceJWT { + encode() { + const header = base64url.encode(JSON.stringify({ alg: 'none' })); + const payload = base64url.encode(JSON.stringify(this._payload)); + return `${header}.${payload}.`; + } + static decode(jwt, options) { + if (typeof jwt !== 'string') { + throw new JWTInvalid('Unsecured JWT must be a string'); + } + const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.'); + if (length !== 3 || signature !== '') { + throw new JWTInvalid('Invalid Unsecured JWT'); + } + let header; + try { + header = JSON.parse(decoder.decode(base64url.decode(encodedHeader))); + if (header.alg !== 'none') + throw new Error(); + } + catch (_a) { + throw new JWTInvalid('Invalid Unsecured JWT'); + } + const payload = jwtPayload(header, base64url.decode(encodedPayload), options); + return { payload, header }; + } +} diff --git a/dist/browser/jwt/verify.js b/dist/browser/jwt/verify.js new file mode 100644 index 0000000000..89571c1847 --- /dev/null +++ b/dist/browser/jwt/verify.js @@ -0,0 +1,16 @@ +import { compactVerify } from '../jws/compact/verify.js'; +import jwtPayload from '../lib/jwt_claims_set.js'; +import { JWTInvalid } from '../util/errors.js'; +export async function jwtVerify(jwt, key, options) { + var _a; + const verified = await compactVerify(jwt, key, options); + if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { + throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); + } + const payload = jwtPayload(verified.protectedHeader, verified.payload, options); + const result = { payload, protectedHeader: verified.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: verified.key }; + } + return result; +} diff --git a/dist/browser/key/export.js b/dist/browser/key/export.js new file mode 100644 index 0000000000..e4017047cd --- /dev/null +++ b/dist/browser/key/export.js @@ -0,0 +1,12 @@ +import { toSPKI as exportPublic } from '../runtime/asn1.js'; +import { toPKCS8 as exportPrivate } from '../runtime/asn1.js'; +import keyToJWK from '../runtime/key_to_jwk.js'; +export async function exportSPKI(key) { + return exportPublic(key); +} +export async function exportPKCS8(key) { + return exportPrivate(key); +} +export async function exportJWK(key) { + return keyToJWK(key); +} diff --git a/dist/browser/key/generate_key_pair.js b/dist/browser/key/generate_key_pair.js new file mode 100644 index 0000000000..03b9ee54cd --- /dev/null +++ b/dist/browser/key/generate_key_pair.js @@ -0,0 +1,4 @@ +import { generateKeyPair as generate } from '../runtime/generate.js'; +export async function generateKeyPair(alg, options) { + return generate(alg, options); +} diff --git a/dist/browser/key/generate_secret.js b/dist/browser/key/generate_secret.js new file mode 100644 index 0000000000..58f308a543 --- /dev/null +++ b/dist/browser/key/generate_secret.js @@ -0,0 +1,4 @@ +import { generateSecret as generate } from '../runtime/generate.js'; +export async function generateSecret(alg, options) { + return generate(alg, options); +} diff --git a/dist/browser/key/import.js b/dist/browser/key/import.js new file mode 100644 index 0000000000..25bb0e1659 --- /dev/null +++ b/dist/browser/key/import.js @@ -0,0 +1,50 @@ +import { decode as decodeBase64URL } from '../runtime/base64url.js'; +import { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.js'; +import asKeyObject from '../runtime/jwk_to_key.js'; +import { JOSENotSupported } from '../util/errors.js'; +import isObject from '../lib/is_object.js'; +export async function importSPKI(spki, alg, options) { + if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { + throw new TypeError('"spki" must be SPKI formatted string'); + } + return fromSPKI(spki, alg, options); +} +export async function importX509(x509, alg, options) { + if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { + throw new TypeError('"x509" must be X.509 formatted string'); + } + return fromX509(x509, alg, options); +} +export async function importPKCS8(pkcs8, alg, options) { + if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { + throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); + } + return fromPKCS8(pkcs8, alg, options); +} +export async function importJWK(jwk, alg, octAsKeyObject) { + var _a; + if (!isObject(jwk)) { + throw new TypeError('JWK must be an object'); + } + alg || (alg = jwk.alg); + switch (jwk.kty) { + case 'oct': + if (typeof jwk.k !== 'string' || !jwk.k) { + throw new TypeError('missing "k" (Key Value) Parameter value'); + } + octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true); + if (octAsKeyObject) { + return asKeyObject({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); + } + return decodeBase64URL(jwk.k); + case 'RSA': + if (jwk.oth !== undefined) { + throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); + } + case 'EC': + case 'OKP': + return asKeyObject({ ...jwk, alg }); + default: + throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); + } +} diff --git a/dist/browser/lib/aesgcmkw.js b/dist/browser/lib/aesgcmkw.js new file mode 100644 index 0000000000..de3f4f91df --- /dev/null +++ b/dist/browser/lib/aesgcmkw.js @@ -0,0 +1,14 @@ +import encrypt from '../runtime/encrypt.js'; +import decrypt from '../runtime/decrypt.js'; +import generateIv from './iv.js'; +import { encode as base64url } from '../runtime/base64url.js'; +export async function wrap(alg, key, cek, iv) { + const jweAlgorithm = alg.slice(0, 7); + iv || (iv = generateIv(jweAlgorithm)); + const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0)); + return { encryptedKey, iv: base64url(iv), tag: base64url(tag) }; +} +export async function unwrap(alg, key, encryptedKey, iv, tag) { + const jweAlgorithm = alg.slice(0, 7); + return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); +} diff --git a/dist/browser/lib/buffer_utils.js b/dist/browser/lib/buffer_utils.js new file mode 100644 index 0000000000..5a1a7b334d --- /dev/null +++ b/dist/browser/lib/buffer_utils.js @@ -0,0 +1,51 @@ +import digest from '../runtime/digest.js'; +export const encoder = new TextEncoder(); +export const decoder = new TextDecoder(); +const MAX_INT32 = 2 ** 32; +export function concat(...buffers) { + const size = buffers.reduce((acc, { length }) => acc + length, 0); + const buf = new Uint8Array(size); + let i = 0; + buffers.forEach((buffer) => { + buf.set(buffer, i); + i += buffer.length; + }); + return buf; +} +export function p2s(alg, p2sInput) { + return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); +} +function writeUInt32BE(buf, value, offset) { + if (value < 0 || value >= MAX_INT32) { + throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); + } + buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset); +} +export function uint64be(value) { + const high = Math.floor(value / MAX_INT32); + const low = value % MAX_INT32; + const buf = new Uint8Array(8); + writeUInt32BE(buf, high, 0); + writeUInt32BE(buf, low, 4); + return buf; +} +export function uint32be(value) { + const buf = new Uint8Array(4); + writeUInt32BE(buf, value); + return buf; +} +export function lengthAndInput(input) { + return concat(uint32be(input.length), input); +} +export async function concatKdf(secret, bits, value) { + const iterations = Math.ceil((bits >> 3) / 32); + const res = new Uint8Array(iterations * 32); + for (let iter = 0; iter < iterations; iter++) { + const buf = new Uint8Array(4 + secret.length + value.length); + buf.set(uint32be(iter + 1)); + buf.set(secret, 4); + buf.set(value, 4 + secret.length); + res.set(await digest('sha256', buf), iter * 32); + } + return res.slice(0, bits >> 3); +} diff --git a/dist/browser/lib/cek.js b/dist/browser/lib/cek.js new file mode 100644 index 0000000000..34697d3ac2 --- /dev/null +++ b/dist/browser/lib/cek.js @@ -0,0 +1,20 @@ +import { JOSENotSupported } from '../util/errors.js'; +import random from '../runtime/random.js'; +export function bitLength(alg) { + switch (alg) { + case 'A128GCM': + return 128; + case 'A192GCM': + return 192; + case 'A256GCM': + case 'A128CBC-HS256': + return 256; + case 'A192CBC-HS384': + return 384; + case 'A256CBC-HS512': + return 512; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/browser/lib/check_iv_length.js b/dist/browser/lib/check_iv_length.js new file mode 100644 index 0000000000..dcd28d3a9d --- /dev/null +++ b/dist/browser/lib/check_iv_length.js @@ -0,0 +1,8 @@ +import { JWEInvalid } from '../util/errors.js'; +import { bitLength } from './iv.js'; +const checkIvLength = (enc, iv) => { + if (iv.length << 3 !== bitLength(enc)) { + throw new JWEInvalid('Invalid Initialization Vector length'); + } +}; +export default checkIvLength; diff --git a/dist/browser/lib/check_key_type.js b/dist/browser/lib/check_key_type.js new file mode 100644 index 0000000000..43f3dcbf14 --- /dev/null +++ b/dist/browser/lib/check_key_type.js @@ -0,0 +1,45 @@ +import { withAlg as invalidKeyInput } from './invalid_key_input.js'; +import isKeyLike, { types } from '../runtime/is_key_like.js'; +const symmetricTypeCheck = (alg, key) => { + if (key instanceof Uint8Array) + return; + if (!isKeyLike(key)) { + throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array')); + } + if (key.type !== 'secret') { + throw new TypeError(`${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`); + } +}; +const asymmetricTypeCheck = (alg, key, usage) => { + if (!isKeyLike(key)) { + throw new TypeError(invalidKeyInput(alg, key, ...types)); + } + if (key.type === 'secret') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`); + } + if (usage === 'sign' && key.type === 'public') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`); + } + if (usage === 'decrypt' && key.type === 'public') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`); + } + if (key.algorithm && usage === 'verify' && key.type === 'private') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`); + } + if (key.algorithm && usage === 'encrypt' && key.type === 'private') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`); + } +}; +const checkKeyType = (alg, key, usage) => { + const symmetric = alg.startsWith('HS') || + alg === 'dir' || + alg.startsWith('PBES2') || + /^A\d{3}(?:GCM)?KW$/.test(alg); + if (symmetric) { + symmetricTypeCheck(alg, key); + } + else { + asymmetricTypeCheck(alg, key, usage); + } +}; +export default checkKeyType; diff --git a/dist/browser/lib/check_p2s.js b/dist/browser/lib/check_p2s.js new file mode 100644 index 0000000000..a65289fa7a --- /dev/null +++ b/dist/browser/lib/check_p2s.js @@ -0,0 +1,6 @@ +import { JWEInvalid } from '../util/errors.js'; +export default function checkP2s(p2s) { + if (!(p2s instanceof Uint8Array) || p2s.length < 8) { + throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets'); + } +} diff --git a/dist/browser/lib/crypto_key.js b/dist/browser/lib/crypto_key.js new file mode 100644 index 0000000000..4405b1915c --- /dev/null +++ b/dist/browser/lib/crypto_key.js @@ -0,0 +1,158 @@ +import { isCloudflareWorkers } from '../runtime/env.js'; +function unusable(name, prop = 'algorithm.name') { + return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); +} +function isAlgorithm(algorithm, name) { + return algorithm.name === name; +} +function getHashLength(hash) { + return parseInt(hash.name.slice(4), 10); +} +function getNamedCurve(alg) { + switch (alg) { + case 'ES256': + return 'P-256'; + case 'ES384': + return 'P-384'; + case 'ES512': + return 'P-521'; + default: + throw new Error('unreachable'); + } +} +function checkUsage(key, usages) { + if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { + let msg = 'CryptoKey does not support this operation, its usages must include '; + if (usages.length > 2) { + const last = usages.pop(); + msg += `one of ${usages.join(', ')}, or ${last}.`; + } + else if (usages.length === 2) { + msg += `one of ${usages[0]} or ${usages[1]}.`; + } + else { + msg += `${usages[0]}.`; + } + throw new TypeError(msg); + } +} +export function checkSigCryptoKey(key, alg, ...usages) { + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': { + if (!isAlgorithm(key.algorithm, 'HMAC')) + throw unusable('HMAC'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'RS256': + case 'RS384': + case 'RS512': { + if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) + throw unusable('RSASSA-PKCS1-v1_5'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'PS256': + case 'PS384': + case 'PS512': { + if (!isAlgorithm(key.algorithm, 'RSA-PSS')) + throw unusable('RSA-PSS'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'EdDSA': { + if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { + if (isCloudflareWorkers()) { + if (isAlgorithm(key.algorithm, 'NODE-ED25519')) + break; + throw unusable('Ed25519, Ed448, or NODE-ED25519'); + } + throw unusable('Ed25519 or Ed448'); + } + break; + } + case 'ES256': + case 'ES384': + case 'ES512': { + if (!isAlgorithm(key.algorithm, 'ECDSA')) + throw unusable('ECDSA'); + const expected = getNamedCurve(alg); + const actual = key.algorithm.namedCurve; + if (actual !== expected) + throw unusable(expected, 'algorithm.namedCurve'); + break; + } + default: + throw new TypeError('CryptoKey does not support this operation'); + } + checkUsage(key, usages); +} +export function checkEncCryptoKey(key, alg, ...usages) { + switch (alg) { + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': { + if (!isAlgorithm(key.algorithm, 'AES-GCM')) + throw unusable('AES-GCM'); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, 'algorithm.length'); + break; + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + if (!isAlgorithm(key.algorithm, 'AES-KW')) + throw unusable('AES-KW'); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, 'algorithm.length'); + break; + } + case 'ECDH': { + switch (key.algorithm.name) { + case 'ECDH': + case 'X25519': + case 'X448': + break; + default: + throw unusable('ECDH, X25519, or X448'); + } + break; + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': + if (!isAlgorithm(key.algorithm, 'PBKDF2')) + throw unusable('PBKDF2'); + break; + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) + throw unusable('RSA-OAEP'); + const expected = parseInt(alg.slice(9), 10) || 1; + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + default: + throw new TypeError('CryptoKey does not support this operation'); + } + checkUsage(key, usages); +} diff --git a/dist/browser/lib/decrypt_key_management.js b/dist/browser/lib/decrypt_key_management.js new file mode 100644 index 0000000000..87890a4fa0 --- /dev/null +++ b/dist/browser/lib/decrypt_key_management.js @@ -0,0 +1,98 @@ +import { unwrap as aesKw } from '../runtime/aeskw.js'; +import * as ECDH from '../runtime/ecdhes.js'; +import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js'; +import { decrypt as rsaEs } from '../runtime/rsaes.js'; +import { decode as base64url } from '../runtime/base64url.js'; +import { JOSENotSupported, JWEInvalid } from '../util/errors.js'; +import { bitLength as cekLength } from '../lib/cek.js'; +import { importJWK } from '../key/import.js'; +import checkKeyType from './check_key_type.js'; +import isObject from './is_object.js'; +import { unwrap as aesGcmKw } from './aesgcmkw.js'; +async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { + checkKeyType(alg, key, 'decrypt'); + switch (alg) { + case 'dir': { + if (encryptedKey !== undefined) + throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); + return key; + } + case 'ECDH-ES': + if (encryptedKey !== undefined) + throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + if (!isObject(joseHeader.epk)) + throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); + if (!ECDH.ecdhAllowed(key)) + throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); + const epk = await importJWK(joseHeader.epk, alg); + let partyUInfo; + let partyVInfo; + if (joseHeader.apu !== undefined) { + if (typeof joseHeader.apu !== 'string') + throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); + partyUInfo = base64url(joseHeader.apu); + } + if (joseHeader.apv !== undefined) { + if (typeof joseHeader.apv !== 'string') + throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); + partyVInfo = base64url(joseHeader.apv); + } + const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); + if (alg === 'ECDH-ES') + return sharedSecret; + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + return aesKw(alg.slice(-6), sharedSecret, encryptedKey); + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + return rsaEs(alg, key, encryptedKey); + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + if (typeof joseHeader.p2c !== 'number') + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); + const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 10000; + if (joseHeader.p2c > p2cLimit) + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); + if (typeof joseHeader.p2s !== 'string') + throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); + return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s)); + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + return aesKw(alg, key, encryptedKey); + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + if (typeof joseHeader.iv !== 'string') + throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); + if (typeof joseHeader.tag !== 'string') + throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); + const iv = base64url(joseHeader.iv); + const tag = base64url(joseHeader.tag); + return aesGcmKw(alg, key, encryptedKey, iv, tag); + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } +} +export default decryptKeyManagement; diff --git a/dist/browser/lib/encrypt_key_management.js b/dist/browser/lib/encrypt_key_management.js new file mode 100644 index 0000000000..eb9022c63e --- /dev/null +++ b/dist/browser/lib/encrypt_key_management.js @@ -0,0 +1,87 @@ +import { wrap as aesKw } from '../runtime/aeskw.js'; +import * as ECDH from '../runtime/ecdhes.js'; +import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js'; +import { encrypt as rsaEs } from '../runtime/rsaes.js'; +import { encode as base64url } from '../runtime/base64url.js'; +import generateCek, { bitLength as cekLength } from '../lib/cek.js'; +import { JOSENotSupported } from '../util/errors.js'; +import { exportJWK } from '../key/export.js'; +import checkKeyType from './check_key_type.js'; +import { wrap as aesGcmKw } from './aesgcmkw.js'; +async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { + let encryptedKey; + let parameters; + let cek; + checkKeyType(alg, key, 'encrypt'); + switch (alg) { + case 'dir': { + cek = key; + break; + } + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + if (!ECDH.ecdhAllowed(key)) { + throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); + } + const { apu, apv } = providedParameters; + let { epk: ephemeralKey } = providedParameters; + ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey); + const { x, y, crv, kty } = await exportJWK(ephemeralKey); + const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); + parameters = { epk: { x, crv, kty } }; + if (kty === 'EC') + parameters.epk.y = y; + if (apu) + parameters.apu = base64url(apu); + if (apv) + parameters.apv = base64url(apv); + if (alg === 'ECDH-ES') { + cek = sharedSecret; + break; + } + cek = providedCek || generateCek(enc); + const kwAlg = alg.slice(-6); + encryptedKey = await aesKw(kwAlg, sharedSecret, cek); + break; + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + cek = providedCek || generateCek(enc); + encryptedKey = await rsaEs(alg, key, cek); + break; + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + cek = providedCek || generateCek(enc); + const { p2c, p2s } = providedParameters; + ({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s)); + break; + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + cek = providedCek || generateCek(enc); + encryptedKey = await aesKw(alg, key, cek); + break; + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + cek = providedCek || generateCek(enc); + const { iv } = providedParameters; + ({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv)); + break; + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } + return { cek, encryptedKey, parameters }; +} +export default encryptKeyManagement; diff --git a/dist/browser/lib/epoch.js b/dist/browser/lib/epoch.js new file mode 100644 index 0000000000..e405e4b2df --- /dev/null +++ b/dist/browser/lib/epoch.js @@ -0,0 +1 @@ +export default (date) => Math.floor(date.getTime() / 1000); diff --git a/dist/browser/lib/format_pem.js b/dist/browser/lib/format_pem.js new file mode 100644 index 0000000000..81673f256f --- /dev/null +++ b/dist/browser/lib/format_pem.js @@ -0,0 +1,4 @@ +export default (b64, descriptor) => { + const newlined = (b64.match(/.{1,64}/g) || []).join('\n'); + return `-----BEGIN ${descriptor}-----\n${newlined}\n-----END ${descriptor}-----`; +}; diff --git a/dist/browser/lib/invalid_key_input.js b/dist/browser/lib/invalid_key_input.js new file mode 100644 index 0000000000..049e66ece0 --- /dev/null +++ b/dist/browser/lib/invalid_key_input.js @@ -0,0 +1,30 @@ +function message(msg, actual, ...types) { + if (types.length > 2) { + const last = types.pop(); + msg += `one of type ${types.join(', ')}, or ${last}.`; + } + else if (types.length === 2) { + msg += `one of type ${types[0]} or ${types[1]}.`; + } + else { + msg += `of type ${types[0]}.`; + } + if (actual == null) { + msg += ` Received ${actual}`; + } + else if (typeof actual === 'function' && actual.name) { + msg += ` Received function ${actual.name}`; + } + else if (typeof actual === 'object' && actual != null) { + if (actual.constructor && actual.constructor.name) { + msg += ` Received an instance of ${actual.constructor.name}`; + } + } + return msg; +} +export default (actual, ...types) => { + return message('Key must be ', actual, ...types); +}; +export function withAlg(alg, actual, ...types) { + return message(`Key for the ${alg} algorithm must be `, actual, ...types); +} diff --git a/dist/browser/lib/is_disjoint.js b/dist/browser/lib/is_disjoint.js new file mode 100644 index 0000000000..6f643502dc --- /dev/null +++ b/dist/browser/lib/is_disjoint.js @@ -0,0 +1,22 @@ +const isDisjoint = (...headers) => { + const sources = headers.filter(Boolean); + if (sources.length === 0 || sources.length === 1) { + return true; + } + let acc; + for (const header of sources) { + const parameters = Object.keys(header); + if (!acc || acc.size === 0) { + acc = new Set(parameters); + continue; + } + for (const parameter of parameters) { + if (acc.has(parameter)) { + return false; + } + acc.add(parameter); + } + } + return true; +}; +export default isDisjoint; diff --git a/dist/browser/lib/is_object.js b/dist/browser/lib/is_object.js new file mode 100644 index 0000000000..4955e93225 --- /dev/null +++ b/dist/browser/lib/is_object.js @@ -0,0 +1,16 @@ +function isObjectLike(value) { + return typeof value === 'object' && value !== null; +} +export default function isObject(input) { + if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { + return false; + } + if (Object.getPrototypeOf(input) === null) { + return true; + } + let proto = input; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + return Object.getPrototypeOf(input) === proto; +} diff --git a/dist/browser/lib/iv.js b/dist/browser/lib/iv.js new file mode 100644 index 0000000000..cab2a12729 --- /dev/null +++ b/dist/browser/lib/iv.js @@ -0,0 +1,20 @@ +import { JOSENotSupported } from '../util/errors.js'; +import random from '../runtime/random.js'; +export function bitLength(alg) { + switch (alg) { + case 'A128GCM': + case 'A128GCMKW': + case 'A192GCM': + case 'A192GCMKW': + case 'A256GCM': + case 'A256GCMKW': + return 96; + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return 128; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/browser/lib/jwt_claims_set.js b/dist/browser/lib/jwt_claims_set.js new file mode 100644 index 0000000000..e9e2f1944f --- /dev/null +++ b/dist/browser/lib/jwt_claims_set.js @@ -0,0 +1,91 @@ +import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js'; +import { decoder } from './buffer_utils.js'; +import epoch from './epoch.js'; +import secs from './secs.js'; +import isObject from './is_object.js'; +const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ''); +const checkAudiencePresence = (audPayload, audOption) => { + if (typeof audPayload === 'string') { + return audOption.includes(audPayload); + } + if (Array.isArray(audPayload)) { + return audOption.some(Set.prototype.has.bind(new Set(audPayload))); + } + return false; +}; +export default (protectedHeader, encodedPayload, options = {}) => { + const { typ } = options; + if (typ && + (typeof protectedHeader.typ !== 'string' || + normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { + throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed'); + } + let payload; + try { + payload = JSON.parse(decoder.decode(encodedPayload)); + } + catch (_a) { + } + if (!isObject(payload)) { + throw new JWTInvalid('JWT Claims Set must be a top-level JSON object'); + } + const { issuer } = options; + if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { + throw new JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed'); + } + const { subject } = options; + if (subject && payload.sub !== subject) { + throw new JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed'); + } + const { audience } = options; + if (audience && + !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) { + throw new JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed'); + } + let tolerance; + switch (typeof options.clockTolerance) { + case 'string': + tolerance = secs(options.clockTolerance); + break; + case 'number': + tolerance = options.clockTolerance; + break; + case 'undefined': + tolerance = 0; + break; + default: + throw new TypeError('Invalid clockTolerance option type'); + } + const { currentDate } = options; + const now = epoch(currentDate || new Date()); + if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { + throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid'); + } + if (payload.nbf !== undefined) { + if (typeof payload.nbf !== 'number') { + throw new JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid'); + } + if (payload.nbf > now + tolerance) { + throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', 'nbf', 'check_failed'); + } + } + if (payload.exp !== undefined) { + if (typeof payload.exp !== 'number') { + throw new JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid'); + } + if (payload.exp <= now - tolerance) { + throw new JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed'); + } + } + if (options.maxTokenAge) { + const age = now - payload.iat; + const max = typeof options.maxTokenAge === 'number' ? options.maxTokenAge : secs(options.maxTokenAge); + if (age - tolerance > max) { + throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', 'iat', 'check_failed'); + } + if (age < 0 - tolerance) { + throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed'); + } + } + return payload; +}; diff --git a/dist/browser/lib/secs.js b/dist/browser/lib/secs.js new file mode 100644 index 0000000000..cf470ed8ad --- /dev/null +++ b/dist/browser/lib/secs.js @@ -0,0 +1,44 @@ +const minute = 60; +const hour = minute * 60; +const day = hour * 24; +const week = day * 7; +const year = day * 365.25; +const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; +export default (str) => { + const matched = REGEX.exec(str); + if (!matched) { + throw new TypeError('Invalid time period format'); + } + const value = parseFloat(matched[1]); + const unit = matched[2].toLowerCase(); + switch (unit) { + case 'sec': + case 'secs': + case 'second': + case 'seconds': + case 's': + return Math.round(value); + case 'minute': + case 'minutes': + case 'min': + case 'mins': + case 'm': + return Math.round(value * minute); + case 'hour': + case 'hours': + case 'hr': + case 'hrs': + case 'h': + return Math.round(value * hour); + case 'day': + case 'days': + case 'd': + return Math.round(value * day); + case 'week': + case 'weeks': + case 'w': + return Math.round(value * week); + default: + return Math.round(value * year); + } +}; diff --git a/dist/browser/lib/validate_algorithms.js b/dist/browser/lib/validate_algorithms.js new file mode 100644 index 0000000000..a6a7918571 --- /dev/null +++ b/dist/browser/lib/validate_algorithms.js @@ -0,0 +1,11 @@ +const validateAlgorithms = (option, algorithms) => { + if (algorithms !== undefined && + (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) { + throw new TypeError(`"${option}" option must be an array of strings`); + } + if (!algorithms) { + return undefined; + } + return new Set(algorithms); +}; +export default validateAlgorithms; diff --git a/dist/browser/lib/validate_crit.js b/dist/browser/lib/validate_crit.js new file mode 100644 index 0000000000..68c69f18f5 --- /dev/null +++ b/dist/browser/lib/validate_crit.js @@ -0,0 +1,34 @@ +import { JOSENotSupported } from '../util/errors.js'; +function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { + if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { + throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); + } + if (!protectedHeader || protectedHeader.crit === undefined) { + return new Set(); + } + if (!Array.isArray(protectedHeader.crit) || + protectedHeader.crit.length === 0 || + protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) { + throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); + } + let recognized; + if (recognizedOption !== undefined) { + recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); + } + else { + recognized = recognizedDefault; + } + for (const parameter of protectedHeader.crit) { + if (!recognized.has(parameter)) { + throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); + } + if (joseHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" is missing`); + } + else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); + } + } + return new Set(protectedHeader.crit); +} +export default validateCrit; diff --git a/dist/browser/package.json b/dist/browser/package.json new file mode 100644 index 0000000000..6990891ff3 --- /dev/null +++ b/dist/browser/package.json @@ -0,0 +1 @@ +{"type": "module"} diff --git a/dist/browser/runtime/aeskw.js b/dist/browser/runtime/aeskw.js new file mode 100644 index 0000000000..bb7dff8a5b --- /dev/null +++ b/dist/browser/runtime/aeskw.js @@ -0,0 +1,32 @@ +import bogusWebCrypto from './bogus.js'; +import crypto, { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +function checkKeySize(key, alg) { + if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) { + throw new TypeError(`Invalid key size for alg: ${alg}`); + } +} +function getCryptoKey(key, alg, usage) { + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, usage); + return key; + } + if (key instanceof Uint8Array) { + return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]); + } + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); +} +export const wrap = async (alg, key, cek) => { + const cryptoKey = await getCryptoKey(key, alg, 'wrapKey'); + checkKeySize(cryptoKey, alg); + const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto); + return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, cryptoKey, 'AES-KW')); +}; +export const unwrap = async (alg, key, encryptedKey) => { + const cryptoKey = await getCryptoKey(key, alg, 'unwrapKey'); + checkKeySize(cryptoKey, alg); + const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, cryptoKey, 'AES-KW', ...bogusWebCrypto); + return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)); +}; diff --git a/dist/browser/runtime/asn1.js b/dist/browser/runtime/asn1.js new file mode 100644 index 0000000000..ba617f649a --- /dev/null +++ b/dist/browser/runtime/asn1.js @@ -0,0 +1,214 @@ +import { isCloudflareWorkers } from './env.js'; +import crypto, { isCryptoKey } from './webcrypto.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { encodeBase64, decodeBase64 } from './base64url.js'; +import formatPEM from '../lib/format_pem.js'; +import { JOSENotSupported } from '../util/errors.js'; +import { types } from './is_key_like.js'; +const genericExport = async (keyType, keyFormat, key) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)); + } + if (!key.extractable) { + throw new TypeError('CryptoKey is not extractable'); + } + if (key.type !== keyType) { + throw new TypeError(`key is not a ${keyType} key`); + } + return formatPEM(encodeBase64(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`); +}; +export const toSPKI = (key) => { + return genericExport('public', 'spki', key); +}; +export const toPKCS8 = (key) => { + return genericExport('private', 'pkcs8', key); +}; +const findOid = (keyData, oid, from = 0) => { + if (from === 0) { + oid.unshift(oid.length); + oid.unshift(0x06); + } + let i = keyData.indexOf(oid[0], from); + if (i === -1) + return false; + const sub = keyData.subarray(i, i + oid.length); + if (sub.length !== oid.length) + return false; + return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1); +}; +const getNamedCurve = (keyData) => { + switch (true) { + case findOid(keyData, [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]): + return 'P-256'; + case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x22]): + return 'P-384'; + case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]): + return 'P-521'; + case findOid(keyData, [0x2b, 0x65, 0x6e]): + return 'X25519'; + case findOid(keyData, [0x2b, 0x65, 0x6f]): + return 'X448'; + case findOid(keyData, [0x2b, 0x65, 0x70]): + return 'Ed25519'; + case findOid(keyData, [0x2b, 0x65, 0x71]): + return 'Ed448'; + default: + throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type'); + } +}; +const genericImport = async (replace, keyFormat, pem, alg, options) => { + var _a, _b; + let algorithm; + let keyUsages; + const keyData = new Uint8Array(atob(pem.replace(replace, '')) + .split('') + .map((c) => c.charCodeAt(0))); + const isPublic = keyFormat === 'spki'; + switch (alg) { + case 'PS256': + case 'PS384': + case 'PS512': + algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` }; + keyUsages = isPublic ? ['verify'] : ['sign']; + break; + case 'RS256': + case 'RS384': + case 'RS512': + algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` }; + keyUsages = isPublic ? ['verify'] : ['sign']; + break; + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + algorithm = { + name: 'RSA-OAEP', + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, + }; + keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey']; + break; + case 'ES256': + algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; + keyUsages = isPublic ? ['verify'] : ['sign']; + break; + case 'ES384': + algorithm = { name: 'ECDSA', namedCurve: 'P-384' }; + keyUsages = isPublic ? ['verify'] : ['sign']; + break; + case 'ES512': + algorithm = { name: 'ECDSA', namedCurve: 'P-521' }; + keyUsages = isPublic ? ['verify'] : ['sign']; + break; + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + const namedCurve = getNamedCurve(keyData); + algorithm = namedCurve.startsWith('P-') ? { name: 'ECDH', namedCurve } : { name: namedCurve }; + keyUsages = isPublic ? [] : ['deriveBits']; + break; + } + case 'EdDSA': + algorithm = { name: getNamedCurve(keyData) }; + keyUsages = isPublic ? ['verify'] : ['sign']; + break; + default: + throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value'); + } + try { + return await crypto.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); + } + catch (err) { + if (algorithm.name === 'Ed25519' && + (err === null || err === void 0 ? void 0 : err.name) === 'NotSupportedError' && + isCloudflareWorkers()) { + algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; + return await crypto.subtle.importKey(keyFormat, keyData, algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages); + } + throw err; + } +}; +export const fromPKCS8 = (pem, alg, options) => { + return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options); +}; +export const fromSPKI = (pem, alg, options) => { + return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, 'spki', pem, alg, options); +}; +function getElement(seq) { + let result = []; + let next = 0; + while (next < seq.length) { + let nextPart = parseElement(seq.subarray(next)); + result.push(nextPart); + next += nextPart.byteLength; + } + return result; +} +function parseElement(bytes) { + let position = 0; + let tag = bytes[0] & 0x1f; + position++; + if (tag === 0x1f) { + tag = 0; + while (bytes[position] >= 0x80) { + tag = tag * 128 + bytes[position] - 0x80; + position++; + } + tag = tag * 128 + bytes[position] - 0x80; + position++; + } + let length = 0; + if (bytes[position] < 0x80) { + length = bytes[position]; + position++; + } + else if (length === 0x80) { + length = 0; + while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { + if (length > bytes.byteLength) { + throw new TypeError('invalid indefinite form length'); + } + length++; + } + const byteLength = position + length + 2; + return { + byteLength, + contents: bytes.subarray(position, position + length), + raw: bytes.subarray(0, byteLength), + }; + } + else { + let numberOfDigits = bytes[position] & 0x7f; + position++; + length = 0; + for (let i = 0; i < numberOfDigits; i++) { + length = length * 256 + bytes[position]; + position++; + } + } + const byteLength = position + length; + return { + byteLength, + contents: bytes.subarray(position, byteLength), + raw: bytes.subarray(0, byteLength), + }; +} +function spkiFromX509(buf) { + const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents); + return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 0xa0 ? 6 : 5].raw); +} +function getSPKI(x509) { + const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ''); + const raw = decodeBase64(pem); + return formatPEM(spkiFromX509(raw), 'PUBLIC KEY'); +} +export const fromX509 = (pem, alg, options) => { + let spki; + try { + spki = getSPKI(pem); + } + catch (cause) { + throw new TypeError('failed to parse the X.509 certificate', { cause }); + } + return fromSPKI(spki, alg, options); +}; diff --git a/dist/browser/runtime/base64url.js b/dist/browser/runtime/base64url.js new file mode 100644 index 0000000000..32df82bfe0 --- /dev/null +++ b/dist/browser/runtime/base64url.js @@ -0,0 +1,37 @@ +import { encoder, decoder } from '../lib/buffer_utils.js'; +export const encodeBase64 = (input) => { + let unencoded = input; + if (typeof unencoded === 'string') { + unencoded = encoder.encode(unencoded); + } + const CHUNK_SIZE = 0x8000; + const arr = []; + for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { + arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))); + } + return btoa(arr.join('')); +}; +export const encode = (input) => { + return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); +}; +export const decodeBase64 = (encoded) => { + const binary = atob(encoded); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i); + } + return bytes; +}; +export const decode = (input) => { + let encoded = input; + if (encoded instanceof Uint8Array) { + encoded = decoder.decode(encoded); + } + encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, ''); + try { + return decodeBase64(encoded); + } + catch (_a) { + throw new TypeError('The input to be decoded is not correctly encoded.'); + } +}; diff --git a/dist/browser/runtime/bogus.js b/dist/browser/runtime/bogus.js new file mode 100644 index 0000000000..8fde604ebf --- /dev/null +++ b/dist/browser/runtime/bogus.js @@ -0,0 +1,6 @@ +const bogusWebCrypto = [ + { hash: 'SHA-256', name: 'HMAC' }, + true, + ['sign'], +]; +export default bogusWebCrypto; diff --git a/dist/browser/runtime/check_cek_length.js b/dist/browser/runtime/check_cek_length.js new file mode 100644 index 0000000000..ae89001215 --- /dev/null +++ b/dist/browser/runtime/check_cek_length.js @@ -0,0 +1,8 @@ +import { JWEInvalid } from '../util/errors.js'; +const checkCekLength = (cek, expected) => { + const actual = cek.byteLength << 3; + if (actual !== expected) { + throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); + } +}; +export default checkCekLength; diff --git a/dist/browser/runtime/check_key_length.js b/dist/browser/runtime/check_key_length.js new file mode 100644 index 0000000000..33970068fe --- /dev/null +++ b/dist/browser/runtime/check_key_length.js @@ -0,0 +1,8 @@ +export default (alg, key) => { + if (alg.startsWith('RS') || alg.startsWith('PS')) { + const { modulusLength } = key.algorithm; + if (typeof modulusLength !== 'number' || modulusLength < 2048) { + throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); + } + } +}; diff --git a/dist/browser/runtime/decrypt.js b/dist/browser/runtime/decrypt.js new file mode 100644 index 0000000000..68f9f7c3fe --- /dev/null +++ b/dist/browser/runtime/decrypt.js @@ -0,0 +1,85 @@ +import { concat, uint64be } from '../lib/buffer_utils.js'; +import checkIvLength from '../lib/check_iv_length.js'; +import checkCekLength from './check_cek_length.js'; +import timingSafeEqual from './timing_safe_equal.js'; +import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js'; +import crypto, { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, 'Uint8Array')); + } + const keySize = parseInt(enc.slice(1, 4), 10); + const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['decrypt']); + const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), { + hash: `SHA-${keySize << 1}`, + name: 'HMAC', + }, false, ['sign']); + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); + const expectedTag = new Uint8Array((await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3)); + let macCheckPassed; + try { + macCheckPassed = timingSafeEqual(tag, expectedTag); + } + catch (_a) { + } + if (!macCheckPassed) { + throw new JWEDecryptionFailed(); + } + let plaintext; + try { + plaintext = new Uint8Array(await crypto.subtle.decrypt({ iv, name: 'AES-CBC' }, encKey, ciphertext)); + } + catch (_b) { + } + if (!plaintext) { + throw new JWEDecryptionFailed(); + } + return plaintext; +} +async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { + let encKey; + if (cek instanceof Uint8Array) { + encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']); + } + else { + checkEncCryptoKey(cek, enc, 'decrypt'); + encKey = cek; + } + try { + return new Uint8Array(await crypto.subtle.decrypt({ + additionalData: aad, + iv, + name: 'AES-GCM', + tagLength: 128, + }, encKey, concat(ciphertext, tag))); + } + catch (_a) { + throw new JWEDecryptionFailed(); + } +} +const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); + } + checkIvLength(enc, iv); + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + if (cek instanceof Uint8Array) + checkCekLength(cek, parseInt(enc.slice(-3), 10)); + return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad); + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + if (cek instanceof Uint8Array) + checkCekLength(cek, parseInt(enc.slice(1, 4), 10)); + return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); + default: + throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); + } +}; +export default decrypt; diff --git a/dist/browser/runtime/digest.js b/dist/browser/runtime/digest.js new file mode 100644 index 0000000000..39099d3b1d --- /dev/null +++ b/dist/browser/runtime/digest.js @@ -0,0 +1,6 @@ +import crypto from './webcrypto.js'; +const digest = async (algorithm, data) => { + const subtleDigest = `SHA-${algorithm.slice(-3)}`; + return new Uint8Array(await crypto.subtle.digest(subtleDigest, data)); +}; +export default digest; diff --git a/dist/browser/runtime/ecdhes.js b/dist/browser/runtime/ecdhes.js new file mode 100644 index 0000000000..b4f515e312 --- /dev/null +++ b/dist/browser/runtime/ecdhes.js @@ -0,0 +1,46 @@ +import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.js'; +import crypto, { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { + if (!isCryptoKey(publicKey)) { + throw new TypeError(invalidKeyInput(publicKey, ...types)); + } + checkEncCryptoKey(publicKey, 'ECDH'); + if (!isCryptoKey(privateKey)) { + throw new TypeError(invalidKeyInput(privateKey, ...types)); + } + checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits'); + const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); + let length; + if (publicKey.algorithm.name === 'X25519') { + length = 256; + } + else if (publicKey.algorithm.name === 'X448') { + length = 448; + } + else { + length = + Math.ceil(parseInt(publicKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3; + } + const sharedSecret = new Uint8Array(await crypto.subtle.deriveBits({ + name: publicKey.algorithm.name, + public: publicKey, + }, privateKey, length)); + return concatKdf(sharedSecret, keyLength, value); +} +export async function generateEpk(key) { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)); + } + return crypto.subtle.generateKey(key.algorithm, true, ['deriveBits']); +} +export function ecdhAllowed(key) { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)); + } + return (['P-256', 'P-384', 'P-521'].includes(key.algorithm.namedCurve) || + key.algorithm.name === 'X25519' || + key.algorithm.name === 'X448'); +} diff --git a/dist/browser/runtime/encrypt.js b/dist/browser/runtime/encrypt.js new file mode 100644 index 0000000000..c2ec0ef91d --- /dev/null +++ b/dist/browser/runtime/encrypt.js @@ -0,0 +1,68 @@ +import { concat, uint64be } from '../lib/buffer_utils.js'; +import checkIvLength from '../lib/check_iv_length.js'; +import checkCekLength from './check_cek_length.js'; +import crypto, { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { JOSENotSupported } from '../util/errors.js'; +import { types } from './is_key_like.js'; +async function cbcEncrypt(enc, plaintext, cek, iv, aad) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, 'Uint8Array')); + } + const keySize = parseInt(enc.slice(1, 4), 10); + const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['encrypt']); + const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), { + hash: `SHA-${keySize << 1}`, + name: 'HMAC', + }, false, ['sign']); + const ciphertext = new Uint8Array(await crypto.subtle.encrypt({ + iv, + name: 'AES-CBC', + }, encKey, plaintext)); + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); + const tag = new Uint8Array((await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3)); + return { ciphertext, tag }; +} +async function gcmEncrypt(enc, plaintext, cek, iv, aad) { + let encKey; + if (cek instanceof Uint8Array) { + encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']); + } + else { + checkEncCryptoKey(cek, enc, 'encrypt'); + encKey = cek; + } + const encrypted = new Uint8Array(await crypto.subtle.encrypt({ + additionalData: aad, + iv, + name: 'AES-GCM', + tagLength: 128, + }, encKey, plaintext)); + const tag = encrypted.slice(-16); + const ciphertext = encrypted.slice(0, -16); + return { ciphertext, tag }; +} +const encrypt = async (enc, plaintext, cek, iv, aad) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); + } + checkIvLength(enc, iv); + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + if (cek instanceof Uint8Array) + checkCekLength(cek, parseInt(enc.slice(-3), 10)); + return cbcEncrypt(enc, plaintext, cek, iv, aad); + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + if (cek instanceof Uint8Array) + checkCekLength(cek, parseInt(enc.slice(1, 4), 10)); + return gcmEncrypt(enc, plaintext, cek, iv, aad); + default: + throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); + } +}; +export default encrypt; diff --git a/dist/browser/runtime/env.js b/dist/browser/runtime/env.js new file mode 100644 index 0000000000..740a197ec0 --- /dev/null +++ b/dist/browser/runtime/env.js @@ -0,0 +1,5 @@ +export function isCloudflareWorkers() { + return (typeof WebSocketPair !== 'undefined' || + (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') || + (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel')); +} diff --git a/dist/browser/runtime/fetch_jwks.js b/dist/browser/runtime/fetch_jwks.js new file mode 100644 index 0000000000..85d58b675d --- /dev/null +++ b/dist/browser/runtime/fetch_jwks.js @@ -0,0 +1,34 @@ +import { JOSEError, JWKSTimeout } from '../util/errors.js'; +const fetchJwks = async (url, timeout, options) => { + let controller; + let id; + let timedOut = false; + if (typeof AbortController === 'function') { + controller = new AbortController(); + id = setTimeout(() => { + timedOut = true; + controller.abort(); + }, timeout); + } + const response = await fetch(url.href, { + signal: controller ? controller.signal : undefined, + redirect: 'manual', + headers: options.headers, + }).catch((err) => { + if (timedOut) + throw new JWKSTimeout(); + throw err; + }); + if (id !== undefined) + clearTimeout(id); + if (response.status !== 200) { + throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response'); + } + try { + return await response.json(); + } + catch (_a) { + throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON'); + } +}; +export default fetchJwks; diff --git a/dist/browser/runtime/generate.js b/dist/browser/runtime/generate.js new file mode 100644 index 0000000000..8af84fa141 --- /dev/null +++ b/dist/browser/runtime/generate.js @@ -0,0 +1,153 @@ +import { isCloudflareWorkers } from './env.js'; +import crypto from './webcrypto.js'; +import { JOSENotSupported } from '../util/errors.js'; +import random from './random.js'; +export async function generateSecret(alg, options) { + var _a; + let length; + let algorithm; + let keyUsages; + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': + length = parseInt(alg.slice(-3), 10); + algorithm = { name: 'HMAC', hash: `SHA-${length}`, length }; + keyUsages = ['sign', 'verify']; + break; + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + length = parseInt(alg.slice(-3), 10); + return random(new Uint8Array(length >> 3)); + case 'A128KW': + case 'A192KW': + case 'A256KW': + length = parseInt(alg.slice(1, 4), 10); + algorithm = { name: 'AES-KW', length }; + keyUsages = ['wrapKey', 'unwrapKey']; + break; + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + length = parseInt(alg.slice(1, 4), 10); + algorithm = { name: 'AES-GCM', length }; + keyUsages = ['encrypt', 'decrypt']; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + return crypto.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages); +} +function getModulusLengthOption(options) { + var _a; + const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; + if (typeof modulusLength !== 'number' || modulusLength < 2048) { + throw new JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used'); + } + return modulusLength; +} +export async function generateKeyPair(alg, options) { + var _a, _b, _c, _d; + let algorithm; + let keyUsages; + switch (alg) { + case 'PS256': + case 'PS384': + case 'PS512': + algorithm = { + name: 'RSA-PSS', + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + modulusLength: getModulusLengthOption(options), + }; + keyUsages = ['sign', 'verify']; + break; + case 'RS256': + case 'RS384': + case 'RS512': + algorithm = { + name: 'RSASSA-PKCS1-v1_5', + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + modulusLength: getModulusLengthOption(options), + }; + keyUsages = ['sign', 'verify']; + break; + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + algorithm = { + name: 'RSA-OAEP', + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + modulusLength: getModulusLengthOption(options), + }; + keyUsages = ['decrypt', 'unwrapKey', 'encrypt', 'wrapKey']; + break; + case 'ES256': + algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; + keyUsages = ['sign', 'verify']; + break; + case 'ES384': + algorithm = { name: 'ECDSA', namedCurve: 'P-384' }; + keyUsages = ['sign', 'verify']; + break; + case 'ES512': + algorithm = { name: 'ECDSA', namedCurve: 'P-521' }; + keyUsages = ['sign', 'verify']; + break; + case 'EdDSA': + keyUsages = ['sign', 'verify']; + const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : 'Ed25519'; + switch (crv) { + case 'Ed25519': + case 'Ed448': + algorithm = { name: crv }; + break; + default: + throw new JOSENotSupported('Invalid or unsupported crv option provided'); + } + break; + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + keyUsages = ['deriveKey', 'deriveBits']; + const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256'; + switch (crv) { + case 'P-256': + case 'P-384': + case 'P-521': { + algorithm = { name: 'ECDH', namedCurve: crv }; + break; + } + case 'X25519': + case 'X448': + algorithm = { name: crv }; + break; + default: + throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448'); + } + break; + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + try { + return (await crypto.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages)); + } + catch (err) { + if (algorithm.name === 'Ed25519' && + (err === null || err === void 0 ? void 0 : err.name) === 'NotSupportedError' && + isCloudflareWorkers()) { + algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; + return (await crypto.subtle.generateKey(algorithm, (_d = options === null || options === void 0 ? void 0 : options.extractable) !== null && _d !== void 0 ? _d : false, keyUsages)); + } + throw err; + } +} diff --git a/dist/browser/runtime/get_sign_verify_key.js b/dist/browser/runtime/get_sign_verify_key.js new file mode 100644 index 0000000000..db34ae8bbe --- /dev/null +++ b/dist/browser/runtime/get_sign_verify_key.js @@ -0,0 +1,17 @@ +import crypto, { isCryptoKey } from './webcrypto.js'; +import { checkSigCryptoKey } from '../lib/crypto_key.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +export default function getCryptoKey(alg, key, usage) { + if (isCryptoKey(key)) { + checkSigCryptoKey(key, alg, usage); + return key; + } + if (key instanceof Uint8Array) { + if (!alg.startsWith('HS')) { + throw new TypeError(invalidKeyInput(key, ...types)); + } + return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, false, [usage]); + } + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); +} diff --git a/dist/browser/runtime/is_key_like.js b/dist/browser/runtime/is_key_like.js new file mode 100644 index 0000000000..8d35fdc84c --- /dev/null +++ b/dist/browser/runtime/is_key_like.js @@ -0,0 +1,5 @@ +import { isCryptoKey } from './webcrypto.js'; +export default (key) => { + return isCryptoKey(key); +}; +export const types = ['CryptoKey']; diff --git a/dist/browser/runtime/jwk_to_key.js b/dist/browser/runtime/jwk_to_key.js new file mode 100644 index 0000000000..d3e693d2de --- /dev/null +++ b/dist/browser/runtime/jwk_to_key.js @@ -0,0 +1,155 @@ +import { isCloudflareWorkers } from './env.js'; +import crypto from './webcrypto.js'; +import { JOSENotSupported } from '../util/errors.js'; +import { decode as base64url } from './base64url.js'; +function subtleMapping(jwk) { + let algorithm; + let keyUsages; + switch (jwk.kty) { + case 'oct': { + switch (jwk.alg) { + case 'HS256': + case 'HS384': + case 'HS512': + algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = ['sign', 'verify']; + break; + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`); + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': + algorithm = { name: 'AES-GCM' }; + keyUsages = ['encrypt', 'decrypt']; + break; + case 'A128KW': + case 'A192KW': + case 'A256KW': + algorithm = { name: 'AES-KW' }; + keyUsages = ['wrapKey', 'unwrapKey']; + break; + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': + algorithm = { name: 'PBKDF2' }; + keyUsages = ['deriveBits']; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case 'RSA': { + switch (jwk.alg) { + case 'PS256': + case 'PS384': + case 'PS512': + algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ['sign'] : ['verify']; + break; + case 'RS256': + case 'RS384': + case 'RS512': + algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ['sign'] : ['verify']; + break; + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + algorithm = { + name: 'RSA-OAEP', + hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`, + }; + keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey']; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case 'EC': { + switch (jwk.alg) { + case 'ES256': + algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; + keyUsages = jwk.d ? ['sign'] : ['verify']; + break; + case 'ES384': + algorithm = { name: 'ECDSA', namedCurve: 'P-384' }; + keyUsages = jwk.d ? ['sign'] : ['verify']; + break; + case 'ES512': + algorithm = { name: 'ECDSA', namedCurve: 'P-521' }; + keyUsages = jwk.d ? ['sign'] : ['verify']; + break; + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': + algorithm = { name: 'ECDH', namedCurve: jwk.crv }; + keyUsages = jwk.d ? ['deriveBits'] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case 'OKP': { + switch (jwk.alg) { + case 'EdDSA': + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ['sign'] : ['verify']; + break; + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ['deriveBits'] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); + } + return { algorithm, keyUsages }; +} +const parse = async (jwk) => { + var _a, _b; + if (!jwk.alg) { + throw new TypeError('"alg" argument is required when "jwk.alg" is not present'); + } + const { algorithm, keyUsages } = subtleMapping(jwk); + const rest = [ + algorithm, + (_a = jwk.ext) !== null && _a !== void 0 ? _a : false, + (_b = jwk.key_ops) !== null && _b !== void 0 ? _b : keyUsages, + ]; + if (algorithm.name === 'PBKDF2') { + return crypto.subtle.importKey('raw', base64url(jwk.k), ...rest); + } + const keyData = { ...jwk }; + delete keyData.alg; + delete keyData.use; + try { + return await crypto.subtle.importKey('jwk', keyData, ...rest); + } + catch (err) { + if (algorithm.name === 'Ed25519' && + (err === null || err === void 0 ? void 0 : err.name) === 'NotSupportedError' && + isCloudflareWorkers()) { + rest[0] = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; + return await crypto.subtle.importKey('jwk', keyData, ...rest); + } + throw err; + } +}; +export default parse; diff --git a/dist/browser/runtime/key_to_jwk.js b/dist/browser/runtime/key_to_jwk.js new file mode 100644 index 0000000000..438edfedc3 --- /dev/null +++ b/dist/browser/runtime/key_to_jwk.js @@ -0,0 +1,21 @@ +import crypto, { isCryptoKey } from './webcrypto.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { encode as base64url } from './base64url.js'; +import { types } from './is_key_like.js'; +const keyToJWK = async (key) => { + if (key instanceof Uint8Array) { + return { + kty: 'oct', + k: base64url(key), + }; + } + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); + } + if (!key.extractable) { + throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK'); + } + const { ext, key_ops, alg, use, ...jwk } = await crypto.subtle.exportKey('jwk', key); + return jwk; +}; +export default keyToJWK; diff --git a/dist/browser/runtime/pbes2kw.js b/dist/browser/runtime/pbes2kw.js new file mode 100644 index 0000000000..575304aa6b --- /dev/null +++ b/dist/browser/runtime/pbes2kw.js @@ -0,0 +1,51 @@ +import random from './random.js'; +import { p2s as concatSalt } from '../lib/buffer_utils.js'; +import { encode as base64url } from './base64url.js'; +import { wrap, unwrap } from './aeskw.js'; +import checkP2s from '../lib/check_p2s.js'; +import crypto, { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +function getCryptoKey(key, alg) { + if (key instanceof Uint8Array) { + return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']); + } + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey'); + return key; + } + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); +} +async function deriveKey(p2s, alg, p2c, key) { + checkP2s(p2s); + const salt = concatSalt(alg, p2s); + const keylen = parseInt(alg.slice(13, 16), 10); + const subtleAlg = { + hash: `SHA-${alg.slice(8, 11)}`, + iterations: p2c, + name: 'PBKDF2', + salt, + }; + const wrapAlg = { + length: keylen, + name: 'AES-KW', + }; + const cryptoKey = await getCryptoKey(key, alg); + if (cryptoKey.usages.includes('deriveBits')) { + return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen)); + } + if (cryptoKey.usages.includes('deriveKey')) { + return crypto.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ['wrapKey', 'unwrapKey']); + } + throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"'); +} +export const encrypt = async (alg, key, cek, p2c = 2048, p2s = random(new Uint8Array(16))) => { + const derived = await deriveKey(p2s, alg, p2c, key); + const encryptedKey = await wrap(alg.slice(-6), derived, cek); + return { encryptedKey, p2c, p2s: base64url(p2s) }; +}; +export const decrypt = async (alg, key, encryptedKey, p2c, p2s) => { + const derived = await deriveKey(p2s, alg, p2c, key); + return unwrap(alg.slice(-6), derived, encryptedKey); +}; diff --git a/dist/browser/runtime/random.js b/dist/browser/runtime/random.js new file mode 100644 index 0000000000..e8e461124a --- /dev/null +++ b/dist/browser/runtime/random.js @@ -0,0 +1,2 @@ +import crypto from './webcrypto.js'; +export default crypto.getRandomValues.bind(crypto); diff --git a/dist/browser/runtime/rsaes.js b/dist/browser/runtime/rsaes.js new file mode 100644 index 0000000000..a1733769ec --- /dev/null +++ b/dist/browser/runtime/rsaes.js @@ -0,0 +1,37 @@ +import subtleAlgorithm from './subtle_rsaes.js'; +import bogusWebCrypto from './bogus.js'; +import crypto, { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import checkKeyLength from './check_key_length.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +export const encrypt = async (alg, key, cek) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)); + } + checkEncCryptoKey(key, alg, 'encrypt', 'wrapKey'); + checkKeyLength(alg, key); + if (key.usages.includes('encrypt')) { + return new Uint8Array(await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek)); + } + if (key.usages.includes('wrapKey')) { + const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto); + return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, key, subtleAlgorithm(alg))); + } + throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation'); +}; +export const decrypt = async (alg, key, encryptedKey) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)); + } + checkEncCryptoKey(key, alg, 'decrypt', 'unwrapKey'); + checkKeyLength(alg, key); + if (key.usages.includes('decrypt')) { + return new Uint8Array(await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey)); + } + if (key.usages.includes('unwrapKey')) { + const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, key, subtleAlgorithm(alg), ...bogusWebCrypto); + return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)); + } + throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation'); +}; diff --git a/dist/browser/runtime/sign.js b/dist/browser/runtime/sign.js new file mode 100644 index 0000000000..3ccb9e16c3 --- /dev/null +++ b/dist/browser/runtime/sign.js @@ -0,0 +1,11 @@ +import subtleAlgorithm from './subtle_dsa.js'; +import crypto from './webcrypto.js'; +import checkKeyLength from './check_key_length.js'; +import getSignKey from './get_sign_verify_key.js'; +const sign = async (alg, key, data) => { + const cryptoKey = await getSignKey(alg, key, 'sign'); + checkKeyLength(alg, cryptoKey); + const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data); + return new Uint8Array(signature); +}; +export default sign; diff --git a/dist/browser/runtime/subtle_dsa.js b/dist/browser/runtime/subtle_dsa.js new file mode 100644 index 0000000000..3df4514adf --- /dev/null +++ b/dist/browser/runtime/subtle_dsa.js @@ -0,0 +1,30 @@ +import { isCloudflareWorkers } from './env.js'; +import { JOSENotSupported } from '../util/errors.js'; +export default function subtleDsa(alg, algorithm) { + const hash = `SHA-${alg.slice(-3)}`; + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': + return { hash, name: 'HMAC' }; + case 'PS256': + case 'PS384': + case 'PS512': + return { hash, name: 'RSA-PSS', saltLength: alg.slice(-3) >> 3 }; + case 'RS256': + case 'RS384': + case 'RS512': + return { hash, name: 'RSASSA-PKCS1-v1_5' }; + case 'ES256': + case 'ES384': + case 'ES512': + return { hash, name: 'ECDSA', namedCurve: algorithm.namedCurve }; + case 'EdDSA': + if (isCloudflareWorkers() && algorithm.name === 'NODE-ED25519') { + return { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }; + } + return { name: algorithm.name }; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} diff --git a/dist/browser/runtime/subtle_rsaes.js b/dist/browser/runtime/subtle_rsaes.js new file mode 100644 index 0000000000..3a399bcfa7 --- /dev/null +++ b/dist/browser/runtime/subtle_rsaes.js @@ -0,0 +1,12 @@ +import { JOSENotSupported } from '../util/errors.js'; +export default function subtleRsaEs(alg) { + switch (alg) { + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + return 'RSA-OAEP'; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} diff --git a/dist/browser/runtime/timing_safe_equal.js b/dist/browser/runtime/timing_safe_equal.js new file mode 100644 index 0000000000..442cdccd20 --- /dev/null +++ b/dist/browser/runtime/timing_safe_equal.js @@ -0,0 +1,19 @@ +const timingSafeEqual = (a, b) => { + if (!(a instanceof Uint8Array)) { + throw new TypeError('First argument must be a buffer'); + } + if (!(b instanceof Uint8Array)) { + throw new TypeError('Second argument must be a buffer'); + } + if (a.length !== b.length) { + throw new TypeError('Input buffers must have the same length'); + } + const len = a.length; + let out = 0; + let i = -1; + while (++i < len) { + out |= a[i] ^ b[i]; + } + return out === 0; +}; +export default timingSafeEqual; diff --git a/dist/browser/runtime/verify.js b/dist/browser/runtime/verify.js new file mode 100644 index 0000000000..2ad4c7ffe2 --- /dev/null +++ b/dist/browser/runtime/verify.js @@ -0,0 +1,16 @@ +import subtleAlgorithm from './subtle_dsa.js'; +import crypto from './webcrypto.js'; +import checkKeyLength from './check_key_length.js'; +import getVerifyKey from './get_sign_verify_key.js'; +const verify = async (alg, key, signature, data) => { + const cryptoKey = await getVerifyKey(alg, key, 'verify'); + checkKeyLength(alg, cryptoKey); + const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm); + try { + return await crypto.subtle.verify(algorithm, cryptoKey, signature, data); + } + catch (_a) { + return false; + } +}; +export default verify; diff --git a/dist/browser/runtime/webcrypto.js b/dist/browser/runtime/webcrypto.js new file mode 100644 index 0000000000..f9e1e91539 --- /dev/null +++ b/dist/browser/runtime/webcrypto.js @@ -0,0 +1,2 @@ +export default crypto; +export const isCryptoKey = (key) => key instanceof CryptoKey; diff --git a/dist/browser/runtime/zlib.js b/dist/browser/runtime/zlib.js new file mode 100644 index 0000000000..e47cb532dc --- /dev/null +++ b/dist/browser/runtime/zlib.js @@ -0,0 +1,7 @@ +import { JOSENotSupported } from '../util/errors.js'; +export const inflate = async () => { + throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.'); +}; +export const deflate = async () => { + throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.'); +}; diff --git a/dist/browser/util/base64url.js b/dist/browser/util/base64url.js new file mode 100644 index 0000000000..88ce7556d6 --- /dev/null +++ b/dist/browser/util/base64url.js @@ -0,0 +1,3 @@ +import * as base64url from '../runtime/base64url.js'; +export const encode = base64url.encode; +export const decode = base64url.decode; diff --git a/dist/browser/util/decode_jwt.js b/dist/browser/util/decode_jwt.js new file mode 100644 index 0000000000..bea0ea9018 --- /dev/null +++ b/dist/browser/util/decode_jwt.js @@ -0,0 +1,32 @@ +import { decode as base64url } from './base64url.js'; +import { decoder } from '../lib/buffer_utils.js'; +import isObject from '../lib/is_object.js'; +import { JWTInvalid } from './errors.js'; +export function decodeJwt(jwt) { + if (typeof jwt !== 'string') + throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string'); + const { 1: payload, length } = jwt.split('.'); + if (length === 5) + throw new JWTInvalid('Only JWTs using Compact JWS serialization can be decoded'); + if (length !== 3) + throw new JWTInvalid('Invalid JWT'); + if (!payload) + throw new JWTInvalid('JWTs must contain a payload'); + let decoded; + try { + decoded = base64url(payload); + } + catch (_a) { + throw new JWTInvalid('Failed to parse the base64url encoded payload'); + } + let result; + try { + result = JSON.parse(decoder.decode(decoded)); + } + catch (_b) { + throw new JWTInvalid('Failed to parse the decoded payload as JSON'); + } + if (!isObject(result)) + throw new JWTInvalid('Invalid JWT Claims Set'); + return result; +} diff --git a/dist/browser/util/decode_protected_header.js b/dist/browser/util/decode_protected_header.js new file mode 100644 index 0000000000..aecbfe2390 --- /dev/null +++ b/dist/browser/util/decode_protected_header.js @@ -0,0 +1,34 @@ +import { decode as base64url } from './base64url.js'; +import { decoder } from '../lib/buffer_utils.js'; +import isObject from '../lib/is_object.js'; +export function decodeProtectedHeader(token) { + let protectedB64u; + if (typeof token === 'string') { + const parts = token.split('.'); + if (parts.length === 3 || parts.length === 5) { + ; + [protectedB64u] = parts; + } + } + else if (typeof token === 'object' && token) { + if ('protected' in token) { + protectedB64u = token.protected; + } + else { + throw new TypeError('Token does not contain a Protected Header'); + } + } + try { + if (typeof protectedB64u !== 'string' || !protectedB64u) { + throw new Error(); + } + const result = JSON.parse(decoder.decode(base64url(protectedB64u))); + if (!isObject(result)) { + throw new Error(); + } + return result; + } + catch (_a) { + throw new TypeError('Invalid Token or Protected Header formatting'); + } +} diff --git a/dist/browser/util/errors.js b/dist/browser/util/errors.js new file mode 100644 index 0000000000..13a36f58fa --- /dev/null +++ b/dist/browser/util/errors.js @@ -0,0 +1,148 @@ +export class JOSEError extends Error { + static get code() { + return 'ERR_JOSE_GENERIC'; + } + constructor(message) { + var _a; + super(message); + this.code = 'ERR_JOSE_GENERIC'; + this.name = this.constructor.name; + (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); + } +} +export class JWTClaimValidationFailed extends JOSEError { + static get code() { + return 'ERR_JWT_CLAIM_VALIDATION_FAILED'; + } + constructor(message, claim = 'unspecified', reason = 'unspecified') { + super(message); + this.code = 'ERR_JWT_CLAIM_VALIDATION_FAILED'; + this.claim = claim; + this.reason = reason; + } +} +export class JWTExpired extends JOSEError { + static get code() { + return 'ERR_JWT_EXPIRED'; + } + constructor(message, claim = 'unspecified', reason = 'unspecified') { + super(message); + this.code = 'ERR_JWT_EXPIRED'; + this.claim = claim; + this.reason = reason; + } +} +export class JOSEAlgNotAllowed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JOSE_ALG_NOT_ALLOWED'; + } + static get code() { + return 'ERR_JOSE_ALG_NOT_ALLOWED'; + } +} +export class JOSENotSupported extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JOSE_NOT_SUPPORTED'; + } + static get code() { + return 'ERR_JOSE_NOT_SUPPORTED'; + } +} +export class JWEDecryptionFailed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWE_DECRYPTION_FAILED'; + this.message = 'decryption operation failed'; + } + static get code() { + return 'ERR_JWE_DECRYPTION_FAILED'; + } +} +export class JWEInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWE_INVALID'; + } + static get code() { + return 'ERR_JWE_INVALID'; + } +} +export class JWSInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWS_INVALID'; + } + static get code() { + return 'ERR_JWS_INVALID'; + } +} +export class JWTInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWT_INVALID'; + } + static get code() { + return 'ERR_JWT_INVALID'; + } +} +export class JWKInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWK_INVALID'; + } + static get code() { + return 'ERR_JWK_INVALID'; + } +} +export class JWKSInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_INVALID'; + } + static get code() { + return 'ERR_JWKS_INVALID'; + } +} +export class JWKSNoMatchingKey extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_NO_MATCHING_KEY'; + this.message = 'no applicable key found in the JSON Web Key Set'; + } + static get code() { + return 'ERR_JWKS_NO_MATCHING_KEY'; + } +} +export class JWKSMultipleMatchingKeys extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; + this.message = 'multiple matching keys found in the JSON Web Key Set'; + } + static get code() { + return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; + } +} +Symbol.asyncIterator; +export class JWKSTimeout extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_TIMEOUT'; + this.message = 'request timed out'; + } + static get code() { + return 'ERR_JWKS_TIMEOUT'; + } +} +export class JWSSignatureVerificationFailed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; + this.message = 'signature verification failed'; + } + static get code() { + return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; + } +} diff --git a/dist/deno/README.md b/dist/deno/README.md new file mode 100644 index 0000000000..fa6e72bc68 --- /dev/null +++ b/dist/deno/README.md @@ -0,0 +1,51 @@ +# `jose` Modules API Documentation + +> "JSON Web Almost Everything" - JWA, JWS, JWE, JWT, JWK, JWKS with no dependencies using runtime's native crypto. + +## [đŸ’— Help the project](https://github.com/panva/jose/blob/v4.12.2/docs/https://github.com/sponsors/panva) + +## Available modules + +**`example`** Deno import +```js +import * as jose from 'https://deno.land/x/jose@v4.12.2/index.ts' +``` + +- JSON Web Tokens (JWT) + - [Signing](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jwt_sign.SignJWT.md#readme) + - [Verification & JWT Claims Set Validation](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwt_verify.jwtVerify.md#readme) + - Encrypted JSON Web Tokens + - [Encryption](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jwt_encrypt.EncryptJWT.md#readme) + - [Decryption & JWT Claims Set Validation](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwt_decrypt.jwtDecrypt.md#readme) +- Key Import + - [JWK Import](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_import.importJWK.md#readme) + - [Public Key Import (SPKI)](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_import.importSPKI.md#readme) + - [Public Key Import (X.509 Certificate)](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_import.importX509.md#readme) + - [Private Key Import (PKCS #8)](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_import.importPKCS8.md#readme) +- JSON Web Encryption (JWE) + - Encryption - [Compact](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jwe_compact_encrypt.CompactEncrypt.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jwe_flattened_encrypt.FlattenedEncrypt.md#readme), [General](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jwe_general_encrypt.GeneralEncrypt.md#readme) + - Decryption - [Compact](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwe_compact_decrypt.compactDecrypt.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwe_flattened_decrypt.flattenedDecrypt.md#readme), [General](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwe_general_decrypt.generalDecrypt.md#readme) +- JSON Web Signature (JWS) + - Signing - [Compact](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jws_compact_sign.CompactSign.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jws_flattened_sign.FlattenedSign.md#readme), [General](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jws_general_sign.GeneralSign.md#readme) + - Verification - [Compact](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jws_compact_verify.compactVerify.md#readme), [Flattened](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jws_flattened_verify.flattenedVerify.md#readme), [General](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jws_general_verify.generalVerify.md#readme) +- JSON Web Key (JWK) + - [Calculating JWK Thumbprint](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwk_thumbprint.calculateJwkThumbprint.md#readme) + - [Calculating JWK Thumbprint URI](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwk_thumbprint.calculateJwkThumbprintUri.md#readme) + - [Verification using a JWK Embedded in a JWS Header](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwk_embedded.EmbeddedJWK.md#readme) +- JSON Web Key Set (JWKS) + - [Verify using a local JWKSet](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwks_local.createLocalJWKSet.md#readme) + - [Verify using a remote JWKSet](https://github.com/panva/jose/blob/v4.12.2/docs/functions/jwks_remote.createRemoteJWKSet.md#readme) +- Key Pair or Secret Generation + - [Asymmetric Key Pair Generation](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_generate_key_pair.generateKeyPair.md#readme) + - [Symmetric Secret Generation](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_generate_secret.generateSecret.md#readme) +- Key Export + - [JWK Export](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_export.exportJWK.md#readme) + - [Private Key Export](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_export.exportPKCS8.md#readme) + - [Public Key Export](https://github.com/panva/jose/blob/v4.12.2/docs/functions/key_export.exportSPKI.md#readme) +- Utilities + - [Decoding Token's Protected Header](https://github.com/panva/jose/blob/v4.12.2/docs/functions/util_decode_protected_header.decodeProtectedHeader.md#readme) + - [Decoding JWT Claims Set](https://github.com/panva/jose/blob/v4.12.2/docs/functions/util_decode_jwt.decodeJwt.md#readme) +- [Unsecured JWT](https://github.com/panva/jose/blob/v4.12.2/docs/classes/jwt_unsecured.UnsecuredJWT.md#readme) +- [JOSE Errors](https://github.com/panva/jose/blob/v4.12.2/docs/modules/util_errors.md#readme) + +[support-sponsor]: https://github.com/sponsors/panva diff --git a/dist/deno/index.ts b/dist/deno/index.ts new file mode 100644 index 0000000000..611b8e0d4c --- /dev/null +++ b/dist/deno/index.ts @@ -0,0 +1,98 @@ +export { compactDecrypt } from './jwe/compact/decrypt.ts' +export type { CompactDecryptGetKey } from './jwe/compact/decrypt.ts' +export { flattenedDecrypt } from './jwe/flattened/decrypt.ts' +export type { FlattenedDecryptGetKey } from './jwe/flattened/decrypt.ts' +export { generalDecrypt } from './jwe/general/decrypt.ts' +export type { GeneralDecryptGetKey } from './jwe/general/decrypt.ts' +export { GeneralEncrypt } from './jwe/general/encrypt.ts' +export type { Recipient } from './jwe/general/encrypt.ts' + +export { compactVerify } from './jws/compact/verify.ts' +export type { CompactVerifyGetKey } from './jws/compact/verify.ts' +export { flattenedVerify } from './jws/flattened/verify.ts' +export type { FlattenedVerifyGetKey } from './jws/flattened/verify.ts' +export { generalVerify } from './jws/general/verify.ts' +export type { GeneralVerifyGetKey } from './jws/general/verify.ts' + +export { jwtVerify } from './jwt/verify.ts' +export type { JWTVerifyOptions, JWTVerifyGetKey } from './jwt/verify.ts' +export { jwtDecrypt } from './jwt/decrypt.ts' +export type { JWTDecryptOptions, JWTDecryptGetKey } from './jwt/decrypt.ts' +export type { ProduceJWT } from './jwt/produce.ts' + +export { CompactEncrypt } from './jwe/compact/encrypt.ts' +export { FlattenedEncrypt } from './jwe/flattened/encrypt.ts' + +export { CompactSign } from './jws/compact/sign.ts' +export { FlattenedSign } from './jws/flattened/sign.ts' +export { GeneralSign } from './jws/general/sign.ts' +export type { Signature } from './jws/general/sign.ts' + +export { SignJWT } from './jwt/sign.ts' +export { EncryptJWT } from './jwt/encrypt.ts' + +export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.ts' +export { EmbeddedJWK } from './jwk/embedded.ts' + +export { createLocalJWKSet } from './jwks/local.ts' +export { createRemoteJWKSet } from './jwks/remote.ts' +export type { RemoteJWKSetOptions } from './jwks/remote.ts' + +export { UnsecuredJWT } from './jwt/unsecured.ts' +export type { UnsecuredResult } from './jwt/unsecured.ts' + +export { exportPKCS8, exportSPKI, exportJWK } from './key/export.ts' + +export { importSPKI, importPKCS8, importX509, importJWK } from './key/import.ts' +export type { PEMImportOptions } from './key/import.ts' + +export { decodeProtectedHeader } from './util/decode_protected_header.ts' +export { decodeJwt } from './util/decode_jwt.ts' +export type { ProtectedHeaderParameters } from './util/decode_protected_header.ts' + +export * as errors from './util/errors.ts' + +export { generateKeyPair } from './key/generate_key_pair.ts' +export type { GenerateKeyPairResult, GenerateKeyPairOptions } from './key/generate_key_pair.ts' +export { generateSecret } from './key/generate_secret.ts' +export type { GenerateSecretOptions } from './key/generate_secret.ts' + +export * as base64url from './util/base64url.ts' + +export type { + KeyLike, + JWK, + FlattenedJWSInput, + GeneralJWSInput, + FlattenedJWS, + GeneralJWS, + JoseHeaderParameters, + JWSHeaderParameters, + JWEKeyManagementHeaderParameters, + FlattenedJWE, + GeneralJWE, + JWEHeaderParameters, + CritOption, + DeflateOption, + DecryptOptions, + EncryptOptions, + JWTClaimVerificationOptions, + VerifyOptions, + SignOptions, + JWTPayload, + DeflateFunction, + InflateFunction, + FlattenedDecryptResult, + GeneralDecryptResult, + CompactDecryptResult, + FlattenedVerifyResult, + GeneralVerifyResult, + CompactVerifyResult, + JWTVerifyResult, + JWTDecryptResult, + ResolvedKey, + CompactJWEHeaderParameters, + CompactJWSHeaderParameters, + JWTHeaderParameters, + JSONWebKeySet, +} from './types.d.ts' diff --git a/dist/deno/jwe/compact/decrypt.ts b/dist/deno/jwe/compact/decrypt.ts new file mode 100644 index 0000000000..f3bec8eca6 --- /dev/null +++ b/dist/deno/jwe/compact/decrypt.ts @@ -0,0 +1,99 @@ +import { flattenedDecrypt } from '../flattened/decrypt.ts' +import { JWEInvalid } from '../../util/errors.ts' +import { decoder } from '../../lib/buffer_utils.ts' +import type { + KeyLike, + DecryptOptions, + CompactJWEHeaderParameters, + GetKeyFunction, + FlattenedJWE, + CompactDecryptResult, + ResolvedKey, +} from '../../types.d.ts' + +/** + * Interface for Compact JWE Decryption dynamic key resolution. No token components have been + * verified at the time of this function call. + */ +export interface CompactDecryptGetKey + extends GetKeyFunction {} + +/** + * Decrypts a Compact JWE. + * + * @example Usage + * + * ```js + * const jwe = + * 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.nyQ19eq9ogh9wA7fFtnI2oouzy5_8b5DeLkoRMfi2yijgfTs2zEnayCEofz_qhnL-nwszabd9qUeHv0-IwvhhJJS7GUJOU3ikiIe42qcIAFme1A_Fo9CTxw4XTOy-I5qanl8So91u6hwfyN1VxAqVLsSE7_23EC-gfGEg_5znew9PyXXsOIE-K_HH7IQowRrlZ1X_bM_Liu53RzDpLDvRz59mp3S8L56YqpM8FexFGTGpEaoTcEIst375qncYt3-79IVR7gZN1RWsWgjPatfvVbnh74PglQcATSf3UUhaW0OAKn6q7r3PDx6DIKQ35bgHQg5QopuN00eIfLQL2trGw.W3grIVj5HVuAb76X.6PcuDe5D6ttWFYyv0oqqdDXfI2R8wBg1F2Q80UUA_Gv8eEimNWfxIWdLxrjzgQGSvIhxmFKuLM0.a93_Ug3uZHuczj70Zavx8Q' + * + * const { plaintext, protectedHeader } = await jose.compactDecrypt(jwe, privateKey) + * + * console.log(protectedHeader) + * console.log(new TextDecoder().decode(plaintext)) + * ``` + * + * @param jwe Compact JWE. + * @param key Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export async function compactDecrypt( + jwe: string | Uint8Array, + key: KeyLike | Uint8Array, + options?: DecryptOptions, +): Promise +/** + * @param jwe Compact JWE. + * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export async function compactDecrypt( + jwe: string | Uint8Array, + getKey: CompactDecryptGetKey, + options?: DecryptOptions, +): Promise +export async function compactDecrypt( + jwe: string | Uint8Array, + key: KeyLike | Uint8Array | CompactDecryptGetKey, + options?: DecryptOptions, +) { + if (jwe instanceof Uint8Array) { + jwe = decoder.decode(jwe) + } + + if (typeof jwe !== 'string') { + throw new JWEInvalid('Compact JWE must be a string or Uint8Array') + } + const { + 0: protectedHeader, + 1: encryptedKey, + 2: iv, + 3: ciphertext, + 4: tag, + length, + } = jwe.split('.') + + if (length !== 5) { + throw new JWEInvalid('Invalid Compact JWE') + } + + const decrypted = await flattenedDecrypt( + { + ciphertext, + iv: (iv || undefined), + protected: protectedHeader || undefined, + tag: (tag || undefined), + encrypted_key: encryptedKey || undefined, + }, + [1]>key, + options, + ) + + const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader! } + + if (typeof key === 'function') { + return { ...result, key: decrypted.key } + } + + return result +} diff --git a/dist/deno/jwe/compact/encrypt.ts b/dist/deno/jwe/compact/encrypt.ts new file mode 100644 index 0000000000..bc704a7f0b --- /dev/null +++ b/dist/deno/jwe/compact/encrypt.ts @@ -0,0 +1,91 @@ +import { FlattenedEncrypt } from '../flattened/encrypt.ts' +import type { + KeyLike, + JWEKeyManagementHeaderParameters, + CompactJWEHeaderParameters, + EncryptOptions, +} from '../../types.d.ts' + +/** + * The CompactEncrypt class is a utility for creating Compact JWE strings. + * + * @example Usage + * + * ```js + * const jwe = await new jose.CompactEncrypt( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) + * .encrypt(publicKey) + * + * console.log(jwe) + * ``` + */ +export class CompactEncrypt { + private _flattened: FlattenedEncrypt + + /** @param plaintext Binary representation of the plaintext to encrypt. */ + constructor(plaintext: Uint8Array) { + this._flattened = new FlattenedEncrypt(plaintext) + } + + /** + * Sets a content encryption key to use, by default a random suitable one is generated for the JWE + * enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param cek JWE Content Encryption Key. + */ + setContentEncryptionKey(cek: Uint8Array) { + this._flattened.setContentEncryptionKey(cek) + return this + } + + /** + * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable + * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param iv JWE Initialization Vector. + */ + setInitializationVector(iv: Uint8Array) { + this._flattened.setInitializationVector(iv) + return this + } + + /** + * Sets the JWE Protected Header on the CompactEncrypt object. + * + * @param protectedHeader JWE Protected Header object. + */ + setProtectedHeader(protectedHeader: CompactJWEHeaderParameters) { + this._flattened.setProtectedHeader(protectedHeader) + return this + } + + /** + * Sets the JWE Key Management parameters to be used when encrypting the Content Encryption Key. + * You do not need to invoke this method, it is only really intended for test and vector + * validation purposes. + * + * @param parameters JWE Key Management parameters. + */ + setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters) { + this._flattened.setKeyManagementParameters(parameters) + return this + } + + /** + * Encrypts and resolves the value of the Compact JWE string. + * + * @param key Public Key or Secret to encrypt the JWE with. + * @param options JWE Encryption options. + */ + async encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise { + const jwe = await this._flattened.encrypt(key, options) + + return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.') + } +} diff --git a/dist/deno/jwe/flattened/decrypt.ts b/dist/deno/jwe/flattened/decrypt.ts new file mode 100644 index 0000000000..6b5e4fd0eb --- /dev/null +++ b/dist/deno/jwe/flattened/decrypt.ts @@ -0,0 +1,247 @@ +import { decode as base64url } from '../../runtime/base64url.ts' +import decrypt from '../../runtime/decrypt.ts' +import { inflate } from '../../runtime/zlib.ts' + +import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.ts' +import isDisjoint from '../../lib/is_disjoint.ts' +import isObject from '../../lib/is_object.ts' +import decryptKeyManagement from '../../lib/decrypt_key_management.ts' +import type { + FlattenedDecryptResult, + KeyLike, + FlattenedJWE, + JWEHeaderParameters, + DecryptOptions, + GetKeyFunction, + ResolvedKey, +} from '../../types.d.ts' +import { encoder, decoder, concat } from '../../lib/buffer_utils.ts' +import generateCek from '../../lib/cek.ts' +import validateCrit from '../../lib/validate_crit.ts' +import validateAlgorithms from '../../lib/validate_algorithms.ts' + +/** + * Interface for Flattened JWE Decryption dynamic key resolution. No token components have been + * verified at the time of this function call. + */ +export interface FlattenedDecryptGetKey + extends GetKeyFunction {} + +/** + * Decrypts a Flattened JWE. + * + * @example Usage + * + * ```js + * const jwe = { + * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', + * iv: '8Fy7A_IuoX5VXG9s', + * tag: 'W76IYV6arGRuDSaSyWrQNg', + * encrypted_key: + * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', + * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', + * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', + * } + * + * const { plaintext, protectedHeader, additionalAuthenticatedData } = + * await jose.flattenedDecrypt(jwe, privateKey) + * + * console.log(protectedHeader) + * const decoder = new TextDecoder() + * console.log(decoder.decode(plaintext)) + * console.log(decoder.decode(additionalAuthenticatedData)) + * ``` + * + * @param jwe Flattened JWE. + * @param key Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export function flattenedDecrypt( + jwe: FlattenedJWE, + key: KeyLike | Uint8Array, + options?: DecryptOptions, +): Promise +/** + * @param jwe Flattened JWE. + * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export function flattenedDecrypt( + jwe: FlattenedJWE, + getKey: FlattenedDecryptGetKey, + options?: DecryptOptions, +): Promise +export async function flattenedDecrypt( + jwe: FlattenedJWE, + key: KeyLike | Uint8Array | FlattenedDecryptGetKey, + options?: DecryptOptions, +) { + if (!isObject(jwe)) { + throw new JWEInvalid('Flattened JWE must be an object') + } + + if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { + throw new JWEInvalid('JOSE Header missing') + } + + if (typeof jwe.iv !== 'string') { + throw new JWEInvalid('JWE Initialization Vector missing or incorrect type') + } + + if (typeof jwe.ciphertext !== 'string') { + throw new JWEInvalid('JWE Ciphertext missing or incorrect type') + } + + if (typeof jwe.tag !== 'string') { + throw new JWEInvalid('JWE Authentication Tag missing or incorrect type') + } + + if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { + throw new JWEInvalid('JWE Protected Header incorrect type') + } + + if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { + throw new JWEInvalid('JWE Encrypted Key incorrect type') + } + + if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { + throw new JWEInvalid('JWE AAD incorrect type') + } + + if (jwe.header !== undefined && !isObject(jwe.header)) { + throw new JWEInvalid('JWE Shared Unprotected Header incorrect type') + } + + if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) { + throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type') + } + + let parsedProt!: JWEHeaderParameters + if (jwe.protected) { + try { + const protectedHeader = base64url(jwe.protected) + parsedProt = JSON.parse(decoder.decode(protectedHeader)) + } catch { + throw new JWEInvalid('JWE Protected Header is invalid') + } + } + if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) { + throw new JWEInvalid( + 'JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint', + ) + } + + const joseHeader: JWEHeaderParameters = { + ...parsedProt, + ...jwe.header, + ...jwe.unprotected, + } + + validateCrit(JWEInvalid, new Map(), options?.crit, parsedProt, joseHeader) + + if (joseHeader.zip !== undefined) { + if (!parsedProt || !parsedProt.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected') + } + + if (joseHeader.zip !== 'DEF') { + throw new JOSENotSupported( + 'Unsupported JWE "zip" (Compression Algorithm) Header Parameter value', + ) + } + } + + const { alg, enc } = joseHeader + + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header') + } + + if (typeof enc !== 'string' || !enc) { + throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header') + } + + const keyManagementAlgorithms = + options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms) + const contentEncryptionAlgorithms = + options && + validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms) + + if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed') + } + + if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { + throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed') + } + + let encryptedKey!: Uint8Array + if (jwe.encrypted_key !== undefined) { + encryptedKey = base64url(jwe.encrypted_key!) + } + + let resolvedKey = false + if (typeof key === 'function') { + key = await key(parsedProt, jwe) + resolvedKey = true + } + + let cek: KeyLike | Uint8Array + try { + cek = await decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) + } catch (err) { + if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { + throw err + } + // https://www.rfc-editor.org/rfc/rfc7516#section-11.5 + // To mitigate the attacks described in RFC 3218, the + // recipient MUST NOT distinguish between format, padding, and length + // errors of encrypted keys. It is strongly recommended, in the event + // of receiving an improperly formatted key, that the recipient + // substitute a randomly generated CEK and proceed to the next step, to + // mitigate timing attacks. + cek = generateCek(enc) + } + + const iv = base64url(jwe.iv) + const tag = base64url(jwe.tag) + + const protectedHeader: Uint8Array = encoder.encode(jwe.protected ?? '') + let additionalData: Uint8Array + + if (jwe.aad !== undefined) { + additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(jwe.aad)) + } else { + additionalData = protectedHeader + } + + let plaintext = await decrypt(enc, cek, base64url(jwe.ciphertext), iv, tag, additionalData) + + if (joseHeader.zip === 'DEF') { + plaintext = await (options?.inflateRaw || inflate)(plaintext) + } + + const result: FlattenedDecryptResult = { plaintext } + + if (jwe.protected !== undefined) { + result.protectedHeader = parsedProt + } + + if (jwe.aad !== undefined) { + result.additionalAuthenticatedData = base64url(jwe.aad!) + } + + if (jwe.unprotected !== undefined) { + result.sharedUnprotectedHeader = jwe.unprotected + } + + if (jwe.header !== undefined) { + result.unprotectedHeader = jwe.header + } + + if (resolvedKey) { + return { ...result, key } + } + + return result +} diff --git a/dist/deno/jwe/flattened/encrypt.ts b/dist/deno/jwe/flattened/encrypt.ts new file mode 100644 index 0000000000..966af35b25 --- /dev/null +++ b/dist/deno/jwe/flattened/encrypt.ts @@ -0,0 +1,309 @@ +import { encode as base64url } from '../../runtime/base64url.ts' +import encrypt from '../../runtime/encrypt.ts' +import { deflate } from '../../runtime/zlib.ts' + +import type { + KeyLike, + FlattenedJWE, + JWEHeaderParameters, + JWEKeyManagementHeaderParameters, + EncryptOptions, +} from '../../types.d.ts' +import generateIv from '../../lib/iv.ts' +import encryptKeyManagement from '../../lib/encrypt_key_management.ts' +import { JOSENotSupported, JWEInvalid } from '../../util/errors.ts' +import isDisjoint from '../../lib/is_disjoint.ts' +import { encoder, decoder, concat } from '../../lib/buffer_utils.ts' +import validateCrit from '../../lib/validate_crit.ts' + +/** @private */ +export const unprotected = Symbol() + +/** + * The FlattenedEncrypt class is a utility for creating Flattened JWE objects. + * + * @example Usage + * + * ```js + * const jwe = await new jose.FlattenedEncrypt( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) + * .setAdditionalAuthenticatedData(encoder.encode('The Fellowship of the Ring')) + * .encrypt(publicKey) + * + * console.log(jwe) + * ``` + */ +export class FlattenedEncrypt { + private _plaintext: Uint8Array + + private _protectedHeader!: JWEHeaderParameters + + private _sharedUnprotectedHeader!: JWEHeaderParameters + + private _unprotectedHeader!: JWEHeaderParameters + + private _aad!: Uint8Array + + private _cek!: Uint8Array + + private _iv!: Uint8Array + + private _keyManagementParameters!: JWEKeyManagementHeaderParameters + + /** @param plaintext Binary representation of the plaintext to encrypt. */ + constructor(plaintext: Uint8Array) { + if (!(plaintext instanceof Uint8Array)) { + throw new TypeError('plaintext must be an instance of Uint8Array') + } + this._plaintext = plaintext + } + + /** + * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is + * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or + * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed + * and missing. + * + * @param parameters JWE Key Management parameters. + */ + setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once') + } + this._keyManagementParameters = parameters + return this + } + + /** + * Sets the JWE Protected Header on the FlattenedEncrypt object. + * + * @param protectedHeader JWE Protected Header. + */ + setProtectedHeader(protectedHeader: JWEHeaderParameters) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once') + } + this._protectedHeader = protectedHeader + return this + } + + /** + * Sets the JWE Shared Unprotected Header on the FlattenedEncrypt object. + * + * @param sharedUnprotectedHeader JWE Shared Unprotected Header. + */ + setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters) { + if (this._sharedUnprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once') + } + this._sharedUnprotectedHeader = sharedUnprotectedHeader + return this + } + + /** + * Sets the JWE Per-Recipient Unprotected Header on the FlattenedEncrypt object. + * + * @param unprotectedHeader JWE Per-Recipient Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once') + } + this._unprotectedHeader = unprotectedHeader + return this + } + + /** + * Sets the Additional Authenticated Data on the FlattenedEncrypt object. + * + * @param aad Additional Authenticated Data. + */ + setAdditionalAuthenticatedData(aad: Uint8Array) { + this._aad = aad + return this + } + + /** + * Sets a content encryption key to use, by default a random suitable one is generated for the JWE + * enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param cek JWE Content Encryption Key. + */ + setContentEncryptionKey(cek: Uint8Array) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once') + } + this._cek = cek + return this + } + + /** + * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable + * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param iv JWE Initialization Vector. + */ + setInitializationVector(iv: Uint8Array) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once') + } + this._iv = iv + return this + } + + /** + * Encrypts and resolves the value of the Flattened JWE object. + * + * @param key Public Key or Secret to encrypt the JWE with. + * @param options JWE Encryption options. + */ + async encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions) { + if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { + throw new JWEInvalid( + 'either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()', + ) + } + + if ( + !isDisjoint(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader) + ) { + throw new JWEInvalid( + 'JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint', + ) + } + + const joseHeader: JWEHeaderParameters = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...this._sharedUnprotectedHeader, + } + + validateCrit(JWEInvalid, new Map(), options?.crit, this._protectedHeader, joseHeader) + + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected') + } + + if (joseHeader.zip !== 'DEF') { + throw new JOSENotSupported( + 'Unsupported JWE "zip" (Compression Algorithm) Header Parameter value', + ) + } + } + + const { alg, enc } = joseHeader + + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid') + } + + if (typeof enc !== 'string' || !enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid') + } + + let encryptedKey: Uint8Array | undefined + + if (alg === 'dir') { + if (this._cek) { + throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption') + } + } else if (alg === 'ECDH-ES') { + if (this._cek) { + throw new TypeError( + 'setContentEncryptionKey cannot be called when using Direct Key Agreement', + ) + } + } + + let cek: KeyLike | Uint8Array + { + let parameters: { [propName: string]: unknown } | undefined + ;({ cek, encryptedKey, parameters } = await encryptKeyManagement( + alg, + enc, + key, + this._cek, + this._keyManagementParameters, + )) + + if (parameters) { + if (options && unprotected in options) { + if (!this._unprotectedHeader) { + this.setUnprotectedHeader(parameters) + } else { + this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters } + } + } else { + if (!this._protectedHeader) { + this.setProtectedHeader(parameters) + } else { + this._protectedHeader = { ...this._protectedHeader, ...parameters } + } + } + } + } + + this._iv ||= generateIv(enc) + + let additionalData: Uint8Array + let protectedHeader: Uint8Array + let aadMember: string | undefined + if (this._protectedHeader) { + protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))) + } else { + protectedHeader = encoder.encode('') + } + + if (this._aad) { + aadMember = base64url(this._aad) + additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember)) + } else { + additionalData = protectedHeader + } + + let ciphertext: Uint8Array + let tag: Uint8Array + + if (joseHeader.zip === 'DEF') { + const deflated = await (options?.deflateRaw || deflate)(this._plaintext) + ;({ ciphertext, tag } = await encrypt(enc, deflated, cek, this._iv, additionalData)) + } else { + ;({ ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData)) + } + + const jwe: FlattenedJWE = { + ciphertext: base64url(ciphertext), + iv: base64url(this._iv), + tag: base64url(tag), + } + + if (encryptedKey) { + jwe.encrypted_key = base64url(encryptedKey) + } + + if (aadMember) { + jwe.aad = aadMember + } + + if (this._protectedHeader) { + jwe.protected = decoder.decode(protectedHeader) + } + + if (this._sharedUnprotectedHeader) { + jwe.unprotected = this._sharedUnprotectedHeader + } + + if (this._unprotectedHeader) { + jwe.header = this._unprotectedHeader + } + + return jwe + } +} diff --git a/dist/deno/jwe/general/decrypt.ts b/dist/deno/jwe/general/decrypt.ts new file mode 100644 index 0000000000..c674f3b99b --- /dev/null +++ b/dist/deno/jwe/general/decrypt.ts @@ -0,0 +1,107 @@ +import { flattenedDecrypt } from '../flattened/decrypt.ts' +import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.ts' +import type { + KeyLike, + DecryptOptions, + JWEHeaderParameters, + GetKeyFunction, + FlattenedJWE, + GeneralJWE, + GeneralDecryptResult, + ResolvedKey, +} from '../../types.d.ts' +import isObject from '../../lib/is_object.ts' + +/** + * Interface for General JWE Decryption dynamic key resolution. No token components have been + * verified at the time of this function call. + */ +export interface GeneralDecryptGetKey extends GetKeyFunction {} + +/** + * Decrypts a General JWE. + * + * @example Usage + * + * ```js + * const jwe = { + * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', + * iv: '8Fy7A_IuoX5VXG9s', + * tag: 'W76IYV6arGRuDSaSyWrQNg', + * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', + * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', + * recipients: [ + * { + * encrypted_key: + * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', + * }, + * ], + * } + * + * const { plaintext, protectedHeader, additionalAuthenticatedData } = + * await jose.generalDecrypt(jwe, privateKey) + * + * console.log(protectedHeader) + * const decoder = new TextDecoder() + * console.log(decoder.decode(plaintext)) + * console.log(decoder.decode(additionalAuthenticatedData)) + * ``` + * + * @param jwe General JWE. + * @param key Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export function generalDecrypt( + jwe: GeneralJWE, + key: KeyLike | Uint8Array, + options?: DecryptOptions, +): Promise +/** + * @param jwe General JWE. + * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export function generalDecrypt( + jwe: GeneralJWE, + getKey: GeneralDecryptGetKey, + options?: DecryptOptions, +): Promise +export async function generalDecrypt( + jwe: GeneralJWE, + key: KeyLike | Uint8Array | GeneralDecryptGetKey, + options?: DecryptOptions, +) { + if (!isObject(jwe)) { + throw new JWEInvalid('General JWE must be an object') + } + + if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { + throw new JWEInvalid('JWE Recipients missing or incorrect type') + } + + if (!jwe.recipients.length) { + throw new JWEInvalid('JWE Recipients has no members') + } + + for (const recipient of jwe.recipients) { + try { + return await flattenedDecrypt( + { + aad: jwe.aad, + ciphertext: jwe.ciphertext, + encrypted_key: recipient.encrypted_key, + header: recipient.header, + iv: jwe.iv, + protected: jwe.protected, + tag: jwe.tag, + unprotected: jwe.unprotected, + }, + [1]>key, + options, + ) + } catch { + // + } + } + throw new JWEDecryptionFailed() +} diff --git a/dist/deno/jwe/general/encrypt.ts b/dist/deno/jwe/general/encrypt.ts new file mode 100644 index 0000000000..e97d976f29 --- /dev/null +++ b/dist/deno/jwe/general/encrypt.ts @@ -0,0 +1,306 @@ +import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.ts' +import { JWEInvalid } from '../../util/errors.ts' +import generateCek from '../../lib/cek.ts' +import isDisjoint from '../../lib/is_disjoint.ts' +import encryptKeyManagement from '../../lib/encrypt_key_management.ts' +import { encode as base64url } from '../../runtime/base64url.ts' +import validateCrit from '../../lib/validate_crit.ts' + +import type { + KeyLike, + GeneralJWE, + JWEHeaderParameters, + CritOption, + DeflateOption, +} from '../../types.d.ts' + +export interface Recipient { + /** + * Sets the JWE Per-Recipient Unprotected Header on the Recipient object. + * + * @param unprotectedHeader JWE Per-Recipient Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters): Recipient + + /** A shorthand for calling addRecipient() on the enclosing GeneralEncrypt instance */ + addRecipient(...args: Parameters): Recipient + + /** A shorthand for calling encrypt() on the enclosing GeneralEncrypt instance */ + encrypt(...args: Parameters): Promise + + /** Returns the enclosing GeneralEncrypt */ + done(): GeneralEncrypt +} + +class IndividualRecipient implements Recipient { + private parent: GeneralEncrypt + unprotectedHeader?: JWEHeaderParameters + key: KeyLike | Uint8Array + options: CritOption + + constructor(enc: GeneralEncrypt, key: KeyLike | Uint8Array, options: CritOption) { + this.parent = enc + this.key = key + this.options = options + } + + setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once') + } + this.unprotectedHeader = unprotectedHeader + return this + } + + addRecipient(...args: Parameters) { + return this.parent.addRecipient(...args) + } + + encrypt(...args: Parameters) { + return this.parent.encrypt(...args) + } + + done() { + return this.parent + } +} + +/** + * The GeneralEncrypt class is a utility for creating General JWE objects. + * + * @example Usage + * + * ```js + * const jwe = await new jose.GeneralEncrypt( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ enc: 'A256GCM' }) + * .addRecipient(ecPublicKey) + * .setUnprotectedHeader({ alg: 'ECDH-ES+A256KW' }) + * .addRecipient(rsaPublicKey) + * .setUnprotectedHeader({ alg: 'RSA-OAEP-384' }) + * .encrypt() + * + * console.log(jwe) + * ``` + */ +export class GeneralEncrypt { + private _plaintext: Uint8Array + + private _recipients: IndividualRecipient[] = [] + + private _protectedHeader!: JWEHeaderParameters + + private _unprotectedHeader!: JWEHeaderParameters + + private _aad!: Uint8Array + + /** @param plaintext Binary representation of the plaintext to encrypt. */ + constructor(plaintext: Uint8Array) { + this._plaintext = plaintext + } + + /** + * Adds an additional recipient for the General JWE object. + * + * @param key Public Key or Secret to encrypt the Content Encryption Key for the recipient with. + * @param options JWE Encryption options. + */ + addRecipient(key: KeyLike | Uint8Array, options?: CritOption): Recipient { + const recipient = new IndividualRecipient(this, key, { crit: options?.crit }) + this._recipients.push(recipient) + return recipient + } + + /** + * Sets the JWE Protected Header on the GeneralEncrypt object. + * + * @param protectedHeader JWE Protected Header object. + */ + setProtectedHeader(protectedHeader: JWEHeaderParameters): this { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once') + } + this._protectedHeader = protectedHeader + return this + } + + /** + * Sets the JWE Shared Unprotected Header on the GeneralEncrypt object. + * + * @param sharedUnprotectedHeader JWE Shared Unprotected Header object. + */ + setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters): this { + if (this._unprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once') + } + this._unprotectedHeader = sharedUnprotectedHeader + return this + } + + /** + * Sets the Additional Authenticated Data on the GeneralEncrypt object. + * + * @param aad Additional Authenticated Data. + */ + setAdditionalAuthenticatedData(aad: Uint8Array) { + this._aad = aad + return this + } + + /** + * Encrypts and resolves the value of the General JWE object. + * + * @param options JWE Encryption options. + */ + async encrypt(options?: DeflateOption): Promise { + if (!this._recipients.length) { + throw new JWEInvalid('at least one recipient must be added') + } + + options = { deflateRaw: options?.deflateRaw } + + if (this._recipients.length === 1) { + const [recipient] = this._recipients + + const flattened = await new FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader!) + .encrypt(recipient.key, { ...recipient.options, ...options }) + + let jwe: GeneralJWE = { + ciphertext: flattened.ciphertext, + iv: flattened.iv, + recipients: [{}], + tag: flattened.tag, + } + + if (flattened.aad) jwe.aad = flattened.aad + if (flattened.protected) jwe.protected = flattened.protected + if (flattened.unprotected) jwe.unprotected = flattened.unprotected + if (flattened.encrypted_key) jwe.recipients![0].encrypted_key = flattened.encrypted_key + if (flattened.header) jwe.recipients![0].header = flattened.header + + return jwe + } + + let enc!: string + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i] + if ( + !isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader) + ) { + throw new JWEInvalid( + 'JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint', + ) + } + + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + } + + const { alg } = joseHeader + + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid') + } + + if (alg === 'dir' || alg === 'ECDH-ES') { + throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient') + } + + if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid') + } + + if (!enc) { + enc = joseHeader.enc + } else if (enc !== joseHeader.enc) { + throw new JWEInvalid( + 'JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients', + ) + } + + validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader) + + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid( + 'JWE "zip" (Compression Algorithm) Header MUST be integrity protected', + ) + } + } + } + + const cek = generateCek(enc) + + let jwe: GeneralJWE = { + ciphertext: '', + iv: '', + recipients: [], + tag: '', + } + + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i] + const target: Record = {} + jwe.recipients!.push(target) + + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + } + + const p2c = joseHeader.alg!.startsWith('PBES2') ? 2048 + i : undefined + + if (i === 0) { + const flattened = await new FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setContentEncryptionKey(cek) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader!) + .setKeyManagementParameters({ p2c }) + .encrypt(recipient.key, { + ...recipient.options, + ...options, + // @ts-expect-error + [unprotected]: true, + }) + + jwe.ciphertext = flattened.ciphertext + jwe.iv = flattened.iv + jwe.tag = flattened.tag + + if (flattened.aad) jwe.aad = flattened.aad + if (flattened.protected) jwe.protected = flattened.protected + if (flattened.unprotected) jwe.unprotected = flattened.unprotected + + target.encrypted_key = flattened.encrypted_key! + if (flattened.header) target.header = flattened.header + + continue + } + + const { encryptedKey, parameters } = await encryptKeyManagement( + recipient.unprotectedHeader?.alg! || + this._protectedHeader?.alg! || + this._unprotectedHeader?.alg!, + enc, + recipient.key, + cek, + { p2c }, + ) + target.encrypted_key = base64url(encryptedKey!) + if (recipient.unprotectedHeader || parameters) + target.header = { ...recipient.unprotectedHeader, ...parameters } + } + + return jwe + } +} diff --git a/dist/deno/jwk/embedded.ts b/dist/deno/jwk/embedded.ts new file mode 100644 index 0000000000..2a69bc0a2c --- /dev/null +++ b/dist/deno/jwk/embedded.ts @@ -0,0 +1,46 @@ +import type { KeyLike, FlattenedJWSInput, JWSHeaderParameters } from '../types.d.ts' +import { importJWK } from '../key/import.ts' +import isObject from '../lib/is_object.ts' +import { JWSInvalid } from '../util/errors.ts' + +/** + * EmbeddedJWK is an implementation of a GetKeyFunction intended to be used with the JWS/JWT verify + * operations whenever you need to opt-in to verify signatures with a public key embedded in the + * token's "jwk" (JSON Web Key) Header Parameter. It is recommended to combine this with the verify + * function's `algorithms` option to define accepted JWS "alg" (Algorithm) Header Parameter values. + * + * @example Usage + * + * ```js + * const jwt = + * 'eyJqd2siOnsiY3J2IjoiUC0yNTYiLCJ4IjoiVU05ZzVuS25aWFlvdldBbE03NmNMejl2VG96UmpfX0NIVV9kT2wtZ09vRSIsInkiOiJkczhhZVF3MWwyY0RDQTdiQ2tPTnZ3REtwWEFidFhqdnFDbGVZSDhXc19VIiwia3R5IjoiRUMifSwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSIsImlhdCI6MTYwNDU4MDc5NH0.60boak3_dErnW47ZPty1C0nrjeVq86EN_eK0GOq6K8w2OA0thKoBxFK4j-NuU9yZ_A9UKGxPT_G87DladBaV9g' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, jose.EmbeddedJWK, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + */ +export async function EmbeddedJWK( + protectedHeader: JWSHeaderParameters, + token: FlattenedJWSInput, +): Promise { + const joseHeader = { + ...protectedHeader, + ...token.header, + } + if (!isObject(joseHeader.jwk)) { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object') + } + + const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg!, true) + + if (key instanceof Uint8Array || key.type !== 'public') { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key') + } + + return key +} diff --git a/dist/deno/jwk/thumbprint.ts b/dist/deno/jwk/thumbprint.ts new file mode 100644 index 0000000000..2e5f410b1f --- /dev/null +++ b/dist/deno/jwk/thumbprint.ts @@ -0,0 +1,114 @@ +import digest from '../runtime/digest.ts' +import { encode as base64url } from '../runtime/base64url.ts' + +import { JOSENotSupported, JWKInvalid } from '../util/errors.ts' +import { encoder } from '../lib/buffer_utils.ts' +import type { JWK } from '../types.d.ts' +import isObject from '../lib/is_object.ts' + +const check = (value: unknown, description: string) => { + if (typeof value !== 'string' || !value) { + throw new JWKInvalid(`${description} missing or invalid`) + } +} + +/** + * Calculates a base64url-encoded JSON Web Key (JWK) Thumbprint + * + * @example Usage + * + * ```js + * const thumbprint = await jose.calculateJwkThumbprint({ + * kty: 'EC', + * crv: 'P-256', + * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', + * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', + * }) + * + * console.log(thumbprint) + * // 'w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' + * ``` + * + * @param jwk JSON Web Key. + * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is + * "sha256". + * @see [RFC7638](https://www.rfc-editor.org/rfc/rfc7638) + */ +export async function calculateJwkThumbprint( + jwk: JWK, + digestAlgorithm?: 'sha256' | 'sha384' | 'sha512', +): Promise { + if (!isObject(jwk)) { + throw new TypeError('JWK must be an object') + } + + digestAlgorithm ??= 'sha256' + + if ( + digestAlgorithm !== 'sha256' && + digestAlgorithm !== 'sha384' && + digestAlgorithm !== 'sha512' + ) { + throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"') + } + + let components: JWK + switch (jwk.kty) { + case 'EC': + check(jwk.crv, '"crv" (Curve) Parameter') + check(jwk.x, '"x" (X Coordinate) Parameter') + check(jwk.y, '"y" (Y Coordinate) Parameter') + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y } + break + case 'OKP': + check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter') + check(jwk.x, '"x" (Public Key) Parameter') + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x } + break + case 'RSA': + check(jwk.e, '"e" (Exponent) Parameter') + check(jwk.n, '"n" (Modulus) Parameter') + components = { e: jwk.e, kty: jwk.kty, n: jwk.n } + break + case 'oct': + check(jwk.k, '"k" (Key Value) Parameter') + components = { k: jwk.k, kty: jwk.kty } + break + default: + throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported') + } + + const data = encoder.encode(JSON.stringify(components)) + return base64url(await digest(digestAlgorithm, data)) +} + +/** + * Calculates a JSON Web Key (JWK) Thumbprint URI + * + * @example Usage + * + * ```js + * const thumbprintUri = await jose.calculateJwkThumbprintUri({ + * kty: 'EC', + * crv: 'P-256', + * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', + * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', + * }) + * + * console.log(thumbprint) + * // 'urn:ietf:params:oauth:jwk-thumbprint:sha-256:w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' + * ``` + * + * @param jwk JSON Web Key. + * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is + * "sha256". + * @see [RFC9278](https://www.rfc-editor.org/rfc/rfc9278) + */ +export async function calculateJwkThumbprintUri( + jwk: JWK, + digestAlgorithm?: 'sha256' | 'sha384' | 'sha512', +): Promise { + digestAlgorithm ??= 'sha256' + const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm) + return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}` +} diff --git a/dist/deno/jwks/local.ts b/dist/deno/jwks/local.ts new file mode 100644 index 0000000000..b9693be1bf --- /dev/null +++ b/dist/deno/jwks/local.ts @@ -0,0 +1,245 @@ +import type { + KeyLike, + JWSHeaderParameters, + JWK, + JSONWebKeySet, + FlattenedJWSInput, +} from '../types.d.ts' +import { importJWK } from '../key/import.ts' +import { + JWKSInvalid, + JOSENotSupported, + JWKSNoMatchingKey, + JWKSMultipleMatchingKeys, +} from '../util/errors.ts' +import isObject from '../lib/is_object.ts' + +function getKtyFromAlg(alg: unknown) { + switch (typeof alg === 'string' && alg.slice(0, 2)) { + case 'RS': + case 'PS': + return 'RSA' + case 'ES': + return 'EC' + case 'Ed': + return 'OKP' + default: + throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set') + } +} + +interface Cache { + [alg: string]: KeyLike +} + +/** @private */ +export function isJWKSLike(jwks: unknown): jwks is JSONWebKeySet { + return ( + jwks && + typeof jwks === 'object' && + // @ts-expect-error + Array.isArray(jwks.keys) && + // @ts-expect-error + jwks.keys.every(isJWKLike) + ) +} + +function isJWKLike(key: unknown) { + return isObject(key) +} + +function clone(obj: T): T { + // @ts-ignore + if (typeof structuredClone === 'function') { + // @ts-ignore + return structuredClone(obj) + } + + return JSON.parse(JSON.stringify(obj)) +} + +/** @private */ +export class LocalJWKSet { + protected _jwks?: JSONWebKeySet + + private _cached: WeakMap = new WeakMap() + + constructor(jwks: unknown) { + if (!isJWKSLike(jwks)) { + throw new JWKSInvalid('JSON Web Key Set malformed') + } + + this._jwks = clone(jwks) + } + + async getKey(protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise { + const { alg, kid } = { ...protectedHeader, ...token?.header } + const kty = getKtyFromAlg(alg) + + const candidates = this._jwks!.keys.filter((jwk) => { + // filter keys based on the mapping of signature algorithms to Key Type + let candidate = kty === jwk.kty + + // filter keys based on the JWK Key ID in the header + if (candidate && typeof kid === 'string') { + candidate = kid === jwk.kid + } + + // filter keys based on the key's declared Algorithm + if (candidate && typeof jwk.alg === 'string') { + candidate = alg === jwk.alg + } + + // filter keys based on the key's declared Public Key Use + if (candidate && typeof jwk.use === 'string') { + candidate = jwk.use === 'sig' + } + + // filter keys based on the key's declared Key Operations + if (candidate && Array.isArray(jwk.key_ops)) { + candidate = jwk.key_ops.includes('verify') + } + + // filter out non-applicable OKP Sub Types + if (candidate && alg === 'EdDSA') { + candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448' + } + + // filter out non-applicable EC curves + if (candidate) { + switch (alg) { + case 'ES256': + candidate = jwk.crv === 'P-256' + break + case 'ES256K': + candidate = jwk.crv === 'secp256k1' + break + case 'ES384': + candidate = jwk.crv === 'P-384' + break + case 'ES512': + candidate = jwk.crv === 'P-521' + break + } + } + + return candidate + }) + + const { 0: jwk, length } = candidates + + if (length === 0) { + throw new JWKSNoMatchingKey() + } else if (length !== 1) { + const error = new JWKSMultipleMatchingKeys() + + const { _cached } = this + error[Symbol.asyncIterator] = async function* () { + for (const jwk of candidates) { + try { + yield await importWithAlgCache(_cached, jwk, alg!) + } catch { + continue + } + } + } + + throw error + } + + return importWithAlgCache(this._cached, jwk, alg!) + } +} + +async function importWithAlgCache(cache: WeakMap, jwk: JWK, alg: string) { + const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk)! + if (cached[alg] === undefined) { + const keyObject = await importJWK({ ...jwk, ext: true }, alg) + + if (keyObject.type !== 'public') { + throw new JWKSInvalid('JSON Web Key Set members must be public keys') + } + + cached[alg] = keyObject + } + + return cached[alg] +} + +/** + * Returns a function that resolves to a key object from a locally stored, or otherwise available, + * JSON Web Key Set. + * + * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), + * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if + * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key + * Operations) Parameters (if they are present on the JWK). + * + * Only a single public key must match the selection process. As shown in the example below when + * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt + * verification in an iterative manner. + * + * @example Usage + * + * ```js + * const JWKS = jose.createLocalJWKSet({ + * keys: [ + * { + * kty: 'RSA', + * e: 'AQAB', + * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', + * alg: 'PS256', + * }, + * { + * crv: 'P-256', + * kty: 'EC', + * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', + * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', + * alg: 'ES256', + * }, + * ], + * }) + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Opting-in to multiple JWKS matches using `createLocalJWKSet` + * + * ```js + * const options = { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * } + * const { payload, protectedHeader } = await jose + * .jwtVerify(jwt, JWKS, options) + * .catch(async (error) => { + * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { + * for await (const publicKey of error) { + * try { + * return await jose.jwtVerify(jwt, publicKey, options) + * } catch (innerError) { + * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { + * continue + * } + * throw innerError + * } + * } + * throw new jose.errors.JWSSignatureVerificationFailed() + * } + * + * throw error + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwks JSON Web Key Set formatted object. + */ +export function createLocalJWKSet(jwks: JSONWebKeySet) { + return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)) +} diff --git a/dist/deno/jwks/remote.ts b/dist/deno/jwks/remote.ts new file mode 100644 index 0000000000..1a67595572 --- /dev/null +++ b/dist/deno/jwks/remote.ts @@ -0,0 +1,204 @@ +import fetchJwks from '../runtime/fetch_jwks.ts' +import { isCloudflareWorkers } from '../runtime/env.ts' + +import type { KeyLike, JWSHeaderParameters, FlattenedJWSInput } from '../types.d.ts' +import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.ts' + +import { isJWKSLike, LocalJWKSet } from './local.ts' + +/** Options for the remote JSON Web Key Set. */ +export interface RemoteJWKSetOptions { + /** + * Timeout (in milliseconds) for the HTTP request. When reached the request will be aborted and + * the verification will fail. Default is 5000 (5 seconds). + */ + timeoutDuration?: number + + /** + * Duration (in milliseconds) for which no more HTTP requests will be triggered after a previous + * successful fetch. Default is 30000 (30 seconds). + */ + cooldownDuration?: number + + /** + * Maximum time (in milliseconds) between successful HTTP requests. Default is 600000 (10 + * minutes). + */ + cacheMaxAge?: number | typeof Infinity + + /** + * An instance of [http.Agent](https://nodejs.org/api/http.html#class-httpagent) or + * [https.Agent](https://nodejs.org/api/https.html#class-httpsagent) to pass to the + * [http.get](https://nodejs.org/api/http.html#httpgetoptions-callback) or + * [https.get](https://nodejs.org/api/https.html#httpsgetoptions-callback) method's options. Use + * when behind an http(s) proxy. This is a Node.js runtime specific option, it is ignored when + * used outside of Node.js runtime. + */ + agent?: any + + /** Optional headers to be sent with the HTTP request. */ + headers?: Record +} + +class RemoteJWKSet extends LocalJWKSet { + private _url: URL + + private _timeoutDuration: number + + private _cooldownDuration: number + + private _cacheMaxAge: number + + private _jwksTimestamp?: number + + private _pendingFetch?: Promise + + private _options: Pick + + constructor(url: unknown, options?: RemoteJWKSetOptions) { + super({ keys: [] }) + + this._jwks = undefined + + if (!(url instanceof URL)) { + throw new TypeError('url must be an instance of URL') + } + this._url = new URL(url.href) + this._options = { agent: options?.agent, headers: options?.headers } + this._timeoutDuration = + typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000 + this._cooldownDuration = + typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000 + this._cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000 + } + + coolingDown() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cooldownDuration + : false + } + + fresh() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cacheMaxAge + : false + } + + async getKey(protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise { + if (!this._jwks || !this.fresh()) { + await this.reload() + } + + try { + return await super.getKey(protectedHeader, token) + } catch (err) { + if (err instanceof JWKSNoMatchingKey) { + if (this.coolingDown() === false) { + await this.reload() + return super.getKey(protectedHeader, token) + } + } + throw err + } + } + + async reload() { + // see https://github.com/panva/jose/issues/355 + if (this._pendingFetch && isCloudflareWorkers()) { + return new Promise((resolve) => { + const isDone = () => { + if (this._pendingFetch === undefined) { + resolve() + } else { + setTimeout(isDone, 5) + } + } + isDone() + }) + } + + if (!this._pendingFetch) { + this._pendingFetch = fetchJwks(this._url, this._timeoutDuration, this._options) + .then((json) => { + if (!isJWKSLike(json)) { + throw new JWKSInvalid('JSON Web Key Set malformed') + } + + this._jwks = { keys: json.keys } + this._jwksTimestamp = Date.now() + this._pendingFetch = undefined + }) + .catch((err: Error) => { + this._pendingFetch = undefined + throw err + }) + } + + await this._pendingFetch + } +} + +/** + * Returns a function that resolves to a key object downloaded from a remote endpoint returning a + * JSON Web Key Set, that is, for example, an OAuth 2.0 or OIDC jwks_uri. The JSON Web Key Set is + * fetched when no key matches the selection process but only as frequently as the + * `cooldownDuration` option allows to prevent abuse. + * + * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), + * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if + * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key + * Operations) Parameters (if they are present on the JWK). + * + * Only a single public key must match the selection process. As shown in the example below when + * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt + * verification in an iterative manner. + * + * @example Usage + * + * ```js + * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Opting-in to multiple JWKS matches using `createRemoteJWKSet` + * + * ```js + * const options = { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * } + * const { payload, protectedHeader } = await jose + * .jwtVerify(jwt, JWKS, options) + * .catch(async (error) => { + * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { + * for await (const publicKey of error) { + * try { + * return await jose.jwtVerify(jwt, publicKey, options) + * } catch (innerError) { + * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { + * continue + * } + * throw innerError + * } + * } + * throw new jose.errors.JWSSignatureVerificationFailed() + * } + * + * throw error + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param url URL to fetch the JSON Web Key Set from. + * @param options Options for the remote JSON Web Key Set. + */ +export function createRemoteJWKSet(url: URL, options?: RemoteJWKSetOptions) { + return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)) +} diff --git a/dist/deno/jws/compact/sign.ts b/dist/deno/jws/compact/sign.ts new file mode 100644 index 0000000000..339858f58b --- /dev/null +++ b/dist/deno/jws/compact/sign.ts @@ -0,0 +1,52 @@ +import { FlattenedSign } from '../flattened/sign.ts' +import type { CompactJWSHeaderParameters, KeyLike, SignOptions } from '../../types.d.ts' + +/** + * The CompactSign class is a utility for creating Compact JWS strings. + * + * @example Usage + * + * ```js + * const jws = await new jose.CompactSign( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'ES256' }) + * .sign(privateKey) + * + * console.log(jws) + * ``` + */ +export class CompactSign { + private _flattened: FlattenedSign + + /** @param payload Binary representation of the payload to sign. */ + constructor(payload: Uint8Array) { + this._flattened = new FlattenedSign(payload) + } + + /** + * Sets the JWS Protected Header on the Sign object. + * + * @param protectedHeader JWS Protected Header. + */ + setProtectedHeader(protectedHeader: CompactJWSHeaderParameters) { + this._flattened.setProtectedHeader(protectedHeader) + return this + } + + /** + * Signs and resolves the value of the Compact JWS string. + * + * @param key Private Key or Secret to sign the JWS with. + * @param options JWS Sign options. + */ + async sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise { + const jws = await this._flattened.sign(key, options) + + if (jws.payload === undefined) { + throw new TypeError('use the flattened module for creating JWS with b64: false') + } + + return `${jws.protected}.${jws.payload}.${jws.signature}` + } +} diff --git a/dist/deno/jws/compact/verify.ts b/dist/deno/jws/compact/verify.ts new file mode 100644 index 0000000000..026de73ff0 --- /dev/null +++ b/dist/deno/jws/compact/verify.ts @@ -0,0 +1,90 @@ +import { flattenedVerify } from '../flattened/verify.ts' +import { JWSInvalid } from '../../util/errors.ts' +import { decoder } from '../../lib/buffer_utils.ts' +import type { + CompactVerifyResult, + FlattenedJWSInput, + GetKeyFunction, + CompactJWSHeaderParameters, + KeyLike, + VerifyOptions, + ResolvedKey, +} from '../../types.d.ts' + +/** + * Interface for Compact JWS Verification dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface CompactVerifyGetKey + extends GetKeyFunction {} + +/** + * Verifies the signature and format of and afterwards decodes the Compact JWS. + * + * @example Usage + * + * ```js + * const jws = + * 'eyJhbGciOiJFUzI1NiJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4.kkAs_gPPxWMI3rHuVlxHaTPfDWDoqdI8jSvuSmqV-8IHIWXg9mcAeC9ggV-45ZHRbiRJ3obUIFo1rHphPA5URg' + * + * const { payload, protectedHeader } = await jose.compactVerify(jws, publicKey) + * + * console.log(protectedHeader) + * console.log(new TextDecoder().decode(payload)) + * ``` + * + * @param jws Compact JWS. + * @param key Key to verify the JWS with. + * @param options JWS Verify options. + */ +export function compactVerify( + jws: string | Uint8Array, + key: KeyLike | Uint8Array, + options?: VerifyOptions, +): Promise +/** + * @param jws Compact JWS. + * @param getKey Function resolving a key to verify the JWS with. + * @param options JWS Verify options. + */ +export function compactVerify( + jws: string | Uint8Array, + getKey: CompactVerifyGetKey, + options?: VerifyOptions, +): Promise +export async function compactVerify( + jws: string | Uint8Array, + key: KeyLike | Uint8Array | CompactVerifyGetKey, + options?: VerifyOptions, +) { + if (jws instanceof Uint8Array) { + jws = decoder.decode(jws) + } + + if (typeof jws !== 'string') { + throw new JWSInvalid('Compact JWS must be a string or Uint8Array') + } + const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.') + + if (length !== 3) { + throw new JWSInvalid('Invalid Compact JWS') + } + + const verified = await flattenedVerify( + { payload, protected: protectedHeader, signature }, + [1]>key, + options, + ) + + const result = { payload: verified.payload, protectedHeader: verified.protectedHeader! } + + if (typeof key === 'function') { + return { ...result, key: verified.key } + } + + return result +} diff --git a/dist/deno/jws/flattened/sign.ts b/dist/deno/jws/flattened/sign.ts new file mode 100644 index 0000000000..57f2353ce7 --- /dev/null +++ b/dist/deno/jws/flattened/sign.ts @@ -0,0 +1,152 @@ +import { encode as base64url } from '../../runtime/base64url.ts' +import sign from '../../runtime/sign.ts' + +import isDisjoint from '../../lib/is_disjoint.ts' +import { JWSInvalid } from '../../util/errors.ts' +import { encoder, decoder, concat } from '../../lib/buffer_utils.ts' +import type { KeyLike, FlattenedJWS, JWSHeaderParameters, SignOptions } from '../../types.d.ts' +import checkKeyType from '../../lib/check_key_type.ts' +import validateCrit from '../../lib/validate_crit.ts' + +/** + * The FlattenedSign class is a utility for creating Flattened JWS objects. + * + * @example Usage + * + * ```js + * const jws = await new jose.FlattenedSign( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'ES256' }) + * .sign(privateKey) + * + * console.log(jws) + * ``` + */ +export class FlattenedSign { + private _payload: Uint8Array + + private _protectedHeader!: JWSHeaderParameters + + private _unprotectedHeader!: JWSHeaderParameters + + /** @param payload Binary representation of the payload to sign. */ + constructor(payload: Uint8Array) { + if (!(payload instanceof Uint8Array)) { + throw new TypeError('payload must be an instance of Uint8Array') + } + this._payload = payload + } + + /** + * Sets the JWS Protected Header on the FlattenedSign object. + * + * @param protectedHeader JWS Protected Header. + */ + setProtectedHeader(protectedHeader: JWSHeaderParameters) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once') + } + this._protectedHeader = protectedHeader + return this + } + + /** + * Sets the JWS Unprotected Header on the FlattenedSign object. + * + * @param unprotectedHeader JWS Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once') + } + this._unprotectedHeader = unprotectedHeader + return this + } + + /** + * Signs and resolves the value of the Flattened JWS object. + * + * @param key Private Key or Secret to sign the JWS with. + * @param options JWS Sign options. + */ + async sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise { + if (!this._protectedHeader && !this._unprotectedHeader) { + throw new JWSInvalid( + 'either setProtectedHeader or setUnprotectedHeader must be called before #sign()', + ) + } + + if (!isDisjoint(this._protectedHeader, this._unprotectedHeader)) { + throw new JWSInvalid( + 'JWS Protected and JWS Unprotected Header Parameter names must be disjoint', + ) + } + + const joseHeader: JWSHeaderParameters = { + ...this._protectedHeader, + ...this._unprotectedHeader, + } + + const extensions = validateCrit( + JWSInvalid, + new Map([['b64', true]]), + options?.crit, + this._protectedHeader, + joseHeader, + ) + + let b64: boolean = true + if (extensions.has('b64')) { + b64 = this._protectedHeader.b64! + if (typeof b64 !== 'boolean') { + throw new JWSInvalid( + 'The "b64" (base64url-encode payload) Header Parameter must be a boolean', + ) + } + } + + const { alg } = joseHeader + + if (typeof alg !== 'string' || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid') + } + + checkKeyType(alg, key, 'sign') + + let payload = this._payload + if (b64) { + payload = encoder.encode(base64url(payload)) + } + + let protectedHeader: Uint8Array + if (this._protectedHeader) { + protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))) + } else { + protectedHeader = encoder.encode('') + } + + const data = concat(protectedHeader, encoder.encode('.'), payload) + + const signature = await sign(alg, key, data) + + const jws: FlattenedJWS = { + signature: base64url(signature), + payload: '', + } + + if (b64) { + jws.payload = decoder.decode(payload) + } + + if (this._unprotectedHeader) { + jws.header = this._unprotectedHeader + } + + if (this._protectedHeader) { + jws.protected = decoder.decode(protectedHeader) + } + + return jws + } +} diff --git a/dist/deno/jws/flattened/verify.ts b/dist/deno/jws/flattened/verify.ts new file mode 100644 index 0000000000..6f9f5eda68 --- /dev/null +++ b/dist/deno/jws/flattened/verify.ts @@ -0,0 +1,203 @@ +import { decode as base64url } from '../../runtime/base64url.ts' +import verify from '../../runtime/verify.ts' + +import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.ts' +import { concat, encoder, decoder } from '../../lib/buffer_utils.ts' +import isDisjoint from '../../lib/is_disjoint.ts' +import isObject from '../../lib/is_object.ts' +import checkKeyType from '../../lib/check_key_type.ts' +import validateCrit from '../../lib/validate_crit.ts' +import validateAlgorithms from '../../lib/validate_algorithms.ts' + +import type { + FlattenedVerifyResult, + KeyLike, + FlattenedJWSInput, + JWSHeaderParameters, + VerifyOptions, + GetKeyFunction, + ResolvedKey, +} from '../../types.d.ts' + +/** + * Interface for Flattened JWS Verification dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface FlattenedVerifyGetKey + extends GetKeyFunction {} + +/** + * Verifies the signature and format of and afterwards decodes the Flattened JWS. + * + * @example Usage + * + * ```js + * const decoder = new TextDecoder() + * const jws = { + * signature: + * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', + * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', + * protected: 'eyJhbGciOiJFUzI1NiJ9', + * } + * + * const { payload, protectedHeader } = await jose.flattenedVerify(jws, publicKey) + * + * console.log(protectedHeader) + * console.log(decoder.decode(payload)) + * ``` + * + * @param jws Flattened JWS. + * @param key Key to verify the JWS with. + * @param options JWS Verify options. + */ +export function flattenedVerify( + jws: FlattenedJWSInput, + key: KeyLike | Uint8Array, + options?: VerifyOptions, +): Promise +/** + * @param jws Flattened JWS. + * @param getKey Function resolving a key to verify the JWS with. + * @param options JWS Verify options. + */ +export function flattenedVerify( + jws: FlattenedJWSInput, + getKey: FlattenedVerifyGetKey, + options?: VerifyOptions, +): Promise +export async function flattenedVerify( + jws: FlattenedJWSInput, + key: KeyLike | Uint8Array | FlattenedVerifyGetKey, + options?: VerifyOptions, +) { + if (!isObject(jws)) { + throw new JWSInvalid('Flattened JWS must be an object') + } + + if (jws.protected === undefined && jws.header === undefined) { + throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members') + } + + if (jws.protected !== undefined && typeof jws.protected !== 'string') { + throw new JWSInvalid('JWS Protected Header incorrect type') + } + + if (jws.payload === undefined) { + throw new JWSInvalid('JWS Payload missing') + } + + if (typeof jws.signature !== 'string') { + throw new JWSInvalid('JWS Signature missing or incorrect type') + } + + if (jws.header !== undefined && !isObject(jws.header)) { + throw new JWSInvalid('JWS Unprotected Header incorrect type') + } + + let parsedProt: JWSHeaderParameters = {} + if (jws.protected) { + try { + const protectedHeader = base64url(jws.protected) + parsedProt = JSON.parse(decoder.decode(protectedHeader)) + } catch { + throw new JWSInvalid('JWS Protected Header is invalid') + } + } + if (!isDisjoint(parsedProt, jws.header)) { + throw new JWSInvalid( + 'JWS Protected and JWS Unprotected Header Parameter names must be disjoint', + ) + } + + const joseHeader: JWSHeaderParameters = { + ...parsedProt, + ...jws.header, + } + + const extensions = validateCrit( + JWSInvalid, + new Map([['b64', true]]), + options?.crit, + parsedProt, + joseHeader, + ) + + let b64: boolean = true + if (extensions.has('b64')) { + b64 = parsedProt.b64! + if (typeof b64 !== 'boolean') { + throw new JWSInvalid( + 'The "b64" (base64url-encode payload) Header Parameter must be a boolean', + ) + } + } + + const { alg } = joseHeader + + if (typeof alg !== 'string' || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid') + } + + const algorithms = options && validateAlgorithms('algorithms', options.algorithms) + + if (algorithms && !algorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed') + } + + if (b64) { + if (typeof jws.payload !== 'string') { + throw new JWSInvalid('JWS Payload must be a string') + } + } else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { + throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance') + } + + let resolvedKey = false + if (typeof key === 'function') { + key = await key(parsedProt, jws) + resolvedKey = true + } + + checkKeyType(alg, key, 'verify') + + const data = concat( + encoder.encode(jws.protected ?? ''), + encoder.encode('.'), + typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload, + ) + const signature = base64url(jws.signature) + const verified = await verify(alg, key, signature, data) + + if (!verified) { + throw new JWSSignatureVerificationFailed() + } + + let payload: Uint8Array + if (b64) { + payload = base64url(jws.payload) + } else if (typeof jws.payload === 'string') { + payload = encoder.encode(jws.payload) + } else { + payload = jws.payload + } + + const result: FlattenedVerifyResult = { payload } + + if (jws.protected !== undefined) { + result.protectedHeader = parsedProt + } + + if (jws.header !== undefined) { + result.unprotectedHeader = jws.header + } + + if (resolvedKey) { + return { ...result, key } + } + + return result +} diff --git a/dist/deno/jws/general/sign.ts b/dist/deno/jws/general/sign.ts new file mode 100644 index 0000000000..0b3886e804 --- /dev/null +++ b/dist/deno/jws/general/sign.ts @@ -0,0 +1,143 @@ +import { FlattenedSign } from '../flattened/sign.ts' +import { JWSInvalid } from '../../util/errors.ts' + +import type { KeyLike, GeneralJWS, JWSHeaderParameters, SignOptions } from '../../types.d.ts' + +export interface Signature { + /** + * Sets the JWS Protected Header on the Signature object. + * + * @param protectedHeader JWS Protected Header. + */ + setProtectedHeader(protectedHeader: JWSHeaderParameters): Signature + + /** + * Sets the JWS Unprotected Header on the Signature object. + * + * @param unprotectedHeader JWS Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters): Signature + + /** A shorthand for calling addSignature() on the enclosing GeneralSign instance */ + addSignature(...args: Parameters): Signature + + /** A shorthand for calling encrypt() on the enclosing GeneralSign instance */ + sign(...args: Parameters): Promise + + /** Returns the enclosing GeneralSign */ + done(): GeneralSign +} + +class IndividualSignature implements Signature { + private parent: GeneralSign + + protectedHeader?: JWSHeaderParameters + unprotectedHeader?: JWSHeaderParameters + options?: SignOptions + key: KeyLike | Uint8Array + + constructor(sig: GeneralSign, key: KeyLike | Uint8Array, options?: SignOptions) { + this.parent = sig + this.key = key + this.options = options + } + + setProtectedHeader(protectedHeader: JWSHeaderParameters) { + if (this.protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once') + } + this.protectedHeader = protectedHeader + return this + } + + setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once') + } + this.unprotectedHeader = unprotectedHeader + return this + } + + addSignature(...args: Parameters) { + return this.parent.addSignature(...args) + } + + sign(...args: Parameters) { + return this.parent.sign(...args) + } + + done() { + return this.parent + } +} + +/** + * The GeneralSign class is a utility for creating General JWS objects. + * + * @example Usage + * + * ```js + * const jws = await new jose.GeneralSign( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .addSignature(ecPrivateKey) + * .setProtectedHeader({ alg: 'ES256' }) + * .addSignature(rsaPrivateKey) + * .setProtectedHeader({ alg: 'PS256' }) + * .sign() + * + * console.log(jws) + * ``` + */ +export class GeneralSign { + private _payload: Uint8Array + + private _signatures: IndividualSignature[] = [] + + /** @param payload Binary representation of the payload to sign. */ + constructor(payload: Uint8Array) { + this._payload = payload + } + + /** + * Adds an additional signature for the General JWS object. + * + * @param key Private Key or Secret to sign the individual JWS signature with. + * @param options JWS Sign options. + */ + addSignature(key: KeyLike | Uint8Array, options?: SignOptions): Signature { + const signature = new IndividualSignature(this, key, options) + this._signatures.push(signature) + return signature + } + + /** Signs and resolves the value of the General JWS object. */ + async sign(): Promise { + if (!this._signatures.length) { + throw new JWSInvalid('at least one signature must be added') + } + + const jws: GeneralJWS = { + signatures: [], + payload: '', + } + + for (let i = 0; i < this._signatures.length; i++) { + const signature = this._signatures[i] + const flattened = new FlattenedSign(this._payload) + + flattened.setProtectedHeader(signature.protectedHeader!) + flattened.setUnprotectedHeader(signature.unprotectedHeader!) + + const { payload, ...rest } = await flattened.sign(signature.key, signature.options) + if (i === 0) { + jws.payload = payload + } else if (jws.payload !== payload) { + throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)') + } + jws.signatures.push(rest) + } + + return jws + } +} diff --git a/dist/deno/jws/general/verify.ts b/dist/deno/jws/general/verify.ts new file mode 100644 index 0000000000..fa31fc7c76 --- /dev/null +++ b/dist/deno/jws/general/verify.ts @@ -0,0 +1,98 @@ +import { flattenedVerify } from '../flattened/verify.ts' +import type { + GeneralJWSInput, + GeneralVerifyResult, + FlattenedJWSInput, + GetKeyFunction, + JWSHeaderParameters, + KeyLike, + VerifyOptions, + ResolvedKey, +} from '../../types.d.ts' +import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.ts' +import isObject from '../../lib/is_object.ts' + +/** + * Interface for General JWS Verification dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface GeneralVerifyGetKey + extends GetKeyFunction {} + +/** + * Verifies the signature and format of and afterwards decodes the General JWS. + * + * @example Usage + * + * ```js + * const jws = { + * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', + * signatures: [ + * { + * signature: + * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', + * protected: 'eyJhbGciOiJFUzI1NiJ9', + * }, + * ], + * } + * + * const { payload, protectedHeader } = await jose.generalVerify(jws, publicKey) + * + * console.log(protectedHeader) + * console.log(new TextDecoder().decode(payload)) + * ``` + * + * @param jws General JWS. + * @param key Key to verify the JWS with. + * @param options JWS Verify options. + */ +export function generalVerify( + jws: GeneralJWSInput, + key: KeyLike | Uint8Array, + options?: VerifyOptions, +): Promise +/** + * @param jws General JWS. + * @param getKey Function resolving a key to verify the JWS with. + * @param options JWS Verify options. + */ +export function generalVerify( + jws: GeneralJWSInput, + getKey: GeneralVerifyGetKey, + options?: VerifyOptions, +): Promise +export async function generalVerify( + jws: GeneralJWSInput, + key: KeyLike | Uint8Array | GeneralVerifyGetKey, + options?: VerifyOptions, +) { + if (!isObject(jws)) { + throw new JWSInvalid('General JWS must be an object') + } + + if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { + throw new JWSInvalid('JWS Signatures missing or incorrect type') + } + + for (const signature of jws.signatures) { + try { + return await flattenedVerify( + { + header: signature.header, + payload: jws.payload, + protected: signature.protected, + signature: signature.signature, + }, + [1]>key, + options, + ) + } catch { + // + } + } + throw new JWSSignatureVerificationFailed() +} diff --git a/dist/deno/jwt/decrypt.ts b/dist/deno/jwt/decrypt.ts new file mode 100644 index 0000000000..d8aa32a4df --- /dev/null +++ b/dist/deno/jwt/decrypt.ts @@ -0,0 +1,108 @@ +import { compactDecrypt } from '../jwe/compact/decrypt.ts' +import type { + KeyLike, + DecryptOptions, + JWTClaimVerificationOptions, + GetKeyFunction, + CompactJWEHeaderParameters, + FlattenedJWE, + JWTDecryptResult, + ResolvedKey, +} from '../types.d.ts' +import jwtPayload from '../lib/jwt_claims_set.ts' +import { JWTClaimValidationFailed } from '../util/errors.ts' + +/** Combination of JWE Decryption options and JWT Claims Set verification options. */ +export interface JWTDecryptOptions extends DecryptOptions, JWTClaimVerificationOptions {} + +/** + * Interface for JWT Decryption dynamic key resolution. No token components have been verified at + * the time of this function call. + */ +export interface JWTDecryptGetKey + extends GetKeyFunction {} + +/** + * Verifies the JWT format (to be a JWE Compact format), decrypts the ciphertext, validates the JWT + * Claims Set. + * + * @example Usage + * + * ```js + * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') + * const jwt = + * 'eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..MB66qstZBPxAXKdsjet_lA.WHbtJTl4taHp7otOHLq3hBvv0yNPsPEKHYInmCPdDDeyV1kU-f-tGEiU4FxlSqkqAT2hVs8_wMNiQFAzPU1PUgIqWCPsBrPP3TtxYsrtwagpn4SvCsUsx0Mhw9ZhliAO8CLmCBQkqr_T9AcYsz5uZw.7nX9m7BGUu_u1p1qFHzyIg' + * + * const { payload, protectedHeader } = await jose.jwtDecrypt(jwt, secret, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwt JSON Web Token value (encoded as JWE). + * @param key Private Key or Secret to decrypt and verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export async function jwtDecrypt( + jwt: string | Uint8Array, + key: KeyLike | Uint8Array, + options?: JWTDecryptOptions, +): Promise +/** + * @param jwt JSON Web Token value (encoded as JWE). + * @param getKey Function resolving Private Key or Secret to decrypt and verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export async function jwtDecrypt( + jwt: string | Uint8Array, + getKey: JWTDecryptGetKey, + options?: JWTDecryptOptions, +): Promise +export async function jwtDecrypt( + jwt: string | Uint8Array, + key: KeyLike | Uint8Array | JWTDecryptGetKey, + options?: JWTDecryptOptions, +) { + const decrypted = await compactDecrypt(jwt, [1]>key, options) + const payload = jwtPayload(decrypted.protectedHeader, decrypted.plaintext, options) + + const { protectedHeader } = decrypted + + if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { + throw new JWTClaimValidationFailed( + 'replicated "iss" claim header parameter mismatch', + 'iss', + 'mismatch', + ) + } + + if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { + throw new JWTClaimValidationFailed( + 'replicated "sub" claim header parameter mismatch', + 'sub', + 'mismatch', + ) + } + + if ( + protectedHeader.aud !== undefined && + JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud) + ) { + throw new JWTClaimValidationFailed( + 'replicated "aud" claim header parameter mismatch', + 'aud', + 'mismatch', + ) + } + + const result = { payload, protectedHeader } + + if (typeof key === 'function') { + return { ...result, key: decrypted.key } + } + + return result +} diff --git a/dist/deno/jwt/encrypt.ts b/dist/deno/jwt/encrypt.ts new file mode 100644 index 0000000000..de3cc6df1e --- /dev/null +++ b/dist/deno/jwt/encrypt.ts @@ -0,0 +1,162 @@ +import { CompactEncrypt } from '../jwe/compact/encrypt.ts' +import type { + EncryptOptions, + CompactJWEHeaderParameters, + JWEKeyManagementHeaderParameters, + KeyLike, +} from '../types.d.ts' +import { encoder } from '../lib/buffer_utils.ts' +import { ProduceJWT } from './produce.ts' + +/** + * The EncryptJWT class is a utility for creating Compact JWE formatted JWT strings. + * + * @example Usage + * + * ```js + * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') + * const jwt = await new jose.EncryptJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg: 'dir', enc: 'A128CBC-HS256' }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .encrypt(secret) + * + * console.log(jwt) + * ``` + */ +export class EncryptJWT extends ProduceJWT { + private _cek!: Uint8Array + + private _iv!: Uint8Array + + private _keyManagementParameters!: JWEKeyManagementHeaderParameters + + private _protectedHeader!: CompactJWEHeaderParameters + + private _replicateIssuerAsHeader!: boolean + + private _replicateSubjectAsHeader!: boolean + + private _replicateAudienceAsHeader!: boolean + + /** + * Sets the JWE Protected Header on the EncryptJWT object. + * + * @param protectedHeader JWE Protected Header. Must contain an "alg" (JWE Algorithm) and "enc" + * (JWE Encryption Algorithm) properties. + */ + setProtectedHeader(protectedHeader: CompactJWEHeaderParameters) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once') + } + this._protectedHeader = protectedHeader + return this + } + + /** + * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is + * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or + * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed + * and missing. + * + * @param parameters JWE Key Management parameters. + */ + setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once') + } + this._keyManagementParameters = parameters + return this + } + + /** + * Sets a content encryption key to use, by default a random suitable one is generated for the JWE + * enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param cek JWE Content Encryption Key. + */ + setContentEncryptionKey(cek: Uint8Array) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once') + } + this._cek = cek + return this + } + + /** + * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable + * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param iv JWE Initialization Vector. + */ + setInitializationVector(iv: Uint8Array) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once') + } + this._iv = iv + return this + } + + /** + * Replicates the "iss" (Issuer) Claim as a JWE Protected Header Parameter as per + * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). + */ + replicateIssuerAsHeader() { + this._replicateIssuerAsHeader = true + return this + } + + /** + * Replicates the "sub" (Subject) Claim as a JWE Protected Header Parameter as per + * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). + */ + replicateSubjectAsHeader() { + this._replicateSubjectAsHeader = true + return this + } + + /** + * Replicates the "aud" (Audience) Claim as a JWE Protected Header Parameter as per + * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). + */ + replicateAudienceAsHeader() { + this._replicateAudienceAsHeader = true + return this + } + + /** + * Encrypts and returns the JWT. + * + * @param key Public Key or Secret to encrypt the JWT with. + * @param options JWE Encryption options. + */ + async encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise { + const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))) + if (this._replicateIssuerAsHeader) { + this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss } + } + if (this._replicateSubjectAsHeader) { + this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub } + } + if (this._replicateAudienceAsHeader) { + this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud } + } + enc.setProtectedHeader(this._protectedHeader) + if (this._iv) { + enc.setInitializationVector(this._iv) + } + if (this._cek) { + enc.setContentEncryptionKey(this._cek) + } + if (this._keyManagementParameters) { + enc.setKeyManagementParameters(this._keyManagementParameters) + } + return enc.encrypt(key, options) + } +} diff --git a/dist/deno/jwt/produce.ts b/dist/deno/jwt/produce.ts new file mode 100644 index 0000000000..5fd7defddf --- /dev/null +++ b/dist/deno/jwt/produce.ts @@ -0,0 +1,104 @@ +import type { JWTPayload } from '../types.d.ts' +import epoch from '../lib/epoch.ts' +import isObject from '../lib/is_object.ts' +import secs from '../lib/secs.ts' + +/** Generic class for JWT producing. */ +export class ProduceJWT { + protected _payload!: JWTPayload + + /** @param payload The JWT Claims Set object. */ + constructor(payload: JWTPayload) { + if (!isObject(payload)) { + throw new TypeError('JWT Claims Set MUST be an object') + } + this._payload = payload + } + + /** + * Set "iss" (Issuer) Claim. + * + * @param issuer "Issuer" Claim value to set on the JWT Claims Set. + */ + setIssuer(issuer: string) { + this._payload = { ...this._payload, iss: issuer } + return this + } + + /** + * Set "sub" (Subject) Claim. + * + * @param subject "sub" (Subject) Claim value to set on the JWT Claims Set. + */ + setSubject(subject: string) { + this._payload = { ...this._payload, sub: subject } + return this + } + + /** + * Set "aud" (Audience) Claim. + * + * @param audience "aud" (Audience) Claim value to set on the JWT Claims Set. + */ + setAudience(audience: string | string[]) { + this._payload = { ...this._payload, aud: audience } + return this + } + + /** + * Set "jti" (JWT ID) Claim. + * + * @param jwtId "jti" (JWT ID) Claim value to set on the JWT Claims Set. + */ + setJti(jwtId: string) { + this._payload = { ...this._payload, jti: jwtId } + return this + } + + /** + * Set "nbf" (Not Before) Claim. + * + * @param input "nbf" (Not Before) Claim value to set on the JWT Claims Set. When number is passed + * that is used as a value, when string is passed it is resolved to a time span and added to the + * current timestamp. + */ + setNotBefore(input: number | string) { + if (typeof input === 'number') { + this._payload = { ...this._payload, nbf: input } + } else { + this._payload = { ...this._payload, nbf: epoch(new Date()) + secs(input) } + } + return this + } + + /** + * Set "exp" (Expiration Time) Claim. + * + * @param input "exp" (Expiration Time) Claim value to set on the JWT Claims Set. When number is + * passed that is used as a value, when string is passed it is resolved to a time span and added + * to the current timestamp. + */ + setExpirationTime(input: number | string) { + if (typeof input === 'number') { + this._payload = { ...this._payload, exp: input } + } else { + this._payload = { ...this._payload, exp: epoch(new Date()) + secs(input) } + } + return this + } + + /** + * Set "iat" (Issued At) Claim. + * + * @param input "iat" (Issued At) Claim value to set on the JWT Claims Set. Default is current + * timestamp. + */ + setIssuedAt(input?: number) { + if (typeof input === 'undefined') { + this._payload = { ...this._payload, iat: epoch(new Date()) } + } else { + this._payload = { ...this._payload, iat: input } + } + return this + } +} diff --git a/dist/deno/jwt/sign.ts b/dist/deno/jwt/sign.ts new file mode 100644 index 0000000000..d7f9761a19 --- /dev/null +++ b/dist/deno/jwt/sign.ts @@ -0,0 +1,134 @@ +import { CompactSign } from '../jws/compact/sign.ts' +import { JWTInvalid } from '../util/errors.ts' +import type { JWTHeaderParameters, KeyLike, SignOptions } from '../types.d.ts' +import { encoder } from '../lib/buffer_utils.ts' +import { ProduceJWT } from './produce.ts' + +/** + * The SignJWT class is a utility for creating Compact JWS formatted JWT strings. + * + * @example Usage with a symmetric secret + * + * ```js + * const secret = new TextEncoder().encode( + * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', + * ) + * const alg = 'HS256' + * + * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .sign(secret) + * + * console.log(jwt) + * ``` + * + * @example Usage with a private PKCS#8 encoded RSA key + * + * ```js + * const alg = 'RS256' + * const pkcs8 = `-----BEGIN PRIVATE KEY----- + * MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCFg4UrY5xtulv + * /NXKmL1J4qI1SopAfTNMo3X7p+kJO7plqUYjzaztcre1qfh0m33Sm1Q8oPbO/GpP + * MU1/HgcceytgJ/b4UwufVVMl9BrMDYG8moDBylbVupFQS3Ly1L9i/iFG9Z9A9xzY + * Zzf799A45bnvNXL6s2glzvjiRvfQ2NDF0anTcnZLcYtC7ugq1IMM+ihAcPfw8Qw2 + * chN/SmP4qAM+PKaQwagmU7doqmmyN9u38AfoYZ1GCFhEs5TBBT6H6h9YdHeVtiIq + * 1c+fl03biSIfLrV7dUBD39gBmXBcL/30Ya3D82mCEUC4zg/UkOfQOmkmV3Lc8YUL + * QZ8EJkBLAgMBAAECggEAVuVE/KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34ls + * VOPK0XDegZkhAybMZHjRhp+gwVxX5ChC+J3cUpOBH5FNxElgW6HizD2Jcq6t6LoL + * YgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG/qJV1K00/Ly1G1QKoBffEs + * +v4fAMJrCbUdCz1qWto+PU+HLMEo+krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq/ + * aAP4a1SXmo+j0cvRU4W5Fj0RVwNesIpetX2ZFz4p/JmB5sWFEj/fC7h5z2lq+6Bm + * e2T3BHtXkIxoBW0/pYVnASC8P2puO5FnVxDmWuHDYQKBgQDTuuBd3+0tSFVEX+DU + * 5qpFmHm5nyGItZRJTS+71yg5pBxq1KqNCUjAtbxR0q//fwauakh+BwRVCPOrqsUG + * jBSb3NYE70Srp6elqxgkE54PwQx4Mr6exJPnseM9U4K+hULllf5yjM9edreJE1nV + * NVgFjeyafQhrHKwgr7PERJ/ikwKBgQDqqsT1M+EJLmI1HtCspOG6cu7q3gf/wKRh + * E8tu84i3YyBnI8uJkKy92RNVI5fvpBARe3tjSdM25rr2rcrcmF/5g6Q9ImxZPGCt + * 86eOgO9ErNtbc4TEgybsP319UE4O41aKeNiBTAZKoYCxv/dMqG0j4avmWzd+foHq + * gSNUvR2maQKBgQCYeqOsV2B6VPY7KIVFLd0AA9/dwvEmgAYLiA/RShDI+hwQ/5jX + * uxDu37KAhqeC65sHLrmIMUt4Zdr+DRyZK3aIDNEAesPMjw/X6lCXYp1ZISD2yyym + * MFGH8X8CIkstI9Faf9vf6PJKSFrC1/HA7wq17VCwrUzLvrljTMW8meM/CwKBgCpo + * 2leGHLFQFKeM/iF1WuYbR1pi7gcmhY6VyTowARFDdOOu8GXYI5/bz0afvCGvAMho + * DJCREv7lC/zww6zCTPYG+HOj+PjXlJFba3ixjIxYwPvyEJiDK1Ge18sB7Fl8dHNq + * C5ayaqCqN1voWYUdGzxU2IA1E/5kVo5O8FesJeOhAoGBAImJbZFf+D5kA32Xxhac + * 59lLWBCsocvvbd1cvDMNlRywAAyhsCb1SuX4nEAK9mrSBdfmoF2Nm3eilfsOds0f + * K5mX069IKG82CMqh3Mzptd7e7lyb9lsoGO0BAtjho3cWtha/UZ70vfaMzGuZ6JmQ + * ak6k+8+UFd93M4z0Qo74OhXB + * -----END PRIVATE KEY-----` + * const privateKey = await jose.importPKCS8(pkcs8, alg) + * + * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .sign(privateKey) + * + * console.log(jwt) + * ``` + * + * @example Usage with a private JWK encoded RSA key + * + * ```js + * const alg = 'RS256' + * const jwk = { + * kty: 'RSA', + * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', + * e: 'AQAB', + * d: 'VuVE_KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34lsVOPK0XDegZkhAybMZHjRhp-gwVxX5ChC-J3cUpOBH5FNxElgW6HizD2Jcq6t6LoLYgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG_qJV1K00_Ly1G1QKoBffEs-v4fAMJrCbUdCz1qWto-PU-HLMEo-krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq_aAP4a1SXmo-j0cvRU4W5Fj0RVwNesIpetX2ZFz4p_JmB5sWFEj_fC7h5z2lq-6Bme2T3BHtXkIxoBW0_pYVnASC8P2puO5FnVxDmWuHDYQ', + * p: '07rgXd_tLUhVRF_g1OaqRZh5uZ8hiLWUSU0vu9coOaQcatSqjQlIwLW8UdKv_38GrmpIfgcEVQjzq6rFBowUm9zWBO9Eq6enpasYJBOeD8EMeDK-nsST57HjPVOCvoVC5ZX-cozPXna3iRNZ1TVYBY3smn0IaxysIK-zxESf4pM', + * q: '6qrE9TPhCS5iNR7QrKThunLu6t4H_8CkYRPLbvOIt2MgZyPLiZCsvdkTVSOX76QQEXt7Y0nTNua69q3K3Jhf-YOkPSJsWTxgrfOnjoDvRKzbW3OExIMm7D99fVBODuNWinjYgUwGSqGAsb_3TKhtI-Gr5ls3fn6B6oEjVL0dpmk', + * dp: 'mHqjrFdgelT2OyiFRS3dAAPf3cLxJoAGC4gP0UoQyPocEP-Y17sQ7t-ygIanguubBy65iDFLeGXa_g0cmSt2iAzRAHrDzI8P1-pQl2KdWSEg9ssspjBRh_F_AiJLLSPRWn_b3-jySkhawtfxwO8Kte1QsK1My765Y0zFvJnjPws', + * dq: 'KmjaV4YcsVAUp4z-IXVa5htHWmLuByaFjpXJOjABEUN0467wZdgjn9vPRp-8Ia8AyGgMkJES_uUL_PDDrMJM9gb4c6P4-NeUkVtreLGMjFjA-_IQmIMrUZ7XywHsWXx0c2oLlrJqoKo3W-hZhR0bPFTYgDUT_mRWjk7wV6wl46E', + * qi: 'iYltkV_4PmQDfZfGFpzn2UtYEKyhy-9t3Vy8Mw2VHLAADKGwJvVK5ficQAr2atIF1-agXY2bd6KV-w52zR8rmZfTr0gobzYIyqHczOm13t7uXJv2WygY7QEC2OGjdxa2Fr9RnvS99ozMa5nomZBqTqT7z5QV33czjPRCjvg6FcE', + * } + * const privateKey = await jose.importJWK(jwk, alg) + * + * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .sign(privateKey) + * + * console.log(jwt) + * ``` + */ +export class SignJWT extends ProduceJWT { + private _protectedHeader!: JWTHeaderParameters + + /** + * Sets the JWS Protected Header on the SignJWT object. + * + * @param protectedHeader JWS Protected Header. Must contain an "alg" (JWS Algorithm) property. + */ + setProtectedHeader(protectedHeader: JWTHeaderParameters) { + this._protectedHeader = protectedHeader + return this + } + + /** + * Signs and returns the JWT. + * + * @param key Private Key or Secret to sign the JWT with. + * @param options JWT Sign options. + */ + async sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise { + const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))) + sig.setProtectedHeader(this._protectedHeader) + if ( + Array.isArray(this._protectedHeader?.crit) && + this._protectedHeader.crit.includes('b64') && + // @ts-expect-error + this._protectedHeader.b64 === false + ) { + throw new JWTInvalid('JWTs MUST NOT use unencoded payload') + } + return sig.sign(key, options) + } +} diff --git a/dist/deno/jwt/unsecured.ts b/dist/deno/jwt/unsecured.ts new file mode 100644 index 0000000000..771ed2375e --- /dev/null +++ b/dist/deno/jwt/unsecured.ts @@ -0,0 +1,78 @@ +import * as base64url from '../runtime/base64url.ts' + +import type { JWSHeaderParameters, JWTClaimVerificationOptions, JWTPayload } from '../types.d.ts' +import { decoder } from '../lib/buffer_utils.ts' +import { JWTInvalid } from '../util/errors.ts' +import jwtPayload from '../lib/jwt_claims_set.ts' +import { ProduceJWT } from './produce.ts' + +export interface UnsecuredResult { + payload: JWTPayload + header: JWSHeaderParameters +} + +/** + * The UnsecuredJWT class is a utility for dealing with `{ "alg": "none" }` Unsecured JWTs. + * + * @example Encoding + * + * ```js + * const unsecuredJwt = new jose.UnsecuredJWT({ 'urn:example:claim': true }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .encode() + * + * console.log(unsecuredJwt) + * ``` + * + * @example Decoding + * + * ```js + * const payload = jose.UnsecuredJWT.decode(jwt, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(payload) + * ``` + */ +export class UnsecuredJWT extends ProduceJWT { + /** Encodes the Unsecured JWT. */ + encode(): string { + const header = base64url.encode(JSON.stringify({ alg: 'none' })) + const payload = base64url.encode(JSON.stringify(this._payload)) + + return `${header}.${payload}.` + } + + /** + * Decodes an unsecured JWT. + * + * @param jwt Unsecured JWT to decode the payload of. + * @param options JWT Claims Set validation options. + */ + static decode(jwt: string, options?: JWTClaimVerificationOptions): UnsecuredResult { + if (typeof jwt !== 'string') { + throw new JWTInvalid('Unsecured JWT must be a string') + } + const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.') + + if (length !== 3 || signature !== '') { + throw new JWTInvalid('Invalid Unsecured JWT') + } + + let header: JWSHeaderParameters + try { + header = JSON.parse(decoder.decode(base64url.decode(encodedHeader))) + if (header.alg !== 'none') throw new Error() + } catch { + throw new JWTInvalid('Invalid Unsecured JWT') + } + + const payload = jwtPayload(header, base64url.decode(encodedPayload), options) + + return { payload, header } + } +} diff --git a/dist/deno/jwt/verify.ts b/dist/deno/jwt/verify.ts new file mode 100644 index 0000000000..e546a0f0c4 --- /dev/null +++ b/dist/deno/jwt/verify.ts @@ -0,0 +1,147 @@ +import { compactVerify } from '../jws/compact/verify.ts' +import type { + KeyLike, + VerifyOptions, + JWTClaimVerificationOptions, + JWTHeaderParameters, + GetKeyFunction, + FlattenedJWSInput, + JWTVerifyResult, + ResolvedKey, +} from '../types.d.ts' +import jwtPayload from '../lib/jwt_claims_set.ts' +import { JWTInvalid } from '../util/errors.ts' + +/** Combination of JWS Verification options and JWT Claims Set verification options. */ +export interface JWTVerifyOptions extends VerifyOptions, JWTClaimVerificationOptions {} + +/** + * Interface for JWT Verification dynamic key resolution. No token components have been verified at + * the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface JWTVerifyGetKey extends GetKeyFunction {} + +/** + * Verifies the JWT format (to be a JWS Compact format), verifies the JWS signature, validates the + * JWT Claims Set. + * + * @example Usage with a symmetric secret + * + * ```js + * const secret = new TextEncoder().encode( + * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', + * ) + * const jwt = + * 'eyJhbGciOiJIUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2MjMxLCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.C4iSlLfAUMBq--wnC6VqD9gEOhwpRZpoRarE0m7KEnI' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, secret, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Usage with a public SPKI encoded RSA key + * + * ```js + * const alg = 'RS256' + * const spki = `-----BEGIN PUBLIC KEY----- + * MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwhYOFK2Ocbbpb/zVypi9 + * SeKiNUqKQH0zTKN1+6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4H + * HHsrYCf2+FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS/Yv4hRvWfQPcc2Gc3+/fQ + * OOW57zVy+rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj + * +KgDPjymkMGoJlO3aKppsjfbt/AH6GGdRghYRLOUwQU+h+ofWHR3lbYiKtXPn5dN + * 24kiHy61e3VAQ9/YAZlwXC/99GGtw/NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZA + * SwIDAQAB + * -----END PUBLIC KEY-----` + * const publicKey = await jose.importSPKI(spki, alg) + * const jwt = + * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Usage with a public JWK encoded RSA key + * + * ```js + * const alg = 'RS256' + * const jwk = { + * kty: 'RSA', + * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', + * e: 'AQAB', + * } + * const publicKey = await jose.importJWK(jwk, alg) + * const jwt = + * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwt JSON Web Token value (encoded as JWS). + * @param key Key to verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export async function jwtVerify( + jwt: string | Uint8Array, + key: KeyLike | Uint8Array, + options?: JWTVerifyOptions, +): Promise + +/** + * @example Usage with a public JSON Web Key Set hosted on a remote URL + * + * ```js + * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwt JSON Web Token value (encoded as JWS). + * @param getKey Function resolving a key to verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export async function jwtVerify( + jwt: string | Uint8Array, + getKey: JWTVerifyGetKey, + options?: JWTVerifyOptions, +): Promise + +export async function jwtVerify( + jwt: string | Uint8Array, + key: KeyLike | Uint8Array | JWTVerifyGetKey, + options?: JWTVerifyOptions, +) { + const verified = await compactVerify(jwt, [1]>key, options) + if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) { + throw new JWTInvalid('JWTs MUST NOT use unencoded payload') + } + const payload = jwtPayload(verified.protectedHeader, verified.payload, options) + const result = { payload, protectedHeader: verified.protectedHeader } + if (typeof key === 'function') { + return { ...result, key: verified.key } + } + return result +} diff --git a/dist/deno/key/export.ts b/dist/deno/key/export.ts new file mode 100644 index 0000000000..2370835d0f --- /dev/null +++ b/dist/deno/key/export.ts @@ -0,0 +1,60 @@ +import { toSPKI as exportPublic } from '../runtime/asn1.ts' +import { toPKCS8 as exportPrivate } from '../runtime/asn1.ts' +import keyToJWK from '../runtime/key_to_jwk.ts' + +import type { JWK, KeyLike } from '../types.d.ts' + +/** + * Exports a runtime-specific public key representation (KeyObject or CryptoKey) to a PEM-encoded + * SPKI string format. + * + * @example Usage + * + * ```js + * const spkiPem = await jose.exportSPKI(publicKey) + * + * console.log(spkiPem) + * ``` + * + * @param key Key representation to transform to a PEM-encoded SPKI string format. + */ +export async function exportSPKI(key: KeyLike): Promise { + return exportPublic(key) +} + +/** + * Exports a runtime-specific private key representation (KeyObject or CryptoKey) to a PEM-encoded + * PKCS8 string format. + * + * @example Usage + * + * ```js + * const pkcs8Pem = await jose.exportPKCS8(privateKey) + * + * console.log(pkcs8Pem) + * ``` + * + * @param key Key representation to transform to a PEM-encoded PKCS8 string format. + */ +export async function exportPKCS8(key: KeyLike): Promise { + return exportPrivate(key) +} + +/** + * Exports a runtime-specific key representation (KeyLike) to a JWK. + * + * @example Usage + * + * ```js + * const privateJwk = await jose.exportJWK(privateKey) + * const publicJwk = await jose.exportJWK(publicKey) + * + * console.log(privateJwk) + * console.log(publicJwk) + * ``` + * + * @param key Key representation to export as JWK. + */ +export async function exportJWK(key: KeyLike | Uint8Array): Promise { + return keyToJWK(key) +} diff --git a/dist/deno/key/generate_key_pair.ts b/dist/deno/key/generate_key_pair.ts new file mode 100644 index 0000000000..a2e699e769 --- /dev/null +++ b/dist/deno/key/generate_key_pair.ts @@ -0,0 +1,57 @@ +import { generateKeyPair as generate } from '../runtime/generate.ts' + +import type { KeyLike } from '../types.d.ts' + +export interface GenerateKeyPairResult { + /** The generated Private Key. */ + privateKey: KeyLike + + /** Public Key corresponding to the generated Private Key. */ + publicKey: KeyLike +} + +export interface GenerateKeyPairOptions { + /** + * The EC "crv" (Curve) or OKP "crv" (Subtype of Key Pair) value to generate. The curve must be + * both supported on the runtime as well as applicable for the given JWA algorithm identifier. + */ + crv?: string + + /** + * A hint for RSA algorithms to generate an RSA key of a given `modulusLength` (Key size in bits). + * JOSE requires 2048 bits or larger. Default is 2048. + */ + modulusLength?: number + + /** + * (Only effective in Web Crypto API runtimes) The value to use as + * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) + * `extractable` argument. Default is false. + */ + extractable?: boolean +} + +/** + * Generates a private and a public key for a given JWA algorithm identifier. This can only generate + * asymmetric key pairs. For symmetric secrets use the `generateSecret` function. + * + * Note: Under Web Crypto API runtime the `privateKey` is generated with `extractable` set to + * `false` by default. + * + * @example Usage + * + * ```js + * const { publicKey, privateKey } = await jose.generateKeyPair('PS256') + * console.log(publicKey) + * console.log(privateKey) + * ``` + * + * @param alg JWA Algorithm Identifier to be used with the generated key pair. + * @param options Additional options passed down to the key pair generation. + */ +export async function generateKeyPair( + alg: string, + options?: GenerateKeyPairOptions, +): Promise { + return generate(alg, options) +} diff --git a/dist/deno/key/generate_secret.ts b/dist/deno/key/generate_secret.ts new file mode 100644 index 0000000000..ee9de48106 --- /dev/null +++ b/dist/deno/key/generate_secret.ts @@ -0,0 +1,35 @@ +import { generateSecret as generate } from '../runtime/generate.ts' + +import type { KeyLike } from '../types.d.ts' + +export interface GenerateSecretOptions { + /** + * (Only effective in Web Crypto API runtimes) The value to use as + * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) + * `extractable` argument. Default is false. + */ + extractable?: boolean +} + +/** + * Generates a symmetric secret key for a given JWA algorithm identifier. + * + * Note: Under Web Crypto API runtime the secret key is generated with `extractable` set to `false` + * by default. + * + * @example Usage + * + * ```js + * const secret = await jose.generateSecret('HS256') + * console.log(secret) + * ``` + * + * @param alg JWA Algorithm Identifier to be used with the generated secret. + * @param options Additional options passed down to the secret generation. + */ +export async function generateSecret( + alg: string, + options?: GenerateSecretOptions, +): Promise { + return generate(alg, options) +} diff --git a/dist/deno/key/import.ts b/dist/deno/key/import.ts new file mode 100644 index 0000000000..15415ff3e8 --- /dev/null +++ b/dist/deno/key/import.ts @@ -0,0 +1,193 @@ +import { decode as decodeBase64URL } from '../runtime/base64url.ts' +import { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.ts' +import asKeyObject from '../runtime/jwk_to_key.ts' + +import { JOSENotSupported } from '../util/errors.ts' +import isObject from '../lib/is_object.ts' +import type { JWK, KeyLike } from '../types.d.ts' + +export interface PEMImportOptions { + /** + * (Only effective in Web Crypto API runtimes) The value to use as + * [SubtleCrypto.importKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) + * `extractable` argument. Default is false. + */ + extractable?: boolean +} + +/** + * Imports a PEM-encoded SPKI string as a runtime-specific public key representation (KeyObject or + * CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to learn + * about key to algorithm requirements and mapping. + * + * @example Usage + * + * ```js + * const algorithm = 'ES256' + * const spki = `-----BEGIN PUBLIC KEY----- + * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM + * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== + * -----END PUBLIC KEY-----` + * const ecPublicKey = await jose.importSPKI(spki, algorithm) + * ``` + * + * @param pem PEM-encoded SPKI string + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key, its presence is only enforced in Web Crypto API runtimes. + */ +export async function importSPKI( + spki: string, + alg: string, + options?: PEMImportOptions, +): Promise { + if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { + throw new TypeError('"spki" must be SPKI formatted string') + } + return fromSPKI(spki, alg, options) +} + +/** + * Imports the SPKI from an X.509 string certificate as a runtime-specific public key representation + * (KeyObject or CryptoKey). See [Algorithm Key + * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm + * requirements and mapping. + * + * @example Usage + * + * ```js + * const algorithm = 'ES256' + * const x509 = `-----BEGIN CERTIFICATE----- + * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np + * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw + * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN + * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI + * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 + * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA + * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh + * v+A1QWZMuTWqYt+uh/YSRNDn + * -----END CERTIFICATE-----` + * const ecPublicKey = await jose.importX509(x509, algorithm) + * ``` + * + * @param pem X.509 certificate string + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key, its presence is only enforced in Web Crypto API runtimes. + */ +export async function importX509( + x509: string, + alg: string, + options?: PEMImportOptions, +): Promise { + if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { + throw new TypeError('"x509" must be X.509 formatted string') + } + return fromX509(x509, alg, options) +} + +/** + * Imports a PEM-encoded PKCS#8 string as a runtime-specific private key representation (KeyObject + * or CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to + * learn about key to algorithm requirements and mapping. Encrypted keys are not supported. + * + * @example Usage + * + * ```js + * const algorithm = 'ES256' + * const pkcs8 = `-----BEGIN PRIVATE KEY----- + * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN + * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg + * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa + * -----END PRIVATE KEY-----` + * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) + * ``` + * + * @param pem PEM-encoded PKCS#8 string + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key, its presence is only enforced in Web Crypto API runtimes. + */ +export async function importPKCS8( + pkcs8: string, + alg: string, + options?: PEMImportOptions, +): Promise { + if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { + throw new TypeError('"pkcs8" must be PKCS#8 formatted string') + } + return fromPKCS8(pkcs8, alg, options) +} + +/** + * Imports a JWK to a runtime-specific key representation (KeyLike). Either JWK "alg" (Algorithm) + * Parameter must be present or the optional "alg" argument. When running on a runtime using [Web + * Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) the jwk parameters "use", "key_ops", and + * "ext" are also used in the resulting `CryptoKey`. See [Algorithm Key + * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm + * requirements and mapping. + * + * @example Usage + * + * ```js + * const ecPublicKey = await jose.importJWK( + * { + * crv: 'P-256', + * kty: 'EC', + * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', + * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', + * }, + * 'ES256', + * ) + * + * const rsaPublicKey = await jose.importJWK( + * { + * kty: 'RSA', + * e: 'AQAB', + * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', + * }, + * 'PS256', + * ) + * ``` + * + * @param jwk JSON Web Key. + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key. Default is the "alg" property on the JWK, its presence is only enforced + * in Web Crypto API runtimes. + * @param octAsKeyObject Forces a symmetric key to be imported to a KeyObject or CryptoKey. Default + * is true unless JWK "ext" (Extractable) is true. + */ +export async function importJWK( + jwk: JWK, + alg?: string, + octAsKeyObject?: boolean, +): Promise { + if (!isObject(jwk)) { + throw new TypeError('JWK must be an object') + } + + alg ||= jwk.alg + + switch (jwk.kty) { + case 'oct': + if (typeof jwk.k !== 'string' || !jwk.k) { + throw new TypeError('missing "k" (Key Value) Parameter value') + } + + octAsKeyObject ??= jwk.ext !== true + + if (octAsKeyObject) { + return asKeyObject({ ...jwk, alg, ext: jwk.ext ?? false }) + } + + return decodeBase64URL(jwk.k) + case 'RSA': + if (jwk.oth !== undefined) { + throw new JOSENotSupported( + 'RSA JWK "oth" (Other Primes Info) Parameter value is not supported', + ) + } + case 'EC': + case 'OKP': + return asKeyObject({ ...jwk, alg }) + default: + throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value') + } +} diff --git a/dist/deno/lib/aesgcmkw.ts b/dist/deno/lib/aesgcmkw.ts new file mode 100644 index 0000000000..87d7013728 --- /dev/null +++ b/dist/deno/lib/aesgcmkw.ts @@ -0,0 +1,30 @@ +import encrypt from '../runtime/encrypt.ts' +import decrypt from '../runtime/decrypt.ts' +import generateIv from './iv.ts' +import { encode as base64url } from '../runtime/base64url.ts' + +export async function wrap(alg: string, key: unknown, cek: Uint8Array, iv?: Uint8Array) { + const jweAlgorithm = alg.slice(0, 7) + iv ||= generateIv(jweAlgorithm) + + const { ciphertext: encryptedKey, tag } = await encrypt( + jweAlgorithm, + cek, + key, + iv, + new Uint8Array(0), + ) + + return { encryptedKey, iv: base64url(iv), tag: base64url(tag) } +} + +export async function unwrap( + alg: string, + key: unknown, + encryptedKey: Uint8Array, + iv: Uint8Array, + tag: Uint8Array, +) { + const jweAlgorithm = alg.slice(0, 7) + return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)) +} diff --git a/dist/deno/lib/buffer_utils.ts b/dist/deno/lib/buffer_utils.ts new file mode 100644 index 0000000000..2c910c61cb --- /dev/null +++ b/dist/deno/lib/buffer_utils.ts @@ -0,0 +1,60 @@ +import digest from '../runtime/digest.ts' + +export const encoder = new TextEncoder() +export const decoder = new TextDecoder() + +const MAX_INT32 = 2 ** 32 + +export function concat(...buffers: Uint8Array[]): Uint8Array { + const size = buffers.reduce((acc, { length }) => acc + length, 0) + const buf = new Uint8Array(size) + let i = 0 + buffers.forEach((buffer) => { + buf.set(buffer, i) + i += buffer.length + }) + return buf +} + +export function p2s(alg: string, p2sInput: Uint8Array) { + return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput) +} + +function writeUInt32BE(buf: Uint8Array, value: number, offset?: number) { + if (value < 0 || value >= MAX_INT32) { + throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`) + } + buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset) +} + +export function uint64be(value: number) { + const high = Math.floor(value / MAX_INT32) + const low = value % MAX_INT32 + const buf = new Uint8Array(8) + writeUInt32BE(buf, high, 0) + writeUInt32BE(buf, low, 4) + return buf +} + +export function uint32be(value: number) { + const buf = new Uint8Array(4) + writeUInt32BE(buf, value) + return buf +} + +export function lengthAndInput(input: Uint8Array) { + return concat(uint32be(input.length), input) +} + +export async function concatKdf(secret: Uint8Array, bits: number, value: Uint8Array) { + const iterations = Math.ceil((bits >> 3) / 32) + const res = new Uint8Array(iterations * 32) + for (let iter = 0; iter < iterations; iter++) { + const buf = new Uint8Array(4 + secret.length + value.length) + buf.set(uint32be(iter + 1)) + buf.set(secret, 4) + buf.set(value, 4 + secret.length) + res.set(await digest('sha256', buf), iter * 32) + } + return res.slice(0, bits >> 3) +} diff --git a/dist/deno/lib/cek.ts b/dist/deno/lib/cek.ts new file mode 100644 index 0000000000..22cb0bb1a7 --- /dev/null +++ b/dist/deno/lib/cek.ts @@ -0,0 +1,21 @@ +import { JOSENotSupported } from '../util/errors.ts' +import random from '../runtime/random.ts' + +export function bitLength(alg: string) { + switch (alg) { + case 'A128GCM': + return 128 + case 'A192GCM': + return 192 + case 'A256GCM': + case 'A128CBC-HS256': + return 256 + case 'A192CBC-HS384': + return 384 + case 'A256CBC-HS512': + return 512 + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`) + } +} +export default (alg: string): Uint8Array => random(new Uint8Array(bitLength(alg) >> 3)) diff --git a/dist/deno/lib/check_iv_length.ts b/dist/deno/lib/check_iv_length.ts new file mode 100644 index 0000000000..d63a2b280a --- /dev/null +++ b/dist/deno/lib/check_iv_length.ts @@ -0,0 +1,10 @@ +import { JWEInvalid } from '../util/errors.ts' +import { bitLength } from './iv.ts' + +const checkIvLength = (enc: string, iv: Uint8Array) => { + if (iv.length << 3 !== bitLength(enc)) { + throw new JWEInvalid('Invalid Initialization Vector length') + } +} + +export default checkIvLength diff --git a/dist/deno/lib/check_key_type.ts b/dist/deno/lib/check_key_type.ts new file mode 100644 index 0000000000..cc85e608dc --- /dev/null +++ b/dist/deno/lib/check_key_type.ts @@ -0,0 +1,74 @@ +import { withAlg as invalidKeyInput } from './invalid_key_input.ts' +import isKeyLike, { types } from '../runtime/is_key_like.ts' + +const symmetricTypeCheck = (alg: string, key: unknown) => { + if (key instanceof Uint8Array) return + + if (!isKeyLike(key)) { + throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array')) + } + + if (key.type !== 'secret') { + throw new TypeError( + `${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`, + ) + } +} + +const asymmetricTypeCheck = (alg: string, key: unknown, usage: string) => { + if (!isKeyLike(key)) { + throw new TypeError(invalidKeyInput(alg, key, ...types)) + } + + if (key.type === 'secret') { + throw new TypeError( + `${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`, + ) + } + + if (usage === 'sign' && key.type === 'public') { + throw new TypeError( + `${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`, + ) + } + + if (usage === 'decrypt' && key.type === 'public') { + throw new TypeError( + `${types.join( + ' or ', + )} instances for asymmetric algorithm decryption must be of type "private"`, + ) + } + + // KeyObject allows this but CryptoKey does not. + if ((key).algorithm && usage === 'verify' && key.type === 'private') { + throw new TypeError( + `${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`, + ) + } + + // KeyObject allows this but CryptoKey does not. + if ((key).algorithm && usage === 'encrypt' && key.type === 'private') { + throw new TypeError( + `${types.join( + ' or ', + )} instances for asymmetric algorithm encryption must be of type "public"`, + ) + } +} + +const checkKeyType = (alg: string, key: unknown, usage: string): void => { + const symmetric = + alg.startsWith('HS') || + alg === 'dir' || + alg.startsWith('PBES2') || + /^A\d{3}(?:GCM)?KW$/.test(alg) + + if (symmetric) { + symmetricTypeCheck(alg, key) + } else { + asymmetricTypeCheck(alg, key, usage) + } +} + +export default checkKeyType diff --git a/dist/deno/lib/check_p2s.ts b/dist/deno/lib/check_p2s.ts new file mode 100644 index 0000000000..53c6d9c85f --- /dev/null +++ b/dist/deno/lib/check_p2s.ts @@ -0,0 +1,7 @@ +import { JWEInvalid } from '../util/errors.ts' + +export default function checkP2s(p2s: Uint8Array) { + if (!(p2s instanceof Uint8Array) || p2s.length < 8) { + throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets') + } +} diff --git a/dist/deno/lib/crypto_key.ts b/dist/deno/lib/crypto_key.ts new file mode 100644 index 0000000000..2c9eb3fdae --- /dev/null +++ b/dist/deno/lib/crypto_key.ts @@ -0,0 +1,151 @@ +import { isCloudflareWorkers } from '../runtime/env.ts' + +function unusable(name: string | number, prop = 'algorithm.name') { + return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`) +} + +function isAlgorithm(algorithm: any, name: string): algorithm is T { + return algorithm.name === name +} + +function getHashLength(hash: KeyAlgorithm) { + return parseInt(hash.name.slice(4), 10) +} + +function getNamedCurve(alg: string) { + switch (alg) { + case 'ES256': + return 'P-256' + case 'ES384': + return 'P-384' + case 'ES512': + return 'P-521' + default: + throw new Error('unreachable') + } +} + +function checkUsage(key: CryptoKey, usages: KeyUsage[]) { + if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { + let msg = 'CryptoKey does not support this operation, its usages must include ' + if (usages.length > 2) { + const last = usages.pop() + msg += `one of ${usages.join(', ')}, or ${last}.` + } else if (usages.length === 2) { + msg += `one of ${usages[0]} or ${usages[1]}.` + } else { + msg += `${usages[0]}.` + } + + throw new TypeError(msg) + } +} + +export function checkSigCryptoKey(key: CryptoKey, alg: string, ...usages: KeyUsage[]) { + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': { + if (!isAlgorithm(key.algorithm, 'HMAC')) throw unusable('HMAC') + const expected = parseInt(alg.slice(2), 10) + const actual = getHashLength(key.algorithm.hash) + if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') + break + } + case 'RS256': + case 'RS384': + case 'RS512': { + if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) + throw unusable('RSASSA-PKCS1-v1_5') + const expected = parseInt(alg.slice(2), 10) + const actual = getHashLength(key.algorithm.hash) + if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') + break + } + case 'PS256': + case 'PS384': + case 'PS512': { + if (!isAlgorithm(key.algorithm, 'RSA-PSS')) throw unusable('RSA-PSS') + const expected = parseInt(alg.slice(2), 10) + const actual = getHashLength(key.algorithm.hash) + if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') + break + } + case 'EdDSA': { + if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { + if (isCloudflareWorkers()) { + if (isAlgorithm(key.algorithm, 'NODE-ED25519')) break + throw unusable('Ed25519, Ed448, or NODE-ED25519') + } + throw unusable('Ed25519 or Ed448') + } + break + } + case 'ES256': + case 'ES384': + case 'ES512': { + if (!isAlgorithm(key.algorithm, 'ECDSA')) throw unusable('ECDSA') + const expected = getNamedCurve(alg) + const actual = key.algorithm.namedCurve + if (actual !== expected) throw unusable(expected, 'algorithm.namedCurve') + break + } + default: + throw new TypeError('CryptoKey does not support this operation') + } + + checkUsage(key, usages) +} + +export function checkEncCryptoKey(key: CryptoKey, alg: string, ...usages: KeyUsage[]) { + switch (alg) { + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': { + if (!isAlgorithm(key.algorithm, 'AES-GCM')) throw unusable('AES-GCM') + const expected = parseInt(alg.slice(1, 4), 10) + const actual = key.algorithm.length + if (actual !== expected) throw unusable(expected, 'algorithm.length') + break + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + if (!isAlgorithm(key.algorithm, 'AES-KW')) throw unusable('AES-KW') + const expected = parseInt(alg.slice(1, 4), 10) + const actual = key.algorithm.length + if (actual !== expected) throw unusable(expected, 'algorithm.length') + break + } + case 'ECDH': { + switch (key.algorithm.name) { + case 'ECDH': + case 'X25519': + case 'X448': + break + default: + throw unusable('ECDH, X25519, or X448') + } + break + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': + if (!isAlgorithm(key.algorithm, 'PBKDF2')) throw unusable('PBKDF2') + break + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) throw unusable('RSA-OAEP') + const expected = parseInt(alg.slice(9), 10) || 1 + const actual = getHashLength(key.algorithm.hash) + if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash') + break + } + default: + throw new TypeError('CryptoKey does not support this operation') + } + + checkUsage(key, usages) +} diff --git a/dist/deno/lib/decrypt_key_management.ts b/dist/deno/lib/decrypt_key_management.ts new file mode 100644 index 0000000000..0960882982 --- /dev/null +++ b/dist/deno/lib/decrypt_key_management.ts @@ -0,0 +1,141 @@ +import { unwrap as aesKw } from '../runtime/aeskw.ts' +import * as ECDH from '../runtime/ecdhes.ts' +import { decrypt as pbes2Kw } from '../runtime/pbes2kw.ts' +import { decrypt as rsaEs } from '../runtime/rsaes.ts' +import { decode as base64url } from '../runtime/base64url.ts' + +import type { DecryptOptions, JWEHeaderParameters, KeyLike, JWK } from '../types.d.ts' +import { JOSENotSupported, JWEInvalid } from '../util/errors.ts' +import { bitLength as cekLength } from '../lib/cek.ts' +import { importJWK } from '../key/import.ts' +import checkKeyType from './check_key_type.ts' +import isObject from './is_object.ts' +import { unwrap as aesGcmKw } from './aesgcmkw.ts' + +async function decryptKeyManagement( + alg: string, + key: KeyLike | Uint8Array, + encryptedKey: Uint8Array | undefined, + joseHeader: JWEHeaderParameters, + options?: DecryptOptions, +): Promise { + checkKeyType(alg, key, 'decrypt') + + switch (alg) { + case 'dir': { + // Direct Encryption + if (encryptedKey !== undefined) + throw new JWEInvalid('Encountered unexpected JWE Encrypted Key') + + return key + } + case 'ECDH-ES': + // Direct Key Agreement + if (encryptedKey !== undefined) + throw new JWEInvalid('Encountered unexpected JWE Encrypted Key') + + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + // Direct Key Agreement + if (!isObject(joseHeader.epk)) + throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`) + + if (!ECDH.ecdhAllowed(key)) + throw new JOSENotSupported( + 'ECDH with the provided key is not allowed or not supported by your javascript runtime', + ) + + const epk = await importJWK(joseHeader.epk, alg) + let partyUInfo!: Uint8Array + let partyVInfo!: Uint8Array + + if (joseHeader.apu !== undefined) { + if (typeof joseHeader.apu !== 'string') + throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`) + partyUInfo = base64url(joseHeader.apu) + } + + if (joseHeader.apv !== undefined) { + if (typeof joseHeader.apv !== 'string') + throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`) + partyVInfo = base64url(joseHeader.apv) + } + + const sharedSecret = await ECDH.deriveKey( + epk, + key, + alg === 'ECDH-ES' ? joseHeader.enc! : alg, + alg === 'ECDH-ES' ? cekLength(joseHeader.enc!) : parseInt(alg.slice(-5, -2), 10), + partyUInfo, + partyVInfo, + ) + + if (alg === 'ECDH-ES') return sharedSecret + + // Key Agreement with Key Wrapping + if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') + + return aesKw(alg.slice(-6), sharedSecret, encryptedKey) + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + // Key Encryption (RSA) + if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') + + return rsaEs(alg, key, encryptedKey) + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + // Key Encryption (PBES2) + if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') + + if (typeof joseHeader.p2c !== 'number') + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`) + + const p2cLimit = options?.maxPBES2Count || 10_000 + + if (joseHeader.p2c > p2cLimit) + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`) + + if (typeof joseHeader.p2s !== 'string') + throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`) + + return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s)) + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + // Key Wrapping (AES KW) + if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') + + return aesKw(alg, key, encryptedKey) + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + // Key Wrapping (AES GCM KW) + if (encryptedKey === undefined) throw new JWEInvalid('JWE Encrypted Key missing') + + if (typeof joseHeader.iv !== 'string') + throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`) + + if (typeof joseHeader.tag !== 'string') + throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`) + + const iv = base64url(joseHeader.iv) + const tag = base64url(joseHeader.tag) + + return aesGcmKw(alg, key, encryptedKey, iv, tag) + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value') + } + } +} + +export default decryptKeyManagement diff --git a/dist/deno/lib/encrypt_key_management.ts b/dist/deno/lib/encrypt_key_management.ts new file mode 100644 index 0000000000..4ce03a4b8d --- /dev/null +++ b/dist/deno/lib/encrypt_key_management.ts @@ -0,0 +1,124 @@ +import { wrap as aesKw } from '../runtime/aeskw.ts' +import * as ECDH from '../runtime/ecdhes.ts' +import { encrypt as pbes2Kw } from '../runtime/pbes2kw.ts' +import { encrypt as rsaEs } from '../runtime/rsaes.ts' +import { encode as base64url } from '../runtime/base64url.ts' + +import type { + KeyLike, + JWEKeyManagementHeaderParameters, + JWEHeaderParameters, + JWK, +} from '../types.d.ts' +import generateCek, { bitLength as cekLength } from '../lib/cek.ts' +import { JOSENotSupported } from '../util/errors.ts' +import { exportJWK } from '../key/export.ts' +import checkKeyType from './check_key_type.ts' +import { wrap as aesGcmKw } from './aesgcmkw.ts' + +async function encryptKeyManagement( + alg: string, + enc: string, + key: KeyLike | Uint8Array, + providedCek?: Uint8Array, + providedParameters: JWEKeyManagementHeaderParameters = {}, +): Promise<{ + cek: KeyLike | Uint8Array + encryptedKey?: Uint8Array + parameters?: JWEHeaderParameters +}> { + let encryptedKey: Uint8Array | undefined + let parameters: (JWEHeaderParameters & { epk?: JWK }) | undefined + let cek: KeyLike | Uint8Array + + checkKeyType(alg, key, 'encrypt') + + switch (alg) { + case 'dir': { + // Direct Encryption + cek = key + break + } + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + // Direct Key Agreement + if (!ECDH.ecdhAllowed(key)) { + throw new JOSENotSupported( + 'ECDH with the provided key is not allowed or not supported by your javascript runtime', + ) + } + const { apu, apv } = providedParameters + let { epk: ephemeralKey } = providedParameters + ephemeralKey ||= (await ECDH.generateEpk(key)).privateKey + const { x, y, crv, kty } = await exportJWK(ephemeralKey!) + const sharedSecret = await ECDH.deriveKey( + key, + ephemeralKey, + alg === 'ECDH-ES' ? enc : alg, + alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), + apu, + apv, + ) + parameters = { epk: { x, crv, kty } } + if (kty === 'EC') parameters.epk!.y = y + if (apu) parameters.apu = base64url(apu) + if (apv) parameters.apv = base64url(apv) + + if (alg === 'ECDH-ES') { + cek = sharedSecret + break + } + + // Key Agreement with Key Wrapping + cek = providedCek || generateCek(enc) + const kwAlg = alg.slice(-6) + encryptedKey = await aesKw(kwAlg, sharedSecret, cek) + break + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + // Key Encryption (RSA) + cek = providedCek || generateCek(enc) + encryptedKey = await rsaEs(alg, key, cek) + break + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + // Key Encryption (PBES2) + cek = providedCek || generateCek(enc) + const { p2c, p2s } = providedParameters + ;({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s)) + break + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + // Key Wrapping (AES KW) + cek = providedCek || generateCek(enc) + encryptedKey = await aesKw(alg, key, cek) + break + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + // Key Wrapping (AES GCM KW) + cek = providedCek || generateCek(enc) + const { iv } = providedParameters + ;({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv)) + break + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value') + } + } + + return { cek, encryptedKey, parameters } +} + +export default encryptKeyManagement diff --git a/dist/deno/lib/epoch.ts b/dist/deno/lib/epoch.ts new file mode 100644 index 0000000000..616795a52e --- /dev/null +++ b/dist/deno/lib/epoch.ts @@ -0,0 +1 @@ +export default (date: Date) => Math.floor(date.getTime() / 1000) diff --git a/dist/deno/lib/format_pem.ts b/dist/deno/lib/format_pem.ts new file mode 100644 index 0000000000..ff54c795dd --- /dev/null +++ b/dist/deno/lib/format_pem.ts @@ -0,0 +1,4 @@ +export default (b64: string, descriptor: string) => { + const newlined = (b64.match(/.{1,64}/g) || []).join('\n') + return `-----BEGIN ${descriptor}-----\n${newlined}\n-----END ${descriptor}-----` +} diff --git a/dist/deno/lib/invalid_key_input.ts b/dist/deno/lib/invalid_key_input.ts new file mode 100644 index 0000000000..2b99dd440c --- /dev/null +++ b/dist/deno/lib/invalid_key_input.ts @@ -0,0 +1,30 @@ +function message(msg: string, actual: unknown, ...types: string[]) { + if (types.length > 2) { + const last = types.pop() + msg += `one of type ${types.join(', ')}, or ${last}.` + } else if (types.length === 2) { + msg += `one of type ${types[0]} or ${types[1]}.` + } else { + msg += `of type ${types[0]}.` + } + + if (actual == null) { + msg += ` Received ${actual}` + } else if (typeof actual === 'function' && actual.name) { + msg += ` Received function ${actual.name}` + } else if (typeof actual === 'object' && actual != null) { + if (actual.constructor && actual.constructor.name) { + msg += ` Received an instance of ${actual.constructor.name}` + } + } + + return msg +} + +export default (actual: unknown, ...types: string[]) => { + return message('Key must be ', actual, ...types) +} + +export function withAlg(alg: string, actual: unknown, ...types: string[]) { + return message(`Key for the ${alg} algorithm must be `, actual, ...types) +} diff --git a/dist/deno/lib/is_disjoint.ts b/dist/deno/lib/is_disjoint.ts new file mode 100644 index 0000000000..c260352e76 --- /dev/null +++ b/dist/deno/lib/is_disjoint.ts @@ -0,0 +1,26 @@ +const isDisjoint = (...headers: Array) => { + const sources = headers.filter(Boolean) + + if (sources.length === 0 || sources.length === 1) { + return true + } + + let acc!: Set + for (const header of sources) { + const parameters = Object.keys(header) + if (!acc || acc.size === 0) { + acc = new Set(parameters) + continue + } + + for (const parameter of parameters) { + if (acc.has(parameter)) { + return false + } + acc.add(parameter) + } + } + + return true +} +export default isDisjoint diff --git a/dist/deno/lib/is_object.ts b/dist/deno/lib/is_object.ts new file mode 100644 index 0000000000..50aa4f6a5c --- /dev/null +++ b/dist/deno/lib/is_object.ts @@ -0,0 +1,17 @@ +function isObjectLike(value: unknown) { + return typeof value === 'object' && value !== null +} + +export default function isObject(input: unknown): input is T { + if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { + return false + } + if (Object.getPrototypeOf(input) === null) { + return true + } + let proto = input + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto) + } + return Object.getPrototypeOf(input) === proto +} diff --git a/dist/deno/lib/iv.ts b/dist/deno/lib/iv.ts new file mode 100644 index 0000000000..93eb2ca8d8 --- /dev/null +++ b/dist/deno/lib/iv.ts @@ -0,0 +1,21 @@ +import { JOSENotSupported } from '../util/errors.ts' +import random from '../runtime/random.ts' + +export function bitLength(alg: string) { + switch (alg) { + case 'A128GCM': + case 'A128GCMKW': + case 'A192GCM': + case 'A192GCMKW': + case 'A256GCM': + case 'A256GCMKW': + return 96 + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return 128 + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`) + } +} +export default (alg: string): Uint8Array => random(new Uint8Array(bitLength(alg) >> 3)) diff --git a/dist/deno/lib/jwt_claims_set.ts b/dist/deno/lib/jwt_claims_set.ts new file mode 100644 index 0000000000..5ebb4c0872 --- /dev/null +++ b/dist/deno/lib/jwt_claims_set.ts @@ -0,0 +1,139 @@ +import type { + JWTPayload, + JWTClaimVerificationOptions, + JWEHeaderParameters, + JWSHeaderParameters, +} from '../types.d.ts' +import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.ts' +import { decoder } from './buffer_utils.ts' +import epoch from './epoch.ts' +import secs from './secs.ts' +import isObject from './is_object.ts' + +const normalizeTyp = (value: string) => value.toLowerCase().replace(/^application\//, '') + +const checkAudiencePresence = (audPayload: unknown, audOption: unknown[]) => { + if (typeof audPayload === 'string') { + return audOption.includes(audPayload) + } + + if (Array.isArray(audPayload)) { + // Each principal intended to process the JWT MUST + // identify itself with a value in the audience claim + return audOption.some(Set.prototype.has.bind(new Set(audPayload))) + } + + return false +} + +export default ( + protectedHeader: JWEHeaderParameters | JWSHeaderParameters, + encodedPayload: Uint8Array, + options: JWTClaimVerificationOptions = {}, +) => { + const { typ } = options + if ( + typ && + (typeof protectedHeader!.typ !== 'string' || + normalizeTyp(protectedHeader!.typ) !== normalizeTyp(typ)) + ) { + throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed') + } + + let payload!: { [propName: string]: unknown } + try { + payload = JSON.parse(decoder.decode(encodedPayload)) + } catch { + // + } + + if (!isObject(payload)) { + throw new JWTInvalid('JWT Claims Set must be a top-level JSON object') + } + + const { issuer } = options + if (issuer && !((Array.isArray(issuer) ? issuer : [issuer])).includes(payload.iss!)) { + throw new JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed') + } + + const { subject } = options + if (subject && payload.sub !== subject) { + throw new JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed') + } + + const { audience } = options + if ( + audience && + !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience) + ) { + throw new JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed') + } + + let tolerance: number + switch (typeof options.clockTolerance) { + case 'string': + tolerance = secs(options.clockTolerance) + break + case 'number': + tolerance = options.clockTolerance + break + case 'undefined': + tolerance = 0 + break + default: + throw new TypeError('Invalid clockTolerance option type') + } + + const { currentDate } = options + const now = epoch(currentDate || new Date()) + + if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { + throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid') + } + + if (payload.nbf !== undefined) { + if (typeof payload.nbf !== 'number') { + throw new JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid') + } + if (payload.nbf > now + tolerance) { + throw new JWTClaimValidationFailed( + '"nbf" claim timestamp check failed', + 'nbf', + 'check_failed', + ) + } + } + + if (payload.exp !== undefined) { + if (typeof payload.exp !== 'number') { + throw new JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid') + } + if (payload.exp <= now - tolerance) { + throw new JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed') + } + } + + if (options.maxTokenAge) { + const age = now - payload.iat! + const max = + typeof options.maxTokenAge === 'number' ? options.maxTokenAge : secs(options.maxTokenAge) + + if (age - tolerance > max) { + throw new JWTExpired( + '"iat" claim timestamp check failed (too far in the past)', + 'iat', + 'check_failed', + ) + } + + if (age < 0 - tolerance) { + throw new JWTClaimValidationFailed( + '"iat" claim timestamp check failed (it should be in the past)', + 'iat', + 'check_failed', + ) + } + } + + return payload +} diff --git a/dist/deno/lib/secs.ts b/dist/deno/lib/secs.ts new file mode 100644 index 0000000000..8d9f07f7de --- /dev/null +++ b/dist/deno/lib/secs.ts @@ -0,0 +1,51 @@ +const minute = 60 +const hour = minute * 60 +const day = hour * 24 +const week = day * 7 +const year = day * 365.25 + +const REGEX = + /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i + +export default (str: string): number => { + const matched = REGEX.exec(str) + + if (!matched) { + throw new TypeError('Invalid time period format') + } + + const value = parseFloat(matched[1]) + const unit = matched[2].toLowerCase() + + switch (unit) { + case 'sec': + case 'secs': + case 'second': + case 'seconds': + case 's': + return Math.round(value) + case 'minute': + case 'minutes': + case 'min': + case 'mins': + case 'm': + return Math.round(value * minute) + case 'hour': + case 'hours': + case 'hr': + case 'hrs': + case 'h': + return Math.round(value * hour) + case 'day': + case 'days': + case 'd': + return Math.round(value * day) + case 'week': + case 'weeks': + case 'w': + return Math.round(value * week) + // years matched + default: + return Math.round(value * year) + } +} diff --git a/dist/deno/lib/validate_algorithms.ts b/dist/deno/lib/validate_algorithms.ts new file mode 100644 index 0000000000..870efaa6ef --- /dev/null +++ b/dist/deno/lib/validate_algorithms.ts @@ -0,0 +1,16 @@ +const validateAlgorithms = (option: string, algorithms?: string[]) => { + if ( + algorithms !== undefined && + (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string')) + ) { + throw new TypeError(`"${option}" option must be an array of strings`) + } + + if (!algorithms) { + return undefined + } + + return new Set(algorithms) +} + +export default validateAlgorithms diff --git a/dist/deno/lib/validate_crit.ts b/dist/deno/lib/validate_crit.ts new file mode 100644 index 0000000000..d5ea76dc55 --- /dev/null +++ b/dist/deno/lib/validate_crit.ts @@ -0,0 +1,56 @@ +import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.ts' + +interface CritCheckHeader { + b64?: boolean + crit?: string[] + [propName: string]: unknown +} + +function validateCrit( + Err: typeof JWEInvalid | typeof JWSInvalid, + recognizedDefault: Map, + recognizedOption: { [propName: string]: boolean } | undefined, + protectedHeader: CritCheckHeader, + joseHeader: CritCheckHeader, +) { + if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { + throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected') + } + + if (!protectedHeader || protectedHeader.crit === undefined) { + return new Set() + } + + if ( + !Array.isArray(protectedHeader.crit) || + protectedHeader.crit.length === 0 || + protectedHeader.crit.some((input: string) => typeof input !== 'string' || input.length === 0) + ) { + throw new Err( + '"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present', + ) + } + + let recognized: Map + if (recognizedOption !== undefined) { + recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]) + } else { + recognized = recognizedDefault + } + + for (const parameter of protectedHeader.crit) { + if (!recognized.has(parameter)) { + throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`) + } + + if (joseHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" is missing`) + } else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`) + } + } + + return new Set(protectedHeader.crit) +} + +export default validateCrit diff --git a/dist/deno/runtime/aeskw.ts b/dist/deno/runtime/aeskw.ts new file mode 100644 index 0000000000..72da0ef4a7 --- /dev/null +++ b/dist/deno/runtime/aeskw.ts @@ -0,0 +1,56 @@ +import type { AesKwUnwrapFunction, AesKwWrapFunction } from './interfaces.d.ts' +import bogusWebCrypto from './bogus.ts' +import crypto, { isCryptoKey } from './webcrypto.ts' +import { checkEncCryptoKey } from '../lib/crypto_key.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { types } from './is_key_like.ts' + +function checkKeySize(key: CryptoKey, alg: string) { + if ((key.algorithm).length !== parseInt(alg.slice(1, 4), 10)) { + throw new TypeError(`Invalid key size for alg: ${alg}`) + } +} + +function getCryptoKey(key: unknown, alg: string, usage: KeyUsage) { + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, usage) + return key + } + + if (key instanceof Uint8Array) { + return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]) + } + + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) +} + +export const wrap: AesKwWrapFunction = async (alg: string, key: unknown, cek: Uint8Array) => { + const cryptoKey = await getCryptoKey(key, alg, 'wrapKey') + + checkKeySize(cryptoKey, alg) + + // we're importing the cek to end up with CryptoKey instance that can be wrapped, the algorithm used is irrelevant + const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto) + + return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, cryptoKey, 'AES-KW')) +} + +export const unwrap: AesKwUnwrapFunction = async ( + alg: string, + key: unknown, + encryptedKey: Uint8Array, +) => { + const cryptoKey = await getCryptoKey(key, alg, 'unwrapKey') + + checkKeySize(cryptoKey, alg) + + const cryptoKeyCek = await crypto.subtle.unwrapKey( + 'raw', + encryptedKey, + cryptoKey, + 'AES-KW', + ...bogusWebCrypto, + ) + + return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)) +} diff --git a/dist/deno/runtime/asn1.ts b/dist/deno/runtime/asn1.ts new file mode 100644 index 0000000000..7e4db5886e --- /dev/null +++ b/dist/deno/runtime/asn1.ts @@ -0,0 +1,268 @@ +import { isCloudflareWorkers } from './env.ts' +import crypto, { isCryptoKey } from './webcrypto.ts' +import type { PEMExportFunction, PEMImportFunction } from './interfaces.d.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { encodeBase64, decodeBase64 } from './base64url.ts' +import formatPEM from '../lib/format_pem.ts' +import { JOSENotSupported } from '../util/errors.ts' +import { types } from './is_key_like.ts' + +import type { PEMImportOptions } from '../key/import.ts' + +const genericExport = async ( + keyType: 'private' | 'public', + keyFormat: 'spki' | 'pkcs8', + key: unknown, +) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)) + } + + if (!key.extractable) { + throw new TypeError('CryptoKey is not extractable') + } + + if (key.type !== keyType) { + throw new TypeError(`key is not a ${keyType} key`) + } + + return formatPEM( + encodeBase64(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), + `${keyType.toUpperCase()} KEY`, + ) +} + +export const toSPKI: PEMExportFunction = (key) => { + return genericExport('public', 'spki', key) +} + +export const toPKCS8: PEMExportFunction = (key) => { + return genericExport('private', 'pkcs8', key) +} + +const findOid = (keyData: Uint8Array, oid: number[], from = 0): boolean => { + if (from === 0) { + oid.unshift(oid.length) + oid.unshift(0x06) + } + let i = keyData.indexOf(oid[0], from) + if (i === -1) return false + const sub = keyData.subarray(i, i + oid.length) + if (sub.length !== oid.length) return false + return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1) +} + +const getNamedCurve = (keyData: Uint8Array): string => { + switch (true) { + case findOid(keyData, [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]): + return 'P-256' + case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x22]): + return 'P-384' + case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]): + return 'P-521' + case findOid(keyData, [0x2b, 0x65, 0x6e]): + return 'X25519' + case findOid(keyData, [0x2b, 0x65, 0x6f]): + return 'X448' + case findOid(keyData, [0x2b, 0x65, 0x70]): + return 'Ed25519' + case findOid(keyData, [0x2b, 0x65, 0x71]): + return 'Ed448' + default: + throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type') + } +} + +const genericImport = async ( + replace: RegExp, + keyFormat: 'spki' | 'pkcs8', + pem: string, + alg: string, + options?: PEMImportOptions, +) => { + let algorithm: RsaHashedImportParams | EcKeyAlgorithm | Algorithm + let keyUsages: KeyUsage[] + + const keyData = new Uint8Array( + atob(pem.replace(replace, '')) + .split('') + .map((c) => c.charCodeAt(0)), + ) + + const isPublic = keyFormat === 'spki' + + switch (alg) { + case 'PS256': + case 'PS384': + case 'PS512': + algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` } + keyUsages = isPublic ? ['verify'] : ['sign'] + break + case 'RS256': + case 'RS384': + case 'RS512': + algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` } + keyUsages = isPublic ? ['verify'] : ['sign'] + break + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + algorithm = { + name: 'RSA-OAEP', + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, + } + keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'] + break + case 'ES256': + algorithm = { name: 'ECDSA', namedCurve: 'P-256' } + keyUsages = isPublic ? ['verify'] : ['sign'] + break + case 'ES384': + algorithm = { name: 'ECDSA', namedCurve: 'P-384' } + keyUsages = isPublic ? ['verify'] : ['sign'] + break + case 'ES512': + algorithm = { name: 'ECDSA', namedCurve: 'P-521' } + keyUsages = isPublic ? ['verify'] : ['sign'] + break + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + const namedCurve = getNamedCurve(keyData) + algorithm = namedCurve.startsWith('P-') ? { name: 'ECDH', namedCurve } : { name: namedCurve } + keyUsages = isPublic ? [] : ['deriveBits'] + break + } + case 'EdDSA': + algorithm = { name: getNamedCurve(keyData) } + keyUsages = isPublic ? ['verify'] : ['sign'] + break + default: + throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value') + } + + try { + return await crypto.subtle.importKey( + keyFormat, + keyData, + algorithm, + options?.extractable ?? false, + keyUsages, + ) + } catch (err) { + if ( + algorithm.name === 'Ed25519' && + (err)?.name === 'NotSupportedError' && + isCloudflareWorkers() + ) { + algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } + return await crypto.subtle.importKey( + keyFormat, + keyData, + algorithm, + options?.extractable ?? false, + keyUsages, + ) + } + throw err + } +} + +export const fromPKCS8: PEMImportFunction = (pem, alg, options?) => { + return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options) +} + +export const fromSPKI: PEMImportFunction = (pem, alg, options?) => { + return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, 'spki', pem, alg, options) +} + +function getElement(seq: Uint8Array) { + let result = [] + let next = 0 + + while (next < seq.length) { + let nextPart = parseElement(seq.subarray(next)) + result.push(nextPart) + next += nextPart.byteLength + } + return result +} + +function parseElement(bytes: Uint8Array) { + let position = 0 + + // tag + let tag = bytes[0] & 0x1f + position++ + if (tag === 0x1f) { + tag = 0 + while (bytes[position] >= 0x80) { + tag = tag * 128 + bytes[position] - 0x80 + position++ + } + tag = tag * 128 + bytes[position] - 0x80 + position++ + } + + // length + let length = 0 + if (bytes[position] < 0x80) { + length = bytes[position] + position++ + } else if (length === 0x80) { + length = 0 + + while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { + if (length > bytes.byteLength) { + throw new TypeError('invalid indefinite form length') + } + length++ + } + + const byteLength = position + length + 2 + return { + byteLength, + contents: bytes.subarray(position, position + length), + raw: bytes.subarray(0, byteLength), + } + } else { + let numberOfDigits = bytes[position] & 0x7f + position++ + length = 0 + for (let i = 0; i < numberOfDigits; i++) { + length = length * 256 + bytes[position] + position++ + } + } + + const byteLength = position + length + return { + byteLength, + contents: bytes.subarray(position, byteLength), + raw: bytes.subarray(0, byteLength), + } +} + +function spkiFromX509(buf: Uint8Array) { + const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents) + return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 0xa0 ? 6 : 5].raw) +} + +function getSPKI(x509: string): string { + const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '') + const raw = decodeBase64(pem) + return formatPEM(spkiFromX509(raw), 'PUBLIC KEY') +} + +export const fromX509: PEMImportFunction = (pem, alg, options?) => { + let spki: string + try { + spki = getSPKI(pem) + } catch (cause) { + // @ts-ignore + throw new TypeError('failed to parse the X.509 certificate', { cause }) + } + return fromSPKI(spki, alg, options) +} diff --git a/dist/deno/runtime/base64url.ts b/dist/deno/runtime/base64url.ts new file mode 100644 index 0000000000..45dff570c3 --- /dev/null +++ b/dist/deno/runtime/base64url.ts @@ -0,0 +1,41 @@ +import { encoder, decoder } from '../lib/buffer_utils.ts' + +export const encodeBase64 = (input: Uint8Array | string) => { + let unencoded = input + if (typeof unencoded === 'string') { + unencoded = encoder.encode(unencoded) + } + const CHUNK_SIZE = 0x8000 + const arr = [] + for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) { + // @ts-expect-error + arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE))) + } + return btoa(arr.join('')) +} + +export const encode = (input: Uint8Array | string) => { + return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_') +} + +export const decodeBase64 = (encoded: string): Uint8Array => { + const binary = atob(encoded) + const bytes = new Uint8Array(binary.length) + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i) + } + return bytes +} + +export const decode = (input: Uint8Array | string) => { + let encoded = input + if (encoded instanceof Uint8Array) { + encoded = decoder.decode(encoded) + } + encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '') + try { + return decodeBase64(encoded) + } catch { + throw new TypeError('The input to be decoded is not correctly encoded.') + } +} diff --git a/dist/deno/runtime/bogus.ts b/dist/deno/runtime/bogus.ts new file mode 100644 index 0000000000..3f7bcfdf66 --- /dev/null +++ b/dist/deno/runtime/bogus.ts @@ -0,0 +1,7 @@ +const bogusWebCrypto: [HmacImportParams, boolean, KeyUsage[]] = [ + { hash: 'SHA-256', name: 'HMAC' }, + true, + ['sign'], +] + +export default bogusWebCrypto diff --git a/dist/deno/runtime/check_cek_length.ts b/dist/deno/runtime/check_cek_length.ts new file mode 100644 index 0000000000..44aeda9684 --- /dev/null +++ b/dist/deno/runtime/check_cek_length.ts @@ -0,0 +1,12 @@ +import { JWEInvalid } from '../util/errors.ts' + +const checkCekLength = (cek: Uint8Array, expected: number) => { + const actual = cek.byteLength << 3 + if (actual !== expected) { + throw new JWEInvalid( + `Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`, + ) + } +} + +export default checkCekLength diff --git a/dist/deno/runtime/check_key_length.ts b/dist/deno/runtime/check_key_length.ts new file mode 100644 index 0000000000..fac5e16f32 --- /dev/null +++ b/dist/deno/runtime/check_key_length.ts @@ -0,0 +1,8 @@ +export default (alg: string, key: CryptoKey) => { + if (alg.startsWith('RS') || alg.startsWith('PS')) { + const { modulusLength } = key.algorithm + if (typeof modulusLength !== 'number' || modulusLength < 2048) { + throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`) + } + } +} diff --git a/dist/deno/runtime/decrypt.ts b/dist/deno/runtime/decrypt.ts new file mode 100644 index 0000000000..5210491dea --- /dev/null +++ b/dist/deno/runtime/decrypt.ts @@ -0,0 +1,137 @@ +import { concat, uint64be } from '../lib/buffer_utils.ts' + +import type { DecryptFunction } from './interfaces.d.ts' +import checkIvLength from '../lib/check_iv_length.ts' +import checkCekLength from './check_cek_length.ts' +import timingSafeEqual from './timing_safe_equal.ts' +import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.ts' +import crypto, { isCryptoKey } from './webcrypto.ts' +import { checkEncCryptoKey } from '../lib/crypto_key.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { types } from './is_key_like.ts' + +async function cbcDecrypt( + enc: string, + cek: Uint8Array | CryptoKey, + ciphertext: Uint8Array, + iv: Uint8Array, + tag: Uint8Array, + aad: Uint8Array, +) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, 'Uint8Array')) + } + const keySize = parseInt(enc.slice(1, 4), 10) + const encKey = await crypto.subtle.importKey( + 'raw', + cek.subarray(keySize >> 3), + 'AES-CBC', + false, + ['decrypt'], + ) + const macKey = await crypto.subtle.importKey( + 'raw', + cek.subarray(0, keySize >> 3), + { + hash: `SHA-${keySize << 1}`, + name: 'HMAC', + }, + false, + ['sign'], + ) + + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)) + const expectedTag = new Uint8Array( + (await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3), + ) + + let macCheckPassed!: boolean + try { + macCheckPassed = timingSafeEqual(tag, expectedTag) + } catch { + // + } + if (!macCheckPassed) { + throw new JWEDecryptionFailed() + } + + let plaintext!: Uint8Array + try { + plaintext = new Uint8Array( + await crypto.subtle.decrypt({ iv, name: 'AES-CBC' }, encKey, ciphertext), + ) + } catch { + // + } + if (!plaintext) { + throw new JWEDecryptionFailed() + } + + return plaintext +} + +async function gcmDecrypt( + enc: string, + cek: Uint8Array | CryptoKey, + ciphertext: Uint8Array, + iv: Uint8Array, + tag: Uint8Array, + aad: Uint8Array, +) { + let encKey: CryptoKey + if (cek instanceof Uint8Array) { + encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']) + } else { + checkEncCryptoKey(cek, enc, 'decrypt') + encKey = cek + } + + try { + return new Uint8Array( + await crypto.subtle.decrypt( + { + additionalData: aad, + iv, + name: 'AES-GCM', + tagLength: 128, + }, + encKey, + concat(ciphertext, tag), + ), + ) + } catch { + throw new JWEDecryptionFailed() + } +} + +const decrypt: DecryptFunction = async ( + enc: string, + cek: unknown, + ciphertext: Uint8Array, + iv: Uint8Array, + tag: Uint8Array, + aad: Uint8Array, +) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')) + } + + checkIvLength(enc, iv) + + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(-3), 10)) + return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(1, 4), 10)) + return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) + default: + throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm') + } +} + +export default decrypt diff --git a/dist/deno/runtime/digest.ts b/dist/deno/runtime/digest.ts new file mode 100644 index 0000000000..58a6e302a1 --- /dev/null +++ b/dist/deno/runtime/digest.ts @@ -0,0 +1,11 @@ +import crypto from './webcrypto.ts' +import type { DigestFunction } from './interfaces.d.ts' + +const digest: DigestFunction = async ( + algorithm: 'sha256' | 'sha384' | 'sha512', + data: Uint8Array, +): Promise => { + const subtleDigest = `SHA-${algorithm.slice(-3)}` + return new Uint8Array(await crypto.subtle.digest(subtleDigest, data)) +} +export default digest diff --git a/dist/deno/runtime/ecdhes.ts b/dist/deno/runtime/ecdhes.ts new file mode 100644 index 0000000000..d5f67827fb --- /dev/null +++ b/dist/deno/runtime/ecdhes.ts @@ -0,0 +1,72 @@ +import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.ts' +import crypto, { isCryptoKey } from './webcrypto.ts' +import { checkEncCryptoKey } from '../lib/crypto_key.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { types } from './is_key_like.ts' + +export async function deriveKey( + publicKey: unknown, + privateKey: unknown, + algorithm: string, + keyLength: number, + apu: Uint8Array = new Uint8Array(0), + apv: Uint8Array = new Uint8Array(0), +) { + if (!isCryptoKey(publicKey)) { + throw new TypeError(invalidKeyInput(publicKey, ...types)) + } + checkEncCryptoKey(publicKey, 'ECDH') + if (!isCryptoKey(privateKey)) { + throw new TypeError(invalidKeyInput(privateKey, ...types)) + } + checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits') + + const value = concat( + lengthAndInput(encoder.encode(algorithm)), + lengthAndInput(apu), + lengthAndInput(apv), + uint32be(keyLength), + ) + + let length: number + if (publicKey.algorithm.name === 'X25519') { + length = 256 + } else if (publicKey.algorithm.name === 'X448') { + length = 448 + } else { + length = + Math.ceil(parseInt((publicKey.algorithm).namedCurve.substr(-3), 10) / 8) << 3 + } + + const sharedSecret = new Uint8Array( + await crypto.subtle.deriveBits( + { + name: publicKey.algorithm.name, + public: publicKey, + }, + privateKey, + length, + ), + ) + + return concatKdf(sharedSecret, keyLength, value) +} + +export async function generateEpk(key: unknown) { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)) + } + + return crypto.subtle.generateKey(key.algorithm, true, ['deriveBits']) +} + +export function ecdhAllowed(key: unknown) { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)) + } + return ( + ['P-256', 'P-384', 'P-521'].includes((key.algorithm).namedCurve) || + key.algorithm.name === 'X25519' || + key.algorithm.name === 'X448' + ) +} diff --git a/dist/deno/runtime/encrypt.ts b/dist/deno/runtime/encrypt.ts new file mode 100644 index 0000000000..f74773c6bb --- /dev/null +++ b/dist/deno/runtime/encrypt.ts @@ -0,0 +1,122 @@ +import { concat, uint64be } from '../lib/buffer_utils.ts' +import type { EncryptFunction } from './interfaces.d.ts' +import checkIvLength from '../lib/check_iv_length.ts' +import checkCekLength from './check_cek_length.ts' +import crypto, { isCryptoKey } from './webcrypto.ts' +import { checkEncCryptoKey } from '../lib/crypto_key.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { JOSENotSupported } from '../util/errors.ts' +import { types } from './is_key_like.ts' + +async function cbcEncrypt( + enc: string, + plaintext: Uint8Array, + cek: Uint8Array | CryptoKey, + iv: Uint8Array, + aad: Uint8Array, +) { + if (!(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, 'Uint8Array')) + } + const keySize = parseInt(enc.slice(1, 4), 10) + const encKey = await crypto.subtle.importKey( + 'raw', + cek.subarray(keySize >> 3), + 'AES-CBC', + false, + ['encrypt'], + ) + const macKey = await crypto.subtle.importKey( + 'raw', + cek.subarray(0, keySize >> 3), + { + hash: `SHA-${keySize << 1}`, + name: 'HMAC', + }, + false, + ['sign'], + ) + + const ciphertext = new Uint8Array( + await crypto.subtle.encrypt( + { + iv, + name: 'AES-CBC', + }, + encKey, + plaintext, + ), + ) + + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)) + const tag = new Uint8Array( + (await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3), + ) + + return { ciphertext, tag } +} + +async function gcmEncrypt( + enc: string, + plaintext: Uint8Array, + cek: Uint8Array | CryptoKey, + iv: Uint8Array, + aad: Uint8Array, +) { + let encKey: CryptoKey + if (cek instanceof Uint8Array) { + encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']) + } else { + checkEncCryptoKey(cek, enc, 'encrypt') + encKey = cek + } + + const encrypted = new Uint8Array( + await crypto.subtle.encrypt( + { + additionalData: aad, + iv, + name: 'AES-GCM', + tagLength: 128, + }, + encKey, + plaintext, + ), + ) + + const tag = encrypted.slice(-16) + const ciphertext = encrypted.slice(0, -16) + + return { ciphertext, tag } +} + +const encrypt: EncryptFunction = async ( + enc: string, + plaintext: Uint8Array, + cek: unknown, + iv: Uint8Array, + aad: Uint8Array, +) => { + if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { + throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')) + } + + checkIvLength(enc, iv) + + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(-3), 10)) + return cbcEncrypt(enc, plaintext, cek, iv, aad) + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + if (cek instanceof Uint8Array) checkCekLength(cek, parseInt(enc.slice(1, 4), 10)) + return gcmEncrypt(enc, plaintext, cek, iv, aad) + default: + throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm') + } +} + +export default encrypt diff --git a/dist/deno/runtime/env.ts b/dist/deno/runtime/env.ts new file mode 100644 index 0000000000..c756022f1b --- /dev/null +++ b/dist/deno/runtime/env.ts @@ -0,0 +1,10 @@ +export function isCloudflareWorkers() { + return ( + // @ts-ignore + typeof WebSocketPair !== 'undefined' || + // @ts-ignore + (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') || + // @ts-ignore + (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel') + ) +} diff --git a/dist/deno/runtime/fetch_jwks.ts b/dist/deno/runtime/fetch_jwks.ts new file mode 100644 index 0000000000..6b7aad808f --- /dev/null +++ b/dist/deno/runtime/fetch_jwks.ts @@ -0,0 +1,43 @@ +import type { FetchFunction } from './interfaces.d.ts' +import { JOSEError, JWKSTimeout } from '../util/errors.ts' + +type AcceptedRequestOptions = Pick + +const fetchJwks: FetchFunction = async ( + url: URL, + timeout: number, + options: AcceptedRequestOptions, +) => { + let controller!: AbortController + let id!: ReturnType + let timedOut = false + if (typeof AbortController === 'function') { + controller = new AbortController() + id = setTimeout(() => { + timedOut = true + controller.abort() + }, timeout) + } + + const response = await fetch(url.href, { + signal: controller ? controller.signal : undefined, + redirect: 'manual', + headers: options.headers, + }).catch((err) => { + if (timedOut) throw new JWKSTimeout() + throw err + }) + + if (id !== undefined) clearTimeout(id) + + if (response.status !== 200) { + throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response') + } + + try { + return await response.json() + } catch { + throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON') + } +} +export default fetchJwks diff --git a/dist/deno/runtime/generate.ts b/dist/deno/runtime/generate.ts new file mode 100644 index 0000000000..b9672cf2fb --- /dev/null +++ b/dist/deno/runtime/generate.ts @@ -0,0 +1,169 @@ +import { isCloudflareWorkers } from './env.ts' +import crypto from './webcrypto.ts' +import { JOSENotSupported } from '../util/errors.ts' +import random from './random.ts' +import type { GenerateKeyPairOptions } from '../key/generate_key_pair.ts' +import type { GenerateSecretOptions } from '../key/generate_secret.ts' + +export async function generateSecret(alg: string, options?: GenerateSecretOptions) { + let length: number + let algorithm: AesKeyGenParams | HmacKeyGenParams + let keyUsages: KeyUsage[] + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': + length = parseInt(alg.slice(-3), 10) + algorithm = { name: 'HMAC', hash: `SHA-${length}`, length } + keyUsages = ['sign', 'verify'] + break + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + length = parseInt(alg.slice(-3), 10) + return random(new Uint8Array(length >> 3)) + case 'A128KW': + case 'A192KW': + case 'A256KW': + length = parseInt(alg.slice(1, 4), 10) + algorithm = { name: 'AES-KW', length } + keyUsages = ['wrapKey', 'unwrapKey'] + break + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + length = parseInt(alg.slice(1, 4), 10) + algorithm = { name: 'AES-GCM', length } + keyUsages = ['encrypt', 'decrypt'] + break + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') + } + + return >( + (crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages)) + ) +} + +function getModulusLengthOption(options?: GenerateKeyPairOptions) { + const modulusLength = options?.modulusLength ?? 2048 + if (typeof modulusLength !== 'number' || modulusLength < 2048) { + throw new JOSENotSupported( + 'Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used', + ) + } + return modulusLength +} + +export async function generateKeyPair(alg: string, options?: GenerateKeyPairOptions) { + let algorithm: RsaHashedKeyGenParams | EcKeyGenParams | KeyAlgorithm + let keyUsages: KeyUsage[] + + switch (alg) { + case 'PS256': + case 'PS384': + case 'PS512': + algorithm = { + name: 'RSA-PSS', + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + modulusLength: getModulusLengthOption(options), + } + keyUsages = ['sign', 'verify'] + break + case 'RS256': + case 'RS384': + case 'RS512': + algorithm = { + name: 'RSASSA-PKCS1-v1_5', + hash: `SHA-${alg.slice(-3)}`, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + modulusLength: getModulusLengthOption(options), + } + keyUsages = ['sign', 'verify'] + break + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + algorithm = { + name: 'RSA-OAEP', + hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + modulusLength: getModulusLengthOption(options), + } + keyUsages = ['decrypt', 'unwrapKey', 'encrypt', 'wrapKey'] + break + case 'ES256': + algorithm = { name: 'ECDSA', namedCurve: 'P-256' } + keyUsages = ['sign', 'verify'] + break + case 'ES384': + algorithm = { name: 'ECDSA', namedCurve: 'P-384' } + keyUsages = ['sign', 'verify'] + break + case 'ES512': + algorithm = { name: 'ECDSA', namedCurve: 'P-521' } + keyUsages = ['sign', 'verify'] + break + case 'EdDSA': + keyUsages = ['sign', 'verify'] + const crv = options?.crv ?? 'Ed25519' + switch (crv) { + case 'Ed25519': + case 'Ed448': + algorithm = { name: crv } + break + default: + throw new JOSENotSupported('Invalid or unsupported crv option provided') + } + break + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + keyUsages = ['deriveKey', 'deriveBits'] + const crv = options?.crv ?? 'P-256' + switch (crv) { + case 'P-256': + case 'P-384': + case 'P-521': { + algorithm = { name: 'ECDH', namedCurve: crv } + break + } + case 'X25519': + case 'X448': + algorithm = { name: crv } + break + default: + throw new JOSENotSupported( + 'Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448', + ) + } + break + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') + } + + try { + return <{ publicKey: CryptoKey; privateKey: CryptoKey }>( + await crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages) + ) + } catch (err) { + if ( + algorithm.name === 'Ed25519' && + (err)?.name === 'NotSupportedError' && + isCloudflareWorkers() + ) { + algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } + return <{ publicKey: CryptoKey; privateKey: CryptoKey }>( + await crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages) + ) + } + throw err + } +} diff --git a/dist/deno/runtime/get_sign_verify_key.ts b/dist/deno/runtime/get_sign_verify_key.ts new file mode 100644 index 0000000000..9a813f8e3c --- /dev/null +++ b/dist/deno/runtime/get_sign_verify_key.ts @@ -0,0 +1,26 @@ +import crypto, { isCryptoKey } from './webcrypto.ts' +import { checkSigCryptoKey } from '../lib/crypto_key.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { types } from './is_key_like.ts' + +export default function getCryptoKey(alg: string, key: unknown, usage: KeyUsage) { + if (isCryptoKey(key)) { + checkSigCryptoKey(key, alg, usage) + return key + } + + if (key instanceof Uint8Array) { + if (!alg.startsWith('HS')) { + throw new TypeError(invalidKeyInput(key, ...types)) + } + return crypto.subtle.importKey( + 'raw', + key, + { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, + false, + [usage], + ) + } + + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) +} diff --git a/dist/deno/runtime/interfaces.d.ts b/dist/deno/runtime/interfaces.d.ts new file mode 100644 index 0000000000..242c79603f --- /dev/null +++ b/dist/deno/runtime/interfaces.d.ts @@ -0,0 +1,75 @@ +import type { JWK, KeyLike } from '../types.d.ts' +import type { PEMImportOptions } from '../key/import.ts' + +type AsyncOrSync = Promise | T + +export interface TimingSafeEqual { + (a: Uint8Array, b: Uint8Array): boolean +} +export interface SignFunction { + (alg: string, key: unknown, data: Uint8Array): Promise +} +export interface VerifyFunction { + (alg: string, key: unknown, signature: Uint8Array, data: Uint8Array): Promise +} +export interface AesKwWrapFunction { + (alg: string, key: unknown, cek: Uint8Array): AsyncOrSync +} +export interface AesKwUnwrapFunction { + (alg: string, key: unknown, encryptedKey: Uint8Array): AsyncOrSync +} +export interface RsaEsEncryptFunction { + (alg: string, key: unknown, cek: Uint8Array): AsyncOrSync +} +export interface RsaEsDecryptFunction { + (alg: string, key: unknown, encryptedKey: Uint8Array): AsyncOrSync +} +export interface Pbes2KWEncryptFunction { + (alg: string, key: unknown, cek: Uint8Array, p2c?: number, p2s?: Uint8Array): Promise<{ + encryptedKey: Uint8Array + p2c: number + p2s: string + }> +} +export interface Pbes2KWDecryptFunction { + ( + alg: string, + key: unknown, + encryptedKey: Uint8Array, + p2c: number, + p2s: Uint8Array, + ): Promise +} +export interface EncryptFunction { + (enc: string, plaintext: Uint8Array, cek: unknown, iv: Uint8Array, aad: Uint8Array): AsyncOrSync<{ + ciphertext: Uint8Array + tag: Uint8Array + }> +} +export interface DecryptFunction { + ( + enc: string, + cek: unknown, + ciphertext: Uint8Array, + iv: Uint8Array, + tag: Uint8Array, + additionalData: Uint8Array, + ): AsyncOrSync +} +export interface FetchFunction { + (url: URL, timeout: number, options?: any): Promise<{ [propName: string]: unknown }> +} +export interface DigestFunction { + (digest: 'sha256' | 'sha384' | 'sha512', data: Uint8Array): AsyncOrSync +} +export interface JWKImportFunction { + (jwk: JWK): AsyncOrSync +} +export interface PEMImportFunction { + (pem: string, alg: string, options?: PEMImportOptions): AsyncOrSync +} +interface ExportFunction { + (key: unknown): AsyncOrSync +} +export type JWKExportFunction = ExportFunction +export type PEMExportFunction = ExportFunction diff --git a/dist/deno/runtime/is_key_like.ts b/dist/deno/runtime/is_key_like.ts new file mode 100644 index 0000000000..7023da56fc --- /dev/null +++ b/dist/deno/runtime/is_key_like.ts @@ -0,0 +1,8 @@ +import type { KeyLike } from '../types.d.ts' +import { isCryptoKey } from './webcrypto.ts' + +export default (key: unknown): key is KeyLike => { + return isCryptoKey(key) +} + +export const types = ['CryptoKey'] diff --git a/dist/deno/runtime/jwk_to_key.ts b/dist/deno/runtime/jwk_to_key.ts new file mode 100644 index 0000000000..8367979fff --- /dev/null +++ b/dist/deno/runtime/jwk_to_key.ts @@ -0,0 +1,167 @@ +import { isCloudflareWorkers } from './env.ts' +import crypto from './webcrypto.ts' +import type { JWKImportFunction } from './interfaces.d.ts' +import { JOSENotSupported } from '../util/errors.ts' +import type { JWK } from '../types.d.ts' +import { decode as base64url } from './base64url.ts' + +function subtleMapping(jwk: JWK): { + algorithm: RsaHashedImportParams | EcKeyAlgorithm | Algorithm + keyUsages: KeyUsage[] +} { + let algorithm: RsaHashedImportParams | EcKeyAlgorithm | Algorithm + let keyUsages: KeyUsage[] + + switch (jwk.kty) { + case 'oct': { + switch (jwk.alg) { + case 'HS256': + case 'HS384': + case 'HS512': + algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.slice(-3)}` } + keyUsages = ['sign', 'verify'] + break + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`) + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': + algorithm = { name: 'AES-GCM' } + keyUsages = ['encrypt', 'decrypt'] + break + case 'A128KW': + case 'A192KW': + case 'A256KW': + algorithm = { name: 'AES-KW' } + keyUsages = ['wrapKey', 'unwrapKey'] + break + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': + algorithm = { name: 'PBKDF2' } + keyUsages = ['deriveBits'] + break + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') + } + break + } + case 'RSA': { + switch (jwk.alg) { + case 'PS256': + case 'PS384': + case 'PS512': + algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` } + keyUsages = jwk.d ? ['sign'] : ['verify'] + break + case 'RS256': + case 'RS384': + case 'RS512': + algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` } + keyUsages = jwk.d ? ['sign'] : ['verify'] + break + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + algorithm = { + name: 'RSA-OAEP', + hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`, + } + keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'] + break + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') + } + break + } + case 'EC': { + switch (jwk.alg) { + case 'ES256': + algorithm = { name: 'ECDSA', namedCurve: 'P-256' } + keyUsages = jwk.d ? ['sign'] : ['verify'] + break + case 'ES384': + algorithm = { name: 'ECDSA', namedCurve: 'P-384' } + keyUsages = jwk.d ? ['sign'] : ['verify'] + break + case 'ES512': + algorithm = { name: 'ECDSA', namedCurve: 'P-521' } + keyUsages = jwk.d ? ['sign'] : ['verify'] + break + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': + algorithm = { name: 'ECDH', namedCurve: jwk.crv! } + keyUsages = jwk.d ? ['deriveBits'] : [] + break + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') + } + break + } + case 'OKP': { + switch (jwk.alg) { + case 'EdDSA': + algorithm = { name: jwk.crv! } + keyUsages = jwk.d ? ['sign'] : ['verify'] + break + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': + algorithm = { name: jwk.crv! } + keyUsages = jwk.d ? ['deriveBits'] : [] + break + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value') + } + break + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value') + } + + return { algorithm, keyUsages } +} + +const parse: JWKImportFunction = async (jwk: JWK): Promise => { + if (!jwk.alg) { + throw new TypeError('"alg" argument is required when "jwk.alg" is not present') + } + + const { algorithm, keyUsages } = subtleMapping(jwk) + const rest: [RsaHashedImportParams | EcKeyAlgorithm | Algorithm, boolean, KeyUsage[]] = [ + algorithm, + jwk.ext ?? false, + jwk.key_ops ?? keyUsages, + ] + + if (algorithm.name === 'PBKDF2') { + return crypto.subtle.importKey('raw', base64url(jwk.k!), ...rest) + } + + const keyData: JWK = { ...jwk } + delete keyData.alg + delete keyData.use + try { + return await crypto.subtle.importKey('jwk', keyData, ...rest) + } catch (err) { + if ( + algorithm.name === 'Ed25519' && + (err)?.name === 'NotSupportedError' && + isCloudflareWorkers() + ) { + rest[0] = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } + return await crypto.subtle.importKey('jwk', keyData, ...rest) + } + throw err + } +} +export default parse diff --git a/dist/deno/runtime/key_to_jwk.ts b/dist/deno/runtime/key_to_jwk.ts new file mode 100644 index 0000000000..c279b618cc --- /dev/null +++ b/dist/deno/runtime/key_to_jwk.ts @@ -0,0 +1,25 @@ +import crypto, { isCryptoKey } from './webcrypto.ts' +import type { JWKExportFunction } from './interfaces.d.ts' +import type { JWK } from '../types.d.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { encode as base64url } from './base64url.ts' +import { types } from './is_key_like.ts' + +const keyToJWK: JWKExportFunction = async (key: unknown): Promise => { + if (key instanceof Uint8Array) { + return { + kty: 'oct', + k: base64url(key), + } + } + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) + } + if (!key.extractable) { + throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK') + } + const { ext, key_ops, alg, use, ...jwk } = await crypto.subtle.exportKey('jwk', key) + + return jwk +} +export default keyToJWK diff --git a/dist/deno/runtime/pbes2kw.ts b/dist/deno/runtime/pbes2kw.ts new file mode 100644 index 0000000000..03976bdcc7 --- /dev/null +++ b/dist/deno/runtime/pbes2kw.ts @@ -0,0 +1,78 @@ +import type { Pbes2KWDecryptFunction, Pbes2KWEncryptFunction } from './interfaces.d.ts' +import random from './random.ts' +import { p2s as concatSalt } from '../lib/buffer_utils.ts' +import { encode as base64url } from './base64url.ts' +import { wrap, unwrap } from './aeskw.ts' +import checkP2s from '../lib/check_p2s.ts' +import crypto, { isCryptoKey } from './webcrypto.ts' +import { checkEncCryptoKey } from '../lib/crypto_key.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { types } from './is_key_like.ts' + +function getCryptoKey(key: unknown, alg: string) { + if (key instanceof Uint8Array) { + return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']) + } + + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey') + return key + } + + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')) +} + +async function deriveKey(p2s: Uint8Array, alg: string, p2c: number, key: unknown) { + checkP2s(p2s) + + const salt = concatSalt(alg, p2s) + const keylen = parseInt(alg.slice(13, 16), 10) + const subtleAlg = { + hash: `SHA-${alg.slice(8, 11)}`, + iterations: p2c, + name: 'PBKDF2', + salt, + } + const wrapAlg = { + length: keylen, + name: 'AES-KW', + } + + const cryptoKey = await getCryptoKey(key, alg) + + if (cryptoKey.usages.includes('deriveBits')) { + return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen)) + } + + if (cryptoKey.usages.includes('deriveKey')) { + return crypto.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ['wrapKey', 'unwrapKey']) + } + + throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"') +} + +export const encrypt: Pbes2KWEncryptFunction = async ( + alg: string, + key: unknown, + cek: Uint8Array, + p2c: number = 2048, + p2s: Uint8Array = random(new Uint8Array(16)), +) => { + const derived = await deriveKey(p2s, alg, p2c, key) + + const encryptedKey = await wrap(alg.slice(-6), derived, cek) + + return { encryptedKey, p2c, p2s: base64url(p2s) } +} + +export const decrypt: Pbes2KWDecryptFunction = async ( + alg: string, + key: unknown, + encryptedKey: Uint8Array, + p2c: number, + p2s: Uint8Array, +) => { + const derived = await deriveKey(p2s, alg, p2c, key) + + return unwrap(alg.slice(-6), derived, encryptedKey) +} diff --git a/dist/deno/runtime/random.ts b/dist/deno/runtime/random.ts new file mode 100644 index 0000000000..b885796ffb --- /dev/null +++ b/dist/deno/runtime/random.ts @@ -0,0 +1,3 @@ +import crypto from './webcrypto.ts' + +export default crypto.getRandomValues.bind(crypto) diff --git a/dist/deno/runtime/rsaes.ts b/dist/deno/runtime/rsaes.ts new file mode 100644 index 0000000000..e5e4bd514e --- /dev/null +++ b/dist/deno/runtime/rsaes.ts @@ -0,0 +1,64 @@ +import type { RsaEsDecryptFunction, RsaEsEncryptFunction } from './interfaces.d.ts' +import subtleAlgorithm from './subtle_rsaes.ts' +import bogusWebCrypto from './bogus.ts' +import crypto, { isCryptoKey } from './webcrypto.ts' +import { checkEncCryptoKey } from '../lib/crypto_key.ts' +import checkKeyLength from './check_key_length.ts' +import invalidKeyInput from '../lib/invalid_key_input.ts' +import { types } from './is_key_like.ts' + +export const encrypt: RsaEsEncryptFunction = async (alg: string, key: unknown, cek: Uint8Array) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)) + } + checkEncCryptoKey(key, alg, 'encrypt', 'wrapKey') + checkKeyLength(alg, key) + + if (key.usages.includes('encrypt')) { + return new Uint8Array(await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek)) + } + + if (key.usages.includes('wrapKey')) { + // we're importing the cek to end up with CryptoKey instance that can be wrapped, the algorithm used is irrelevant + const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto) + return new Uint8Array( + await crypto.subtle.wrapKey('raw', cryptoKeyCek, key, subtleAlgorithm(alg)), + ) + } + + throw new TypeError( + 'RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation', + ) +} + +export const decrypt: RsaEsDecryptFunction = async ( + alg: string, + key: unknown, + encryptedKey: Uint8Array, +) => { + if (!isCryptoKey(key)) { + throw new TypeError(invalidKeyInput(key, ...types)) + } + checkEncCryptoKey(key, alg, 'decrypt', 'unwrapKey') + checkKeyLength(alg, key) + + if (key.usages.includes('decrypt')) { + return new Uint8Array(await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey)) + } + + if (key.usages.includes('unwrapKey')) { + const cryptoKeyCek = await crypto.subtle.unwrapKey( + 'raw', + encryptedKey, + key, + subtleAlgorithm(alg), + ...bogusWebCrypto, + ) + + return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek)) + } + + throw new TypeError( + 'RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation', + ) +} diff --git a/dist/deno/runtime/sign.ts b/dist/deno/runtime/sign.ts new file mode 100644 index 0000000000..8a0c5af1b6 --- /dev/null +++ b/dist/deno/runtime/sign.ts @@ -0,0 +1,18 @@ +import type { SignFunction } from './interfaces.d.ts' +import subtleAlgorithm from './subtle_dsa.ts' +import crypto from './webcrypto.ts' +import checkKeyLength from './check_key_length.ts' +import getSignKey from './get_sign_verify_key.ts' + +const sign: SignFunction = async (alg, key: unknown, data) => { + const cryptoKey = await getSignKey(alg, key, 'sign') + checkKeyLength(alg, cryptoKey) + const signature = await crypto.subtle.sign( + subtleAlgorithm(alg, cryptoKey.algorithm), + cryptoKey, + data, + ) + return new Uint8Array(signature) +} + +export default sign diff --git a/dist/deno/runtime/subtle_dsa.ts b/dist/deno/runtime/subtle_dsa.ts new file mode 100644 index 0000000000..db40dc693e --- /dev/null +++ b/dist/deno/runtime/subtle_dsa.ts @@ -0,0 +1,35 @@ +import { isCloudflareWorkers } from './env.ts' +import { JOSENotSupported } from '../util/errors.ts' + +export default function subtleDsa(alg: string, algorithm: KeyAlgorithm | EcKeyAlgorithm) { + const hash = `SHA-${alg.slice(-3)}` + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': + return { hash, name: 'HMAC' } + case 'PS256': + case 'PS384': + case 'PS512': + // @ts-expect-error + return { hash, name: 'RSA-PSS', saltLength: alg.slice(-3) >> 3 } + case 'RS256': + case 'RS384': + case 'RS512': + return { hash, name: 'RSASSA-PKCS1-v1_5' } + case 'ES256': + case 'ES384': + case 'ES512': + return { hash, name: 'ECDSA', namedCurve: (algorithm).namedCurve } + case 'EdDSA': + if (isCloudflareWorkers() && algorithm.name === 'NODE-ED25519') { + return { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' } + } + + return { name: algorithm.name } + default: + throw new JOSENotSupported( + `alg ${alg} is not supported either by JOSE or your javascript runtime`, + ) + } +} diff --git a/dist/deno/runtime/subtle_rsaes.ts b/dist/deno/runtime/subtle_rsaes.ts new file mode 100644 index 0000000000..16fb3d3c59 --- /dev/null +++ b/dist/deno/runtime/subtle_rsaes.ts @@ -0,0 +1,15 @@ +import { JOSENotSupported } from '../util/errors.ts' + +export default function subtleRsaEs(alg: string) { + switch (alg) { + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + return 'RSA-OAEP' + default: + throw new JOSENotSupported( + `alg ${alg} is not supported either by JOSE or your javascript runtime`, + ) + } +} diff --git a/dist/deno/runtime/timing_safe_equal.ts b/dist/deno/runtime/timing_safe_equal.ts new file mode 100644 index 0000000000..53bc719686 --- /dev/null +++ b/dist/deno/runtime/timing_safe_equal.ts @@ -0,0 +1,23 @@ +import type { TimingSafeEqual } from './interfaces.d.ts' + +const timingSafeEqual: TimingSafeEqual = (a, b) => { + if (!(a instanceof Uint8Array)) { + throw new TypeError('First argument must be a buffer') + } + if (!(b instanceof Uint8Array)) { + throw new TypeError('Second argument must be a buffer') + } + if (a.length !== b.length) { + throw new TypeError('Input buffers must have the same length') + } + + const len = a.length + let out = 0 + let i = -1 + while (++i < len) { + out |= a[i] ^ b[i] + } + return out === 0 +} + +export default timingSafeEqual diff --git a/dist/deno/runtime/verify.ts b/dist/deno/runtime/verify.ts new file mode 100644 index 0000000000..c904d9422e --- /dev/null +++ b/dist/deno/runtime/verify.ts @@ -0,0 +1,18 @@ +import type { VerifyFunction } from './interfaces.d.ts' +import subtleAlgorithm from './subtle_dsa.ts' +import crypto from './webcrypto.ts' +import checkKeyLength from './check_key_length.ts' +import getVerifyKey from './get_sign_verify_key.ts' + +const verify: VerifyFunction = async (alg, key: unknown, signature, data) => { + const cryptoKey = await getVerifyKey(alg, key, 'verify') + checkKeyLength(alg, cryptoKey) + const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm) + try { + return await crypto.subtle.verify(algorithm, cryptoKey, signature, data) + } catch { + return false + } +} + +export default verify diff --git a/dist/deno/runtime/webcrypto.ts b/dist/deno/runtime/webcrypto.ts new file mode 100644 index 0000000000..fd524e1fe4 --- /dev/null +++ b/dist/deno/runtime/webcrypto.ts @@ -0,0 +1,3 @@ +export default crypto + +export const isCryptoKey = (key: unknown): key is CryptoKey => key instanceof CryptoKey diff --git a/dist/deno/runtime/zlib.ts b/dist/deno/runtime/zlib.ts new file mode 100644 index 0000000000..653d1b419f --- /dev/null +++ b/dist/deno/runtime/zlib.ts @@ -0,0 +1,13 @@ +import { JOSENotSupported } from '../util/errors.ts' +import type { InflateFunction, DeflateFunction } from '../types.d.ts' + +export const inflate: InflateFunction = async () => { + throw new JOSENotSupported( + 'JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.', + ) +} +export const deflate: DeflateFunction = async () => { + throw new JOSENotSupported( + 'JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.', + ) +} diff --git a/dist/deno/types.d.ts b/dist/deno/types.d.ts new file mode 100644 index 0000000000..3310685b47 --- /dev/null +++ b/dist/deno/types.d.ts @@ -0,0 +1,628 @@ +/** + * KeyLike are runtime-specific classes representing asymmetric keys or symmetric secrets. These are + * instances of [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) and + * additionally [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) in Node.js runtime. + * [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) + * instances are also accepted as symmetric secret representation only. + * + * [Key Import Functions](../modules/key_import.md#readme) can be used to import PEM, or JWK + * formatted asymmetric keys and certificates to these runtime-specific representations. + * + * In Node.js the [Buffer](https://nodejs.org/api/buffer.html#buffer) class is a subclass of + * Uint8Array and so Buffer can be provided for symmetric secrets as well. + * + * [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) is a representation of a + * key/secret available in the Node.js runtime. In addition to the import functions of this library + * you may use the runtime APIs + * [crypto.createPublicKey](https://nodejs.org/api/crypto.html#cryptocreatepublickeykey), + * [crypto.createPrivateKey](https://nodejs.org/api/crypto.html#cryptocreateprivatekeykey), and + * [crypto.createSecretKey](https://nodejs.org/api/crypto.html#cryptocreatesecretkeykey-encoding) to + * obtain a KeyObject from your existing key material. + * + * [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) is a representation of a + * key/secret available in the Browser and Web-interoperable runtimes. In addition to the import + * functions of this library you may use the + * [SubtleCrypto.importKey](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) + * API to obtain a CryptoKey from your existing key material. + * + * @example Import a PEM-encoded SPKI Public Key + * + * ```js + * const algorithm = 'ES256' + * const spki = `-----BEGIN PUBLIC KEY----- + * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM + * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== + * -----END PUBLIC KEY-----` + * const ecPublicKey = await jose.importSPKI(spki, algorithm) + * ``` + * + * @example Import SPKI from an X.509 Certificate + * + * ```js + * const algorithm = 'ES256' + * const x509 = `-----BEGIN CERTIFICATE----- + * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np + * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw + * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN + * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI + * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 + * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA + * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh + * v+A1QWZMuTWqYt+uh/YSRNDn + * -----END CERTIFICATE-----` + * const ecPublicKey = await jose.importX509(x509, algorithm) + * ``` + * + * @example Import a PEM-encoded PKCS8 Private Key + * + * ```js + * const algorithm = 'ES256' + * const pkcs8 = `-----BEGIN PRIVATE KEY----- + * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN + * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg + * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa + * -----END PRIVATE KEY-----` + * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) + * ``` + * + * @example Import a JSON Web Key (JWK) + * + * ```js + * const ecPublicKey = await jose.importJWK( + * { + * crv: 'P-256', + * kty: 'EC', + * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', + * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', + * }, + * 'ES256', + * ) + * + * const rsaPublicKey = await jose.importJWK( + * { + * kty: 'RSA', + * e: 'AQAB', + * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', + * }, + * 'PS256', + * ) + * ``` + */ +export type KeyLike = { type: string } + +/** + * JSON Web Key ([JWK](https://www.rfc-editor.org/rfc/rfc7517)). "RSA", "EC", "OKP", and "oct" key + * types are supported. + */ +export interface JWK { + /** JWK "alg" (Algorithm) Parameter. */ + alg?: string + crv?: string + d?: string + dp?: string + dq?: string + e?: string + /** JWK "ext" (Extractable) Parameter. */ + ext?: boolean + k?: string + /** JWK "key_ops" (Key Operations) Parameter. */ + key_ops?: string[] + /** JWK "kid" (Key ID) Parameter. */ + kid?: string + /** JWK "kty" (Key Type) Parameter. */ + kty?: string + n?: string + oth?: Array<{ + d?: string + r?: string + t?: string + }> + p?: string + q?: string + qi?: string + /** JWK "use" (Public Key Use) Parameter. */ + use?: string + x?: string + y?: string + /** JWK "x5c" (X.509 Certificate Chain) Parameter. */ + x5c?: string[] + /** JWK "x5t" (X.509 Certificate SHA-1 Thumbprint) Parameter. */ + x5t?: string + /** "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Parameter. */ + 'x5t#S256'?: string + /** JWK "x5u" (X.509 URL) Parameter. */ + x5u?: string + + [propName: string]: unknown +} + +/** + * Generic Interface for consuming operations dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * If you cannot match a key suitable for the token, throw an error instead. + * + * @param protectedHeader JWE or JWS Protected Header. + * @param token The consumed JWE or JWS token. + */ +export interface GetKeyFunction { + (protectedHeader: T, token: T2): Promise | KeyLike | Uint8Array +} + +/** + * Flattened JWS definition for verify function inputs, allows payload as Uint8Array for detached + * signature validation. + */ +export interface FlattenedJWSInput { + /** + * The "header" member MUST be present and contain the value JWS Unprotected Header when the JWS + * Unprotected Header value is non- empty; otherwise, it MUST be absent. This value is represented + * as an unencoded JSON object, rather than as a string. These Header Parameter values are not + * integrity protected. + */ + header?: JWSHeaderParameters + + /** + * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 + * "b64": false is used the value passed may also be a Uint8Array. + */ + payload: string | Uint8Array + + /** + * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWS Protected + * Header)) when the JWS Protected Header value is non-empty; otherwise, it MUST be absent. These + * Header Parameter values are integrity protected. + */ + protected?: string + + /** The "signature" member MUST be present and contain the value BASE64URL(JWS Signature). */ + signature: string +} + +/** + * General JWS definition for verify function inputs, allows payload as Uint8Array for detached + * signature validation. + */ +export interface GeneralJWSInput { + /** + * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 + * "b64": false is used the value passed may also be a Uint8Array. + */ + payload: string | Uint8Array + + /** + * The "signatures" member value MUST be an array of JSON objects. Each object represents a + * signature or MAC over the JWS Payload and the JWS Protected Header. + */ + signatures: Omit[] +} + +/** + * Flattened JWS definition. Payload is returned as an empty string when JWS Unencoded Payload + * Option [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. + */ +export interface FlattenedJWS extends Partial { + payload: string + signature: string +} + +/** + * General JWS definition. Payload is returned as an empty string when JWS Unencoded Payload Option + * [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. + */ +export interface GeneralJWS { + payload: string + signatures: Omit[] +} + +export interface JoseHeaderParameters { + /** "kid" (Key ID) Header Parameter. */ + kid?: string + + /** "x5t" (X.509 Certificate SHA-1 Thumbprint) Header Parameter. */ + x5t?: string + + /** "x5c" (X.509 Certificate Chain) Header Parameter. */ + x5c?: string[] + + /** "x5u" (X.509 URL) Header Parameter. */ + x5u?: string + + /** "jku" (JWK Set URL) Header Parameter. */ + jku?: string + + /** "jwk" (JSON Web Key) Header Parameter. */ + jwk?: Pick + + /** "typ" (Type) Header Parameter. */ + typ?: string + + /** "cty" (Content Type) Header Parameter. */ + cty?: string +} + +/** Recognized JWS Header Parameters, any other Header Members may also be present. */ +export interface JWSHeaderParameters extends JoseHeaderParameters { + /** JWS "alg" (Algorithm) Header Parameter. */ + alg?: string + + /** + * This JWS Extension Header Parameter modifies the JWS Payload representation and the JWS Signing + * Input computation as per [RFC7797](https://www.rfc-editor.org/rfc/rfc7797). + */ + b64?: boolean + + /** JWS "crit" (Critical) Header Parameter. */ + crit?: string[] + + /** Any other JWS Header member. */ + [propName: string]: unknown +} + +/** Recognized JWE Key Management-related Header Parameters. */ +export interface JWEKeyManagementHeaderParameters { + apu?: Uint8Array + apv?: Uint8Array + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + p2c?: number + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + p2s?: Uint8Array + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + iv?: Uint8Array + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + epk?: KeyLike +} + +/** Flattened JWE definition. */ +export interface FlattenedJWE { + /** + * The "aad" member MUST be present and contain the value BASE64URL(JWE AAD)) when the JWE AAD + * value is non-empty; otherwise, it MUST be absent. A JWE AAD value can be included to supply a + * base64url-encoded value to be integrity protected but not encrypted. + */ + aad?: string + + /** The "ciphertext" member MUST be present and contain the value BASE64URL(JWE Ciphertext). */ + ciphertext: string + + /** + * The "encrypted_key" member MUST be present and contain the value BASE64URL(JWE Encrypted Key) + * when the JWE Encrypted Key value is non-empty; otherwise, it MUST be absent. + */ + encrypted_key?: string + + /** + * The "header" member MUST be present and contain the value JWE Per- Recipient Unprotected Header + * when the JWE Per-Recipient Unprotected Header value is non-empty; otherwise, it MUST be absent. + * This value is represented as an unencoded JSON object, rather than as a string. These Header + * Parameter values are not integrity protected. + */ + header?: JWEHeaderParameters + + /** + * The "iv" member MUST be present and contain the value BASE64URL(JWE Initialization Vector) when + * the JWE Initialization Vector value is non-empty; otherwise, it MUST be absent. + */ + iv: string + + /** + * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWE Protected + * Header)) when the JWE Protected Header value is non-empty; otherwise, it MUST be absent. These + * Header Parameter values are integrity protected. + */ + protected?: string + + /** + * The "tag" member MUST be present and contain the value BASE64URL(JWE Authentication Tag) when + * the JWE Authentication Tag value is non-empty; otherwise, it MUST be absent. + */ + tag: string + + /** + * The "unprotected" member MUST be present and contain the value JWE Shared Unprotected Header + * when the JWE Shared Unprotected Header value is non-empty; otherwise, it MUST be absent. This + * value is represented as an unencoded JSON object, rather than as a string. These Header + * Parameter values are not integrity protected. + */ + unprotected?: JWEHeaderParameters +} + +export interface GeneralJWE extends Omit { + recipients: Pick[] +} + +/** Recognized JWE Header Parameters, any other Header members may also be present. */ +export interface JWEHeaderParameters extends JoseHeaderParameters { + /** JWE "alg" (Algorithm) Header Parameter. */ + alg?: string + + /** JWE "enc" (Encryption Algorithm) Header Parameter. */ + enc?: string + + /** JWE "crit" (Critical) Header Parameter. */ + crit?: string[] + + /** JWE "zip" (Compression Algorithm) Header Parameter. */ + zip?: string + + /** Any other JWE Header member. */ + [propName: string]: unknown +} + +/** Shared Interface with a "crit" property for all sign, verify, encrypt and decrypt operations. */ +export interface CritOption { + /** + * An object with keys representing recognized "crit" (Critical) Header Parameter names. The value + * for those is either `true` or `false`. `true` when the Header Parameter MUST be integrity + * protected, `false` when it's irrelevant. + * + * This makes the "Extension Header Parameter "..." is not recognized" error go away. + * + * Use this when a given JWS/JWT/JWE profile requires the use of proprietary non-registered "crit" + * (Critical) Header Parameters. This will only make sure the Header Parameter is syntactically + * correct when provided and that it is optionally integrity protected. It will not process the + * Header Parameter in any way or reject the operation if it is missing. You MUST still verify the + * Header Parameter was present and process it according to the profile's validation steps after + * the operation succeeds. + * + * The JWS extension Header Parameter `b64` is always recognized and processed properly. No other + * registered Header Parameters that need this kind of default built-in treatment are currently + * available. + */ + crit?: { + [propName: string]: boolean + } +} + +/** JWE Decryption options. */ +export interface DecryptOptions extends CritOption { + /** A list of accepted JWE "alg" (Algorithm) Header Parameter values. */ + keyManagementAlgorithms?: string[] + + /** + * A list of accepted JWE "enc" (Encryption Algorithm) Header Parameter values. By default all + * "enc" (Encryption Algorithm) values applicable for the used key/secret are allowed. + */ + contentEncryptionAlgorithms?: string[] + + /** + * In a browser runtime you have to provide an implementation for Inflate Raw when you expect JWEs + * with compressed plaintext. + */ + inflateRaw?: InflateFunction + + /** + * (PBES2 Key Management Algorithms only) Maximum allowed "p2c" (PBES2 Count) Header Parameter + * value. The PBKDF2 iteration count defines the algorithm's computational expense. By default + * this value is set to 10000. + */ + maxPBES2Count?: number +} + +/** JWE Deflate option. */ +export interface DeflateOption { + /** + * In a browser runtime you have to provide an implementation for Deflate Raw when you will be + * producing JWEs with compressed plaintext. + */ + deflateRaw?: DeflateFunction +} + +/** JWE Encryption options. */ +export interface EncryptOptions extends CritOption, DeflateOption {} + +/** JWT Claims Set verification options. */ +export interface JWTClaimVerificationOptions { + /** Expected JWT "aud" (Audience) Claim value(s). */ + audience?: string | string[] + + /** + * Expected clock tolerance + * + * - In seconds when number (e.g. 5) + * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). + */ + clockTolerance?: string | number + + /** Expected JWT "iss" (Issuer) Claim value(s). */ + issuer?: string | string[] + + /** + * Maximum time elapsed (in seconds) from the JWT "iat" (Issued At) Claim value. + * + * - In seconds when number (e.g. 5) + * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). + */ + maxTokenAge?: string | number + + /** Expected JWT "sub" (Subject) Claim value. */ + subject?: string + + /** Expected JWT "typ" (Type) Header Parameter value. */ + typ?: string + + /** Date to use when comparing NumericDate claims, defaults to `new Date()`. */ + currentDate?: Date +} + +/** JWS Verification options. */ +export interface VerifyOptions extends CritOption { + /** + * A list of accepted JWS "alg" (Algorithm) Header Parameter values. By default all "alg" + * (Algorithm) values applicable for the used key/secret are allowed. Note: "none" is never + * accepted. + */ + algorithms?: string[] +} + +/** JWS Signing options. */ +export interface SignOptions extends CritOption {} + +/** Recognized JWT Claims Set members, any other members may also be present. */ +export interface JWTPayload { + /** + * JWT Issuer + * + * @see [RFC7519#section-4.1.1](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1) + */ + iss?: string + + /** + * JWT Subject + * + * @see [RFC7519#section-4.1.2](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2) + */ + sub?: string + + /** JWT Audience [RFC7519#section-4.1.3](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3). */ + aud?: string | string[] + + /** + * JWT ID + * + * @see [RFC7519#section-4.1.7](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7) + */ + jti?: string + + /** + * JWT Not Before + * + * @see [RFC7519#section-4.1.5](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5) + */ + nbf?: number + + /** + * JWT Expiration Time + * + * @see [RFC7519#section-4.1.4](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4) + */ + exp?: number + + /** + * JWT Issued At + * + * @see [RFC7519#section-4.1.6](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6) + */ + iat?: number + + /** Any other JWT Claim Set member. */ + [propName: string]: unknown +} + +/** + * Deflate Raw implementation, e.g. promisified + * [zlib.deflateRaw](https://nodejs.org/api/zlib.html#zlibdeflaterawbuffer-options-callback). + */ +export interface DeflateFunction { + (input: Uint8Array): Promise +} + +/** + * Inflate Raw implementation, e.g. promisified + * [zlib.inflateRaw](https://nodejs.org/api/zlib.html#zlibinflaterawbuffer-options-callback). + */ +export interface InflateFunction { + (input: Uint8Array): Promise +} + +export interface FlattenedDecryptResult { + /** JWE AAD. */ + additionalAuthenticatedData?: Uint8Array + + /** Plaintext. */ + plaintext: Uint8Array + + /** JWE Protected Header. */ + protectedHeader?: JWEHeaderParameters + + /** JWE Shared Unprotected Header. */ + sharedUnprotectedHeader?: JWEHeaderParameters + + /** JWE Per-Recipient Unprotected Header. */ + unprotectedHeader?: JWEHeaderParameters +} + +export interface GeneralDecryptResult extends FlattenedDecryptResult {} + +export interface CompactDecryptResult { + /** Plaintext. */ + plaintext: Uint8Array + + /** JWE Protected Header. */ + protectedHeader: CompactJWEHeaderParameters +} + +export interface FlattenedVerifyResult { + /** JWS Payload. */ + payload: Uint8Array + + /** JWS Protected Header. */ + protectedHeader?: JWSHeaderParameters + + /** JWS Unprotected Header. */ + unprotectedHeader?: JWSHeaderParameters +} + +export interface GeneralVerifyResult extends FlattenedVerifyResult {} + +export interface CompactVerifyResult { + /** JWS Payload. */ + payload: Uint8Array + + /** JWS Protected Header. */ + protectedHeader: CompactJWSHeaderParameters +} + +export interface JWTVerifyResult { + /** JWT Claims Set. */ + payload: JWTPayload + + /** JWS Protected Header. */ + protectedHeader: JWTHeaderParameters +} + +export interface JWTDecryptResult { + /** JWT Claims Set. */ + payload: JWTPayload + + /** JWE Protected Header. */ + protectedHeader: CompactJWEHeaderParameters +} + +export interface ResolvedKey { + /** Key resolved from the key resolver function. */ + key: KeyLike | Uint8Array +} + +/** Recognized Compact JWS Header Parameters, any other Header Members may also be present. */ +export interface CompactJWSHeaderParameters extends JWSHeaderParameters { + alg: string +} + +/** Recognized Signed JWT Header Parameters, any other Header Members may also be present. */ +export interface JWTHeaderParameters extends CompactJWSHeaderParameters { + b64?: true +} + +/** Recognized Compact JWE Header Parameters, any other Header Members may also be present. */ +export interface CompactJWEHeaderParameters extends JWEHeaderParameters { + alg: string + enc: string +} + +/** JSON Web Key Set */ +export interface JSONWebKeySet { + keys: JWK[] +} diff --git a/dist/deno/util/base64url.ts b/dist/deno/util/base64url.ts new file mode 100644 index 0000000000..f3d76163fc --- /dev/null +++ b/dist/deno/util/base64url.ts @@ -0,0 +1,21 @@ +import * as base64url from '../runtime/base64url.ts' + +/** + * Utility function to encode a string or Uint8Array as a base64url string. + * + * @param input Value that will be base64url-encoded. + */ +interface Base64UrlEncode { + (input: Uint8Array | string): string +} +/** + * Utility function to decode a base64url encoded string. + * + * @param input Value that will be base64url-decoded. + */ +interface Base64UrlDecode { + (input: Uint8Array | string): Uint8Array +} + +export const encode: Base64UrlEncode = base64url.encode +export const decode: Base64UrlDecode = base64url.decode diff --git a/dist/deno/util/decode_jwt.ts b/dist/deno/util/decode_jwt.ts new file mode 100644 index 0000000000..f5eb8cb13f --- /dev/null +++ b/dist/deno/util/decode_jwt.ts @@ -0,0 +1,49 @@ +import { decode as base64url } from './base64url.ts' +import { decoder } from '../lib/buffer_utils.ts' +import isObject from '../lib/is_object.ts' +import type { JWTPayload } from '../types.d.ts' +import { JWTInvalid } from './errors.ts' + +/** + * Decodes a signed JSON Web Token payload. This does not validate the JWT Claims Set types or + * values. This does not validate the JWS Signature. For a proper Signed JWT Claims Set validation + * and JWS signature verification use `jose.jwtVerify()`. For an encrypted JWT Claims Set validation + * and JWE decryption use `jose.jwtDecrypt()`. + * + * @example Usage + * + * ```js + * const claims = jose.decodeJwt(token) + * console.log(claims) + * ``` + * + * @param jwt JWT token in compact JWS serialization. + */ +export function decodeJwt(jwt: string) { + if (typeof jwt !== 'string') + throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string') + + const { 1: payload, length } = jwt.split('.') + + if (length === 5) throw new JWTInvalid('Only JWTs using Compact JWS serialization can be decoded') + if (length !== 3) throw new JWTInvalid('Invalid JWT') + if (!payload) throw new JWTInvalid('JWTs must contain a payload') + + let decoded: Uint8Array + try { + decoded = base64url(payload) + } catch { + throw new JWTInvalid('Failed to parse the base64url encoded payload') + } + + let result: unknown + try { + result = JSON.parse(decoder.decode(decoded)) + } catch { + throw new JWTInvalid('Failed to parse the decoded payload as JSON') + } + + if (!isObject(result)) throw new JWTInvalid('Invalid JWT Claims Set') + + return result +} diff --git a/dist/deno/util/decode_protected_header.ts b/dist/deno/util/decode_protected_header.ts new file mode 100644 index 0000000000..7e8f91b0fe --- /dev/null +++ b/dist/deno/util/decode_protected_header.ts @@ -0,0 +1,48 @@ +import { decode as base64url } from './base64url.ts' +import { decoder } from '../lib/buffer_utils.ts' +import isObject from '../lib/is_object.ts' +import type { JWSHeaderParameters, JWEHeaderParameters } from '../types.d.ts' + +export type ProtectedHeaderParameters = JWSHeaderParameters & JWEHeaderParameters + +/** + * Decodes the Protected Header of a JWE/JWS/JWT token utilizing any JOSE serialization. + * + * @example Usage + * + * ```js + * const protectedHeader = jose.decodeProtectedHeader(token) + * console.log(protectedHeader) + * ``` + * + * @param token JWE/JWS/JWT token in any JOSE serialization. + */ +export function decodeProtectedHeader(token: string | object) { + let protectedB64u!: string + + if (typeof token === 'string') { + const parts = token.split('.') + if (parts.length === 3 || parts.length === 5) { + ;[protectedB64u] = parts + } + } else if (typeof token === 'object' && token) { + if ('protected' in token) { + protectedB64u = (<{ protected: string }>token).protected + } else { + throw new TypeError('Token does not contain a Protected Header') + } + } + + try { + if (typeof protectedB64u !== 'string' || !protectedB64u) { + throw new Error() + } + const result = JSON.parse(decoder.decode(base64url(protectedB64u!))) + if (!isObject(result)) { + throw new Error() + } + return result + } catch { + throw new TypeError('Invalid Token or Protected Header formatting') + } +} diff --git a/dist/deno/util/errors.ts b/dist/deno/util/errors.ts new file mode 100644 index 0000000000..7eedb68807 --- /dev/null +++ b/dist/deno/util/errors.ts @@ -0,0 +1,185 @@ +import type { KeyLike } from '../types.d.ts' + +/** A generic Error subclass that all other specific JOSE Error subclasses inherit from. */ +export class JOSEError extends Error { + /** A unique error code for the particular error subclass. */ + static get code(): string { + return 'ERR_JOSE_GENERIC' + } + + /** A unique error code for the particular error subclass. */ + code: string = 'ERR_JOSE_GENERIC' + + constructor(message?: string) { + super(message) + this.name = this.constructor.name + // @ts-ignore + Error.captureStackTrace?.(this, this.constructor) + } +} + +/** An error subclass thrown when a JWT Claim Set member validation fails. */ +export class JWTClaimValidationFailed extends JOSEError { + static get code(): 'ERR_JWT_CLAIM_VALIDATION_FAILED' { + return 'ERR_JWT_CLAIM_VALIDATION_FAILED' + } + + code = 'ERR_JWT_CLAIM_VALIDATION_FAILED' + + /** The Claim for which the validation failed. */ + claim: string + + /** Reason code for the validation failure. */ + reason: string + + constructor(message: string, claim = 'unspecified', reason = 'unspecified') { + super(message) + this.claim = claim + this.reason = reason + } +} + +/** An error subclass thrown when a JWT is expired. */ +export class JWTExpired extends JOSEError implements JWTClaimValidationFailed { + static get code(): 'ERR_JWT_EXPIRED' { + return 'ERR_JWT_EXPIRED' + } + + code = 'ERR_JWT_EXPIRED' + + /** The Claim for which the validation failed. */ + claim: string + + /** Reason code for the validation failure. */ + reason: string + + constructor(message: string, claim = 'unspecified', reason = 'unspecified') { + super(message) + this.claim = claim + this.reason = reason + } +} + +/** An error subclass thrown when a JOSE Algorithm is not allowed per developer preference. */ +export class JOSEAlgNotAllowed extends JOSEError { + static get code(): 'ERR_JOSE_ALG_NOT_ALLOWED' { + return 'ERR_JOSE_ALG_NOT_ALLOWED' + } + + code = 'ERR_JOSE_ALG_NOT_ALLOWED' +} + +/** + * An error subclass thrown when a particular feature or algorithm is not supported by this + * implementation or JOSE in general. + */ +export class JOSENotSupported extends JOSEError { + static get code(): 'ERR_JOSE_NOT_SUPPORTED' { + return 'ERR_JOSE_NOT_SUPPORTED' + } + + code = 'ERR_JOSE_NOT_SUPPORTED' +} + +/** An error subclass thrown when a JWE ciphertext decryption fails. */ +export class JWEDecryptionFailed extends JOSEError { + static get code(): 'ERR_JWE_DECRYPTION_FAILED' { + return 'ERR_JWE_DECRYPTION_FAILED' + } + + code = 'ERR_JWE_DECRYPTION_FAILED' + + message = 'decryption operation failed' +} + +/** An error subclass thrown when a JWE is invalid. */ +export class JWEInvalid extends JOSEError { + static get code(): 'ERR_JWE_INVALID' { + return 'ERR_JWE_INVALID' + } + + code = 'ERR_JWE_INVALID' +} + +/** An error subclass thrown when a JWS is invalid. */ +export class JWSInvalid extends JOSEError { + static get code(): 'ERR_JWS_INVALID' { + return 'ERR_JWS_INVALID' + } + + code = 'ERR_JWS_INVALID' +} + +/** An error subclass thrown when a JWT is invalid. */ +export class JWTInvalid extends JOSEError { + static get code(): 'ERR_JWT_INVALID' { + return 'ERR_JWT_INVALID' + } + + code = 'ERR_JWT_INVALID' +} + +/** An error subclass thrown when a JWK is invalid. */ +export class JWKInvalid extends JOSEError { + static get code(): 'ERR_JWK_INVALID' { + return 'ERR_JWK_INVALID' + } + + code = 'ERR_JWK_INVALID' +} + +/** An error subclass thrown when a JWKS is invalid. */ +export class JWKSInvalid extends JOSEError { + static get code(): 'ERR_JWKS_INVALID' { + return 'ERR_JWKS_INVALID' + } + + code = 'ERR_JWKS_INVALID' +} + +/** An error subclass thrown when no keys match from a JWKS. */ +export class JWKSNoMatchingKey extends JOSEError { + static get code(): 'ERR_JWKS_NO_MATCHING_KEY' { + return 'ERR_JWKS_NO_MATCHING_KEY' + } + + code = 'ERR_JWKS_NO_MATCHING_KEY' + + message = 'no applicable key found in the JSON Web Key Set' +} + +/** An error subclass thrown when multiple keys match from a JWKS. */ +export class JWKSMultipleMatchingKeys extends JOSEError { + /** @ignore */ + [Symbol.asyncIterator]!: () => AsyncIterableIterator + + static get code(): 'ERR_JWKS_MULTIPLE_MATCHING_KEYS' { + return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS' + } + + code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS' + + message = 'multiple matching keys found in the JSON Web Key Set' +} + +/** Timeout was reached when retrieving the JWKS response. */ +export class JWKSTimeout extends JOSEError { + static get code(): 'ERR_JWKS_TIMEOUT' { + return 'ERR_JWKS_TIMEOUT' + } + + code = 'ERR_JWKS_TIMEOUT' + + message = 'request timed out' +} + +/** An error subclass thrown when JWS signature verification fails. */ +export class JWSSignatureVerificationFailed extends JOSEError { + static get code(): 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED' { + return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED' + } + + code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED' + + message = 'signature verification failed' +} diff --git a/dist/node/cjs/index.js b/dist/node/cjs/index.js new file mode 100644 index 0000000000..5f41840500 --- /dev/null +++ b/dist/node/cjs/index.js @@ -0,0 +1,65 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.base64url = exports.generateSecret = exports.generateKeyPair = exports.errors = exports.decodeJwt = exports.decodeProtectedHeader = exports.importJWK = exports.importX509 = exports.importPKCS8 = exports.importSPKI = exports.exportJWK = exports.exportSPKI = exports.exportPKCS8 = exports.UnsecuredJWT = exports.createRemoteJWKSet = exports.createLocalJWKSet = exports.EmbeddedJWK = exports.calculateJwkThumbprintUri = exports.calculateJwkThumbprint = exports.EncryptJWT = exports.SignJWT = exports.GeneralSign = exports.FlattenedSign = exports.CompactSign = exports.FlattenedEncrypt = exports.CompactEncrypt = exports.jwtDecrypt = exports.jwtVerify = exports.generalVerify = exports.flattenedVerify = exports.compactVerify = exports.GeneralEncrypt = exports.generalDecrypt = exports.flattenedDecrypt = exports.compactDecrypt = void 0; +var decrypt_js_1 = require("./jwe/compact/decrypt.js"); +Object.defineProperty(exports, "compactDecrypt", { enumerable: true, get: function () { return decrypt_js_1.compactDecrypt; } }); +var decrypt_js_2 = require("./jwe/flattened/decrypt.js"); +Object.defineProperty(exports, "flattenedDecrypt", { enumerable: true, get: function () { return decrypt_js_2.flattenedDecrypt; } }); +var decrypt_js_3 = require("./jwe/general/decrypt.js"); +Object.defineProperty(exports, "generalDecrypt", { enumerable: true, get: function () { return decrypt_js_3.generalDecrypt; } }); +var encrypt_js_1 = require("./jwe/general/encrypt.js"); +Object.defineProperty(exports, "GeneralEncrypt", { enumerable: true, get: function () { return encrypt_js_1.GeneralEncrypt; } }); +var verify_js_1 = require("./jws/compact/verify.js"); +Object.defineProperty(exports, "compactVerify", { enumerable: true, get: function () { return verify_js_1.compactVerify; } }); +var verify_js_2 = require("./jws/flattened/verify.js"); +Object.defineProperty(exports, "flattenedVerify", { enumerable: true, get: function () { return verify_js_2.flattenedVerify; } }); +var verify_js_3 = require("./jws/general/verify.js"); +Object.defineProperty(exports, "generalVerify", { enumerable: true, get: function () { return verify_js_3.generalVerify; } }); +var verify_js_4 = require("./jwt/verify.js"); +Object.defineProperty(exports, "jwtVerify", { enumerable: true, get: function () { return verify_js_4.jwtVerify; } }); +var decrypt_js_4 = require("./jwt/decrypt.js"); +Object.defineProperty(exports, "jwtDecrypt", { enumerable: true, get: function () { return decrypt_js_4.jwtDecrypt; } }); +var encrypt_js_2 = require("./jwe/compact/encrypt.js"); +Object.defineProperty(exports, "CompactEncrypt", { enumerable: true, get: function () { return encrypt_js_2.CompactEncrypt; } }); +var encrypt_js_3 = require("./jwe/flattened/encrypt.js"); +Object.defineProperty(exports, "FlattenedEncrypt", { enumerable: true, get: function () { return encrypt_js_3.FlattenedEncrypt; } }); +var sign_js_1 = require("./jws/compact/sign.js"); +Object.defineProperty(exports, "CompactSign", { enumerable: true, get: function () { return sign_js_1.CompactSign; } }); +var sign_js_2 = require("./jws/flattened/sign.js"); +Object.defineProperty(exports, "FlattenedSign", { enumerable: true, get: function () { return sign_js_2.FlattenedSign; } }); +var sign_js_3 = require("./jws/general/sign.js"); +Object.defineProperty(exports, "GeneralSign", { enumerable: true, get: function () { return sign_js_3.GeneralSign; } }); +var sign_js_4 = require("./jwt/sign.js"); +Object.defineProperty(exports, "SignJWT", { enumerable: true, get: function () { return sign_js_4.SignJWT; } }); +var encrypt_js_4 = require("./jwt/encrypt.js"); +Object.defineProperty(exports, "EncryptJWT", { enumerable: true, get: function () { return encrypt_js_4.EncryptJWT; } }); +var thumbprint_js_1 = require("./jwk/thumbprint.js"); +Object.defineProperty(exports, "calculateJwkThumbprint", { enumerable: true, get: function () { return thumbprint_js_1.calculateJwkThumbprint; } }); +Object.defineProperty(exports, "calculateJwkThumbprintUri", { enumerable: true, get: function () { return thumbprint_js_1.calculateJwkThumbprintUri; } }); +var embedded_js_1 = require("./jwk/embedded.js"); +Object.defineProperty(exports, "EmbeddedJWK", { enumerable: true, get: function () { return embedded_js_1.EmbeddedJWK; } }); +var local_js_1 = require("./jwks/local.js"); +Object.defineProperty(exports, "createLocalJWKSet", { enumerable: true, get: function () { return local_js_1.createLocalJWKSet; } }); +var remote_js_1 = require("./jwks/remote.js"); +Object.defineProperty(exports, "createRemoteJWKSet", { enumerable: true, get: function () { return remote_js_1.createRemoteJWKSet; } }); +var unsecured_js_1 = require("./jwt/unsecured.js"); +Object.defineProperty(exports, "UnsecuredJWT", { enumerable: true, get: function () { return unsecured_js_1.UnsecuredJWT; } }); +var export_js_1 = require("./key/export.js"); +Object.defineProperty(exports, "exportPKCS8", { enumerable: true, get: function () { return export_js_1.exportPKCS8; } }); +Object.defineProperty(exports, "exportSPKI", { enumerable: true, get: function () { return export_js_1.exportSPKI; } }); +Object.defineProperty(exports, "exportJWK", { enumerable: true, get: function () { return export_js_1.exportJWK; } }); +var import_js_1 = require("./key/import.js"); +Object.defineProperty(exports, "importSPKI", { enumerable: true, get: function () { return import_js_1.importSPKI; } }); +Object.defineProperty(exports, "importPKCS8", { enumerable: true, get: function () { return import_js_1.importPKCS8; } }); +Object.defineProperty(exports, "importX509", { enumerable: true, get: function () { return import_js_1.importX509; } }); +Object.defineProperty(exports, "importJWK", { enumerable: true, get: function () { return import_js_1.importJWK; } }); +var decode_protected_header_js_1 = require("./util/decode_protected_header.js"); +Object.defineProperty(exports, "decodeProtectedHeader", { enumerable: true, get: function () { return decode_protected_header_js_1.decodeProtectedHeader; } }); +var decode_jwt_js_1 = require("./util/decode_jwt.js"); +Object.defineProperty(exports, "decodeJwt", { enumerable: true, get: function () { return decode_jwt_js_1.decodeJwt; } }); +exports.errors = require("./util/errors.js"); +var generate_key_pair_js_1 = require("./key/generate_key_pair.js"); +Object.defineProperty(exports, "generateKeyPair", { enumerable: true, get: function () { return generate_key_pair_js_1.generateKeyPair; } }); +var generate_secret_js_1 = require("./key/generate_secret.js"); +Object.defineProperty(exports, "generateSecret", { enumerable: true, get: function () { return generate_secret_js_1.generateSecret; } }); +exports.base64url = require("./util/base64url.js"); diff --git a/dist/node/cjs/jwe/compact/decrypt.js b/dist/node/cjs/jwe/compact/decrypt.js new file mode 100644 index 0000000000..055b3c4564 --- /dev/null +++ b/dist/node/cjs/jwe/compact/decrypt.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.compactDecrypt = void 0; +const decrypt_js_1 = require("../flattened/decrypt.js"); +const errors_js_1 = require("../../util/errors.js"); +const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); +async function compactDecrypt(jwe, key, options) { + if (jwe instanceof Uint8Array) { + jwe = buffer_utils_js_1.decoder.decode(jwe); + } + if (typeof jwe !== 'string') { + throw new errors_js_1.JWEInvalid('Compact JWE must be a string or Uint8Array'); + } + const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.'); + if (length !== 5) { + throw new errors_js_1.JWEInvalid('Invalid Compact JWE'); + } + const decrypted = await (0, decrypt_js_1.flattenedDecrypt)({ + ciphertext, + iv: (iv || undefined), + protected: protectedHeader || undefined, + tag: (tag || undefined), + encrypted_key: encryptedKey || undefined, + }, key, options); + const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: decrypted.key }; + } + return result; +} +exports.compactDecrypt = compactDecrypt; diff --git a/dist/node/cjs/jwe/compact/encrypt.js b/dist/node/cjs/jwe/compact/encrypt.js new file mode 100644 index 0000000000..949fbb6df7 --- /dev/null +++ b/dist/node/cjs/jwe/compact/encrypt.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CompactEncrypt = void 0; +const encrypt_js_1 = require("../flattened/encrypt.js"); +class CompactEncrypt { + constructor(plaintext) { + this._flattened = new encrypt_js_1.FlattenedEncrypt(plaintext); + } + setContentEncryptionKey(cek) { + this._flattened.setContentEncryptionKey(cek); + return this; + } + setInitializationVector(iv) { + this._flattened.setInitializationVector(iv); + return this; + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + setKeyManagementParameters(parameters) { + this._flattened.setKeyManagementParameters(parameters); + return this; + } + async encrypt(key, options) { + const jwe = await this._flattened.encrypt(key, options); + return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.'); + } +} +exports.CompactEncrypt = CompactEncrypt; diff --git a/dist/node/cjs/jwe/flattened/decrypt.js b/dist/node/cjs/jwe/flattened/decrypt.js new file mode 100644 index 0000000000..fc0ef8d3c6 --- /dev/null +++ b/dist/node/cjs/jwe/flattened/decrypt.js @@ -0,0 +1,141 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flattenedDecrypt = void 0; +const base64url_js_1 = require("../../runtime/base64url.js"); +const decrypt_js_1 = require("../../runtime/decrypt.js"); +const zlib_js_1 = require("../../runtime/zlib.js"); +const errors_js_1 = require("../../util/errors.js"); +const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); +const is_object_js_1 = require("../../lib/is_object.js"); +const decrypt_key_management_js_1 = require("../../lib/decrypt_key_management.js"); +const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); +const cek_js_1 = require("../../lib/cek.js"); +const validate_crit_js_1 = require("../../lib/validate_crit.js"); +const validate_algorithms_js_1 = require("../../lib/validate_algorithms.js"); +async function flattenedDecrypt(jwe, key, options) { + var _a; + if (!(0, is_object_js_1.default)(jwe)) { + throw new errors_js_1.JWEInvalid('Flattened JWE must be an object'); + } + if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { + throw new errors_js_1.JWEInvalid('JOSE Header missing'); + } + if (typeof jwe.iv !== 'string') { + throw new errors_js_1.JWEInvalid('JWE Initialization Vector missing or incorrect type'); + } + if (typeof jwe.ciphertext !== 'string') { + throw new errors_js_1.JWEInvalid('JWE Ciphertext missing or incorrect type'); + } + if (typeof jwe.tag !== 'string') { + throw new errors_js_1.JWEInvalid('JWE Authentication Tag missing or incorrect type'); + } + if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { + throw new errors_js_1.JWEInvalid('JWE Protected Header incorrect type'); + } + if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { + throw new errors_js_1.JWEInvalid('JWE Encrypted Key incorrect type'); + } + if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { + throw new errors_js_1.JWEInvalid('JWE AAD incorrect type'); + } + if (jwe.header !== undefined && !(0, is_object_js_1.default)(jwe.header)) { + throw new errors_js_1.JWEInvalid('JWE Shared Unprotected Header incorrect type'); + } + if (jwe.unprotected !== undefined && !(0, is_object_js_1.default)(jwe.unprotected)) { + throw new errors_js_1.JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type'); + } + let parsedProt; + if (jwe.protected) { + try { + const protectedHeader = (0, base64url_js_1.decode)(jwe.protected); + parsedProt = JSON.parse(buffer_utils_js_1.decoder.decode(protectedHeader)); + } + catch { + throw new errors_js_1.JWEInvalid('JWE Protected Header is invalid'); + } + } + if (!(0, is_disjoint_js_1.default)(parsedProt, jwe.header, jwe.unprotected)) { + throw new errors_js_1.JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...parsedProt, + ...jwe.header, + ...jwe.unprotected, + }; + (0, validate_crit_js_1.default)(errors_js_1.JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + if (joseHeader.zip !== undefined) { + if (!parsedProt || !parsedProt.zip) { + throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== 'DEF') { + throw new errors_js_1.JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new errors_js_1.JWEInvalid('missing JWE Algorithm (alg) in JWE Header'); + } + if (typeof enc !== 'string' || !enc) { + throw new errors_js_1.JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header'); + } + const keyManagementAlgorithms = options && (0, validate_algorithms_js_1.default)('keyManagementAlgorithms', options.keyManagementAlgorithms); + const contentEncryptionAlgorithms = options && + (0, validate_algorithms_js_1.default)('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms); + if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { + throw new errors_js_1.JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { + throw new errors_js_1.JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); + } + let encryptedKey; + if (jwe.encrypted_key !== undefined) { + encryptedKey = (0, base64url_js_1.decode)(jwe.encrypted_key); + } + let resolvedKey = false; + if (typeof key === 'function') { + key = await key(parsedProt, jwe); + resolvedKey = true; + } + let cek; + try { + cek = await (0, decrypt_key_management_js_1.default)(alg, key, encryptedKey, joseHeader, options); + } + catch (err) { + if (err instanceof TypeError || err instanceof errors_js_1.JWEInvalid || err instanceof errors_js_1.JOSENotSupported) { + throw err; + } + cek = (0, cek_js_1.default)(enc); + } + const iv = (0, base64url_js_1.decode)(jwe.iv); + const tag = (0, base64url_js_1.decode)(jwe.tag); + const protectedHeader = buffer_utils_js_1.encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ''); + let additionalData; + if (jwe.aad !== undefined) { + additionalData = (0, buffer_utils_js_1.concat)(protectedHeader, buffer_utils_js_1.encoder.encode('.'), buffer_utils_js_1.encoder.encode(jwe.aad)); + } + else { + additionalData = protectedHeader; + } + let plaintext = await (0, decrypt_js_1.default)(enc, cek, (0, base64url_js_1.decode)(jwe.ciphertext), iv, tag, additionalData); + if (joseHeader.zip === 'DEF') { + plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || zlib_js_1.inflate)(plaintext); + } + const result = { plaintext }; + if (jwe.protected !== undefined) { + result.protectedHeader = parsedProt; + } + if (jwe.aad !== undefined) { + result.additionalAuthenticatedData = (0, base64url_js_1.decode)(jwe.aad); + } + if (jwe.unprotected !== undefined) { + result.sharedUnprotectedHeader = jwe.unprotected; + } + if (jwe.header !== undefined) { + result.unprotectedHeader = jwe.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} +exports.flattenedDecrypt = flattenedDecrypt; diff --git a/dist/node/cjs/jwe/flattened/encrypt.js b/dist/node/cjs/jwe/flattened/encrypt.js new file mode 100644 index 0000000000..8a69ccf40a --- /dev/null +++ b/dist/node/cjs/jwe/flattened/encrypt.js @@ -0,0 +1,179 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FlattenedEncrypt = exports.unprotected = void 0; +const base64url_js_1 = require("../../runtime/base64url.js"); +const encrypt_js_1 = require("../../runtime/encrypt.js"); +const zlib_js_1 = require("../../runtime/zlib.js"); +const iv_js_1 = require("../../lib/iv.js"); +const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js"); +const errors_js_1 = require("../../util/errors.js"); +const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); +const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); +const validate_crit_js_1 = require("../../lib/validate_crit.js"); +exports.unprotected = Symbol(); +class FlattenedEncrypt { + constructor(plaintext) { + if (!(plaintext instanceof Uint8Array)) { + throw new TypeError('plaintext must be an instance of Uint8Array'); + } + this._plaintext = plaintext; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once'); + } + this._keyManagementParameters = parameters; + return this; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._sharedUnprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once'); + } + this._sharedUnprotectedHeader = sharedUnprotectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once'); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once'); + } + this._iv = iv; + return this; + } + async encrypt(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { + throw new errors_js_1.JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()'); + } + if (!(0, is_disjoint_js_1.default)(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { + throw new errors_js_1.JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...this._sharedUnprotectedHeader, + }; + (0, validate_crit_js_1.default)(errors_js_1.JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== 'DEF') { + throw new errors_js_1.JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new errors_js_1.JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (typeof enc !== 'string' || !enc) { + throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + let encryptedKey; + if (alg === 'dir') { + if (this._cek) { + throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption'); + } + } + else if (alg === 'ECDH-ES') { + if (this._cek) { + throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement'); + } + } + let cek; + { + let parameters; + ({ cek, encryptedKey, parameters } = await (0, encrypt_key_management_js_1.default)(alg, enc, key, this._cek, this._keyManagementParameters)); + if (parameters) { + if (options && exports.unprotected in options) { + if (!this._unprotectedHeader) { + this.setUnprotectedHeader(parameters); + } + else { + this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; + } + } + else { + if (!this._protectedHeader) { + this.setProtectedHeader(parameters); + } + else { + this._protectedHeader = { ...this._protectedHeader, ...parameters }; + } + } + } + } + this._iv || (this._iv = (0, iv_js_1.default)(enc)); + let additionalData; + let protectedHeader; + let aadMember; + if (this._protectedHeader) { + protectedHeader = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(JSON.stringify(this._protectedHeader))); + } + else { + protectedHeader = buffer_utils_js_1.encoder.encode(''); + } + if (this._aad) { + aadMember = (0, base64url_js_1.encode)(this._aad); + additionalData = (0, buffer_utils_js_1.concat)(protectedHeader, buffer_utils_js_1.encoder.encode('.'), buffer_utils_js_1.encoder.encode(aadMember)); + } + else { + additionalData = protectedHeader; + } + let ciphertext; + let tag; + if (joseHeader.zip === 'DEF') { + const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || zlib_js_1.deflate)(this._plaintext); + ({ ciphertext, tag } = await (0, encrypt_js_1.default)(enc, deflated, cek, this._iv, additionalData)); + } + else { + ; + ({ ciphertext, tag } = await (0, encrypt_js_1.default)(enc, this._plaintext, cek, this._iv, additionalData)); + } + const jwe = { + ciphertext: (0, base64url_js_1.encode)(ciphertext), + iv: (0, base64url_js_1.encode)(this._iv), + tag: (0, base64url_js_1.encode)(tag), + }; + if (encryptedKey) { + jwe.encrypted_key = (0, base64url_js_1.encode)(encryptedKey); + } + if (aadMember) { + jwe.aad = aadMember; + } + if (this._protectedHeader) { + jwe.protected = buffer_utils_js_1.decoder.decode(protectedHeader); + } + if (this._sharedUnprotectedHeader) { + jwe.unprotected = this._sharedUnprotectedHeader; + } + if (this._unprotectedHeader) { + jwe.header = this._unprotectedHeader; + } + return jwe; + } +} +exports.FlattenedEncrypt = FlattenedEncrypt; diff --git a/dist/node/cjs/jwe/general/decrypt.js b/dist/node/cjs/jwe/general/decrypt.js new file mode 100644 index 0000000000..accb23aa6a --- /dev/null +++ b/dist/node/cjs/jwe/general/decrypt.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generalDecrypt = void 0; +const decrypt_js_1 = require("../flattened/decrypt.js"); +const errors_js_1 = require("../../util/errors.js"); +const is_object_js_1 = require("../../lib/is_object.js"); +async function generalDecrypt(jwe, key, options) { + if (!(0, is_object_js_1.default)(jwe)) { + throw new errors_js_1.JWEInvalid('General JWE must be an object'); + } + if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(is_object_js_1.default)) { + throw new errors_js_1.JWEInvalid('JWE Recipients missing or incorrect type'); + } + if (!jwe.recipients.length) { + throw new errors_js_1.JWEInvalid('JWE Recipients has no members'); + } + for (const recipient of jwe.recipients) { + try { + return await (0, decrypt_js_1.flattenedDecrypt)({ + aad: jwe.aad, + ciphertext: jwe.ciphertext, + encrypted_key: recipient.encrypted_key, + header: recipient.header, + iv: jwe.iv, + protected: jwe.protected, + tag: jwe.tag, + unprotected: jwe.unprotected, + }, key, options); + } + catch { + } + } + throw new errors_js_1.JWEDecryptionFailed(); +} +exports.generalDecrypt = generalDecrypt; diff --git a/dist/node/cjs/jwe/general/encrypt.js b/dist/node/cjs/jwe/general/encrypt.js new file mode 100644 index 0000000000..3caa084eda --- /dev/null +++ b/dist/node/cjs/jwe/general/encrypt.js @@ -0,0 +1,182 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GeneralEncrypt = void 0; +const encrypt_js_1 = require("../flattened/encrypt.js"); +const errors_js_1 = require("../../util/errors.js"); +const cek_js_1 = require("../../lib/cek.js"); +const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); +const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js"); +const base64url_js_1 = require("../../runtime/base64url.js"); +const validate_crit_js_1 = require("../../lib/validate_crit.js"); +class IndividualRecipient { + constructor(enc, key, options) { + this.parent = enc; + this.key = key; + this.options = options; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addRecipient(...args) { + return this.parent.addRecipient(...args); + } + encrypt(...args) { + return this.parent.encrypt(...args); + } + done() { + return this.parent; + } +} +class GeneralEncrypt { + constructor(plaintext) { + this._recipients = []; + this._plaintext = plaintext; + } + addRecipient(key, options) { + const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); + this._recipients.push(recipient); + return recipient; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = sharedUnprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + async encrypt(options) { + var _a, _b, _c; + if (!this._recipients.length) { + throw new errors_js_1.JWEInvalid('at least one recipient must be added'); + } + options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; + if (this._recipients.length === 1) { + const [recipient] = this._recipients; + const flattened = await new encrypt_js_1.FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader) + .encrypt(recipient.key, { ...recipient.options, ...options }); + let jwe = { + ciphertext: flattened.ciphertext, + iv: flattened.iv, + recipients: [{}], + tag: flattened.tag, + }; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + if (flattened.encrypted_key) + jwe.recipients[0].encrypted_key = flattened.encrypted_key; + if (flattened.header) + jwe.recipients[0].header = flattened.header; + return jwe; + } + let enc; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + if (!(0, is_disjoint_js_1.default)(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { + throw new errors_js_1.JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + }; + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new errors_js_1.JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (alg === 'dir' || alg === 'ECDH-ES') { + throw new errors_js_1.JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); + } + if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { + throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + if (!enc) { + enc = joseHeader.enc; + } + else if (enc !== joseHeader.enc) { + throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); + } + (0, validate_crit_js_1.default)(errors_js_1.JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + } + } + const cek = (0, cek_js_1.default)(enc); + let jwe = { + ciphertext: '', + iv: '', + recipients: [], + tag: '', + }; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + const target = {}; + jwe.recipients.push(target); + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + }; + const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined; + if (i === 0) { + const flattened = await new encrypt_js_1.FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setContentEncryptionKey(cek) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader) + .setKeyManagementParameters({ p2c }) + .encrypt(recipient.key, { + ...recipient.options, + ...options, + [encrypt_js_1.unprotected]: true, + }); + jwe.ciphertext = flattened.ciphertext; + jwe.iv = flattened.iv; + jwe.tag = flattened.tag; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + target.encrypted_key = flattened.encrypted_key; + if (flattened.header) + target.header = flattened.header; + continue; + } + const { encryptedKey, parameters } = await (0, encrypt_key_management_js_1.default)(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || + ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || + ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); + target.encrypted_key = (0, base64url_js_1.encode)(encryptedKey); + if (recipient.unprotectedHeader || parameters) + target.header = { ...recipient.unprotectedHeader, ...parameters }; + } + return jwe; + } +} +exports.GeneralEncrypt = GeneralEncrypt; diff --git a/dist/node/cjs/jwk/embedded.js b/dist/node/cjs/jwk/embedded.js new file mode 100644 index 0000000000..3fe1268e68 --- /dev/null +++ b/dist/node/cjs/jwk/embedded.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EmbeddedJWK = void 0; +const import_js_1 = require("../key/import.js"); +const is_object_js_1 = require("../lib/is_object.js"); +const errors_js_1 = require("../util/errors.js"); +async function EmbeddedJWK(protectedHeader, token) { + const joseHeader = { + ...protectedHeader, + ...token.header, + }; + if (!(0, is_object_js_1.default)(joseHeader.jwk)) { + throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); + } + const key = await (0, import_js_1.importJWK)({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); + if (key instanceof Uint8Array || key.type !== 'public') { + throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); + } + return key; +} +exports.EmbeddedJWK = EmbeddedJWK; diff --git a/dist/node/cjs/jwk/thumbprint.js b/dist/node/cjs/jwk/thumbprint.js new file mode 100644 index 0000000000..d50e2ba357 --- /dev/null +++ b/dist/node/cjs/jwk/thumbprint.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.calculateJwkThumbprintUri = exports.calculateJwkThumbprint = void 0; +const digest_js_1 = require("../runtime/digest.js"); +const base64url_js_1 = require("../runtime/base64url.js"); +const errors_js_1 = require("../util/errors.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const is_object_js_1 = require("../lib/is_object.js"); +const check = (value, description) => { + if (typeof value !== 'string' || !value) { + throw new errors_js_1.JWKInvalid(`${description} missing or invalid`); + } +}; +async function calculateJwkThumbprint(jwk, digestAlgorithm) { + if (!(0, is_object_js_1.default)(jwk)) { + throw new TypeError('JWK must be an object'); + } + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); + if (digestAlgorithm !== 'sha256' && + digestAlgorithm !== 'sha384' && + digestAlgorithm !== 'sha512') { + throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); + } + let components; + switch (jwk.kty) { + case 'EC': + check(jwk.crv, '"crv" (Curve) Parameter'); + check(jwk.x, '"x" (X Coordinate) Parameter'); + check(jwk.y, '"y" (Y Coordinate) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; + break; + case 'OKP': + check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); + check(jwk.x, '"x" (Public Key) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; + break; + case 'RSA': + check(jwk.e, '"e" (Exponent) Parameter'); + check(jwk.n, '"n" (Modulus) Parameter'); + components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; + break; + case 'oct': + check(jwk.k, '"k" (Key Value) Parameter'); + components = { k: jwk.k, kty: jwk.kty }; + break; + default: + throw new errors_js_1.JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); + } + const data = buffer_utils_js_1.encoder.encode(JSON.stringify(components)); + return (0, base64url_js_1.encode)(await (0, digest_js_1.default)(digestAlgorithm, data)); +} +exports.calculateJwkThumbprint = calculateJwkThumbprint; +async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); + const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); + return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; +} +exports.calculateJwkThumbprintUri = calculateJwkThumbprintUri; diff --git a/dist/node/cjs/jwks/local.js b/dist/node/cjs/jwks/local.js new file mode 100644 index 0000000000..e95a60724d --- /dev/null +++ b/dist/node/cjs/jwks/local.js @@ -0,0 +1,119 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createLocalJWKSet = exports.LocalJWKSet = exports.isJWKSLike = void 0; +const import_js_1 = require("../key/import.js"); +const errors_js_1 = require("../util/errors.js"); +const is_object_js_1 = require("../lib/is_object.js"); +function getKtyFromAlg(alg) { + switch (typeof alg === 'string' && alg.slice(0, 2)) { + case 'RS': + case 'PS': + return 'RSA'; + case 'ES': + return 'EC'; + case 'Ed': + return 'OKP'; + default: + throw new errors_js_1.JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); + } +} +function isJWKSLike(jwks) { + return (jwks && + typeof jwks === 'object' && + Array.isArray(jwks.keys) && + jwks.keys.every(isJWKLike)); +} +exports.isJWKSLike = isJWKSLike; +function isJWKLike(key) { + return (0, is_object_js_1.default)(key); +} +function clone(obj) { + if (typeof structuredClone === 'function') { + return structuredClone(obj); + } + return JSON.parse(JSON.stringify(obj)); +} +class LocalJWKSet { + constructor(jwks) { + this._cached = new WeakMap(); + if (!isJWKSLike(jwks)) { + throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed'); + } + this._jwks = clone(jwks); + } + async getKey(protectedHeader, token) { + const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; + const kty = getKtyFromAlg(alg); + const candidates = this._jwks.keys.filter((jwk) => { + let candidate = kty === jwk.kty; + if (candidate && typeof kid === 'string') { + candidate = kid === jwk.kid; + } + if (candidate && typeof jwk.alg === 'string') { + candidate = alg === jwk.alg; + } + if (candidate && typeof jwk.use === 'string') { + candidate = jwk.use === 'sig'; + } + if (candidate && Array.isArray(jwk.key_ops)) { + candidate = jwk.key_ops.includes('verify'); + } + if (candidate && alg === 'EdDSA') { + candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'; + } + if (candidate) { + switch (alg) { + case 'ES256': + candidate = jwk.crv === 'P-256'; + break; + case 'ES256K': + candidate = jwk.crv === 'secp256k1'; + break; + case 'ES384': + candidate = jwk.crv === 'P-384'; + break; + case 'ES512': + candidate = jwk.crv === 'P-521'; + break; + } + } + return candidate; + }); + const { 0: jwk, length } = candidates; + if (length === 0) { + throw new errors_js_1.JWKSNoMatchingKey(); + } + else if (length !== 1) { + const error = new errors_js_1.JWKSMultipleMatchingKeys(); + const { _cached } = this; + error[Symbol.asyncIterator] = async function* () { + for (const jwk of candidates) { + try { + yield await importWithAlgCache(_cached, jwk, alg); + } + catch { + continue; + } + } + }; + throw error; + } + return importWithAlgCache(this._cached, jwk, alg); + } +} +exports.LocalJWKSet = LocalJWKSet; +async function importWithAlgCache(cache, jwk, alg) { + const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); + if (cached[alg] === undefined) { + const keyObject = await (0, import_js_1.importJWK)({ ...jwk, ext: true }, alg); + if (keyObject.type !== 'public') { + throw new errors_js_1.JWKSInvalid('JSON Web Key Set members must be public keys'); + } + cached[alg] = keyObject; + } + return cached[alg]; +} +function createLocalJWKSet(jwks) { + return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); +} +exports.createLocalJWKSet = createLocalJWKSet; diff --git a/dist/node/cjs/jwks/remote.js b/dist/node/cjs/jwks/remote.js new file mode 100644 index 0000000000..79794cdee1 --- /dev/null +++ b/dist/node/cjs/jwks/remote.js @@ -0,0 +1,85 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createRemoteJWKSet = void 0; +const fetch_jwks_js_1 = require("../runtime/fetch_jwks.js"); +const env_js_1 = require("../runtime/env.js"); +const errors_js_1 = require("../util/errors.js"); +const local_js_1 = require("./local.js"); +class RemoteJWKSet extends local_js_1.LocalJWKSet { + constructor(url, options) { + super({ keys: [] }); + this._jwks = undefined; + if (!(url instanceof URL)) { + throw new TypeError('url must be an instance of URL'); + } + this._url = new URL(url.href); + this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; + this._timeoutDuration = + typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000; + this._cooldownDuration = + typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000; + this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000; + } + coolingDown() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cooldownDuration + : false; + } + fresh() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cacheMaxAge + : false; + } + async getKey(protectedHeader, token) { + if (!this._jwks || !this.fresh()) { + await this.reload(); + } + try { + return await super.getKey(protectedHeader, token); + } + catch (err) { + if (err instanceof errors_js_1.JWKSNoMatchingKey) { + if (this.coolingDown() === false) { + await this.reload(); + return super.getKey(protectedHeader, token); + } + } + throw err; + } + } + async reload() { + if (this._pendingFetch && (0, env_js_1.isCloudflareWorkers)()) { + return new Promise((resolve) => { + const isDone = () => { + if (this._pendingFetch === undefined) { + resolve(); + } + else { + setTimeout(isDone, 5); + } + }; + isDone(); + }); + } + if (!this._pendingFetch) { + this._pendingFetch = (0, fetch_jwks_js_1.default)(this._url, this._timeoutDuration, this._options) + .then((json) => { + if (!(0, local_js_1.isJWKSLike)(json)) { + throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed'); + } + this._jwks = { keys: json.keys }; + this._jwksTimestamp = Date.now(); + this._pendingFetch = undefined; + }) + .catch((err) => { + this._pendingFetch = undefined; + throw err; + }); + } + await this._pendingFetch; + } +} +function createRemoteJWKSet(url, options) { + return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); +} +exports.createRemoteJWKSet = createRemoteJWKSet; diff --git a/dist/node/cjs/jws/compact/sign.js b/dist/node/cjs/jws/compact/sign.js new file mode 100644 index 0000000000..e960ade473 --- /dev/null +++ b/dist/node/cjs/jws/compact/sign.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CompactSign = void 0; +const sign_js_1 = require("../flattened/sign.js"); +class CompactSign { + constructor(payload) { + this._flattened = new sign_js_1.FlattenedSign(payload); + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + async sign(key, options) { + const jws = await this._flattened.sign(key, options); + if (jws.payload === undefined) { + throw new TypeError('use the flattened module for creating JWS with b64: false'); + } + return `${jws.protected}.${jws.payload}.${jws.signature}`; + } +} +exports.CompactSign = CompactSign; diff --git a/dist/node/cjs/jws/compact/verify.js b/dist/node/cjs/jws/compact/verify.js new file mode 100644 index 0000000000..b7e672477f --- /dev/null +++ b/dist/node/cjs/jws/compact/verify.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.compactVerify = void 0; +const verify_js_1 = require("../flattened/verify.js"); +const errors_js_1 = require("../../util/errors.js"); +const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); +async function compactVerify(jws, key, options) { + if (jws instanceof Uint8Array) { + jws = buffer_utils_js_1.decoder.decode(jws); + } + if (typeof jws !== 'string') { + throw new errors_js_1.JWSInvalid('Compact JWS must be a string or Uint8Array'); + } + const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.'); + if (length !== 3) { + throw new errors_js_1.JWSInvalid('Invalid Compact JWS'); + } + const verified = await (0, verify_js_1.flattenedVerify)({ payload, protected: protectedHeader, signature }, key, options); + const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: verified.key }; + } + return result; +} +exports.compactVerify = compactVerify; diff --git a/dist/node/cjs/jws/flattened/sign.js b/dist/node/cjs/jws/flattened/sign.js new file mode 100644 index 0000000000..2281e97cf3 --- /dev/null +++ b/dist/node/cjs/jws/flattened/sign.js @@ -0,0 +1,85 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FlattenedSign = void 0; +const base64url_js_1 = require("../../runtime/base64url.js"); +const sign_js_1 = require("../../runtime/sign.js"); +const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); +const errors_js_1 = require("../../util/errors.js"); +const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); +const check_key_type_js_1 = require("../../lib/check_key_type.js"); +const validate_crit_js_1 = require("../../lib/validate_crit.js"); +class FlattenedSign { + constructor(payload) { + if (!(payload instanceof Uint8Array)) { + throw new TypeError('payload must be an instance of Uint8Array'); + } + this._payload = payload; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + async sign(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader) { + throw new errors_js_1.JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); + } + if (!(0, is_disjoint_js_1.default)(this._protectedHeader, this._unprotectedHeader)) { + throw new errors_js_1.JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + }; + const extensions = (0, validate_crit_js_1.default)(errors_js_1.JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + let b64 = true; + if (extensions.has('b64')) { + b64 = this._protectedHeader.b64; + if (typeof b64 !== 'boolean') { + throw new errors_js_1.JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new errors_js_1.JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + (0, check_key_type_js_1.default)(alg, key, 'sign'); + let payload = this._payload; + if (b64) { + payload = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(payload)); + } + let protectedHeader; + if (this._protectedHeader) { + protectedHeader = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(JSON.stringify(this._protectedHeader))); + } + else { + protectedHeader = buffer_utils_js_1.encoder.encode(''); + } + const data = (0, buffer_utils_js_1.concat)(protectedHeader, buffer_utils_js_1.encoder.encode('.'), payload); + const signature = await (0, sign_js_1.default)(alg, key, data); + const jws = { + signature: (0, base64url_js_1.encode)(signature), + payload: '', + }; + if (b64) { + jws.payload = buffer_utils_js_1.decoder.decode(payload); + } + if (this._unprotectedHeader) { + jws.header = this._unprotectedHeader; + } + if (this._protectedHeader) { + jws.protected = buffer_utils_js_1.decoder.decode(protectedHeader); + } + return jws; + } +} +exports.FlattenedSign = FlattenedSign; diff --git a/dist/node/cjs/jws/flattened/verify.js b/dist/node/cjs/jws/flattened/verify.js new file mode 100644 index 0000000000..5f0c3930e1 --- /dev/null +++ b/dist/node/cjs/jws/flattened/verify.js @@ -0,0 +1,108 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flattenedVerify = void 0; +const base64url_js_1 = require("../../runtime/base64url.js"); +const verify_js_1 = require("../../runtime/verify.js"); +const errors_js_1 = require("../../util/errors.js"); +const buffer_utils_js_1 = require("../../lib/buffer_utils.js"); +const is_disjoint_js_1 = require("../../lib/is_disjoint.js"); +const is_object_js_1 = require("../../lib/is_object.js"); +const check_key_type_js_1 = require("../../lib/check_key_type.js"); +const validate_crit_js_1 = require("../../lib/validate_crit.js"); +const validate_algorithms_js_1 = require("../../lib/validate_algorithms.js"); +async function flattenedVerify(jws, key, options) { + var _a; + if (!(0, is_object_js_1.default)(jws)) { + throw new errors_js_1.JWSInvalid('Flattened JWS must be an object'); + } + if (jws.protected === undefined && jws.header === undefined) { + throw new errors_js_1.JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); + } + if (jws.protected !== undefined && typeof jws.protected !== 'string') { + throw new errors_js_1.JWSInvalid('JWS Protected Header incorrect type'); + } + if (jws.payload === undefined) { + throw new errors_js_1.JWSInvalid('JWS Payload missing'); + } + if (typeof jws.signature !== 'string') { + throw new errors_js_1.JWSInvalid('JWS Signature missing or incorrect type'); + } + if (jws.header !== undefined && !(0, is_object_js_1.default)(jws.header)) { + throw new errors_js_1.JWSInvalid('JWS Unprotected Header incorrect type'); + } + let parsedProt = {}; + if (jws.protected) { + try { + const protectedHeader = (0, base64url_js_1.decode)(jws.protected); + parsedProt = JSON.parse(buffer_utils_js_1.decoder.decode(protectedHeader)); + } + catch { + throw new errors_js_1.JWSInvalid('JWS Protected Header is invalid'); + } + } + if (!(0, is_disjoint_js_1.default)(parsedProt, jws.header)) { + throw new errors_js_1.JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...parsedProt, + ...jws.header, + }; + const extensions = (0, validate_crit_js_1.default)(errors_js_1.JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + let b64 = true; + if (extensions.has('b64')) { + b64 = parsedProt.b64; + if (typeof b64 !== 'boolean') { + throw new errors_js_1.JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new errors_js_1.JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + const algorithms = options && (0, validate_algorithms_js_1.default)('algorithms', options.algorithms); + if (algorithms && !algorithms.has(alg)) { + throw new errors_js_1.JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (b64) { + if (typeof jws.payload !== 'string') { + throw new errors_js_1.JWSInvalid('JWS Payload must be a string'); + } + } + else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { + throw new errors_js_1.JWSInvalid('JWS Payload must be a string or an Uint8Array instance'); + } + let resolvedKey = false; + if (typeof key === 'function') { + key = await key(parsedProt, jws); + resolvedKey = true; + } + (0, check_key_type_js_1.default)(alg, key, 'verify'); + const data = (0, buffer_utils_js_1.concat)(buffer_utils_js_1.encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), buffer_utils_js_1.encoder.encode('.'), typeof jws.payload === 'string' ? buffer_utils_js_1.encoder.encode(jws.payload) : jws.payload); + const signature = (0, base64url_js_1.decode)(jws.signature); + const verified = await (0, verify_js_1.default)(alg, key, signature, data); + if (!verified) { + throw new errors_js_1.JWSSignatureVerificationFailed(); + } + let payload; + if (b64) { + payload = (0, base64url_js_1.decode)(jws.payload); + } + else if (typeof jws.payload === 'string') { + payload = buffer_utils_js_1.encoder.encode(jws.payload); + } + else { + payload = jws.payload; + } + const result = { payload }; + if (jws.protected !== undefined) { + result.protectedHeader = parsedProt; + } + if (jws.header !== undefined) { + result.unprotectedHeader = jws.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} +exports.flattenedVerify = flattenedVerify; diff --git a/dist/node/cjs/jws/general/sign.js b/dist/node/cjs/jws/general/sign.js new file mode 100644 index 0000000000..6a876d905b --- /dev/null +++ b/dist/node/cjs/jws/general/sign.js @@ -0,0 +1,71 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GeneralSign = void 0; +const sign_js_1 = require("../flattened/sign.js"); +const errors_js_1 = require("../../util/errors.js"); +class IndividualSignature { + constructor(sig, key, options) { + this.parent = sig; + this.key = key; + this.options = options; + } + setProtectedHeader(protectedHeader) { + if (this.protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this.protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addSignature(...args) { + return this.parent.addSignature(...args); + } + sign(...args) { + return this.parent.sign(...args); + } + done() { + return this.parent; + } +} +class GeneralSign { + constructor(payload) { + this._signatures = []; + this._payload = payload; + } + addSignature(key, options) { + const signature = new IndividualSignature(this, key, options); + this._signatures.push(signature); + return signature; + } + async sign() { + if (!this._signatures.length) { + throw new errors_js_1.JWSInvalid('at least one signature must be added'); + } + const jws = { + signatures: [], + payload: '', + }; + for (let i = 0; i < this._signatures.length; i++) { + const signature = this._signatures[i]; + const flattened = new sign_js_1.FlattenedSign(this._payload); + flattened.setProtectedHeader(signature.protectedHeader); + flattened.setUnprotectedHeader(signature.unprotectedHeader); + const { payload, ...rest } = await flattened.sign(signature.key, signature.options); + if (i === 0) { + jws.payload = payload; + } + else if (jws.payload !== payload) { + throw new errors_js_1.JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)'); + } + jws.signatures.push(rest); + } + return jws; + } +} +exports.GeneralSign = GeneralSign; diff --git a/dist/node/cjs/jws/general/verify.js b/dist/node/cjs/jws/general/verify.js new file mode 100644 index 0000000000..9d4a07a296 --- /dev/null +++ b/dist/node/cjs/jws/general/verify.js @@ -0,0 +1,28 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generalVerify = void 0; +const verify_js_1 = require("../flattened/verify.js"); +const errors_js_1 = require("../../util/errors.js"); +const is_object_js_1 = require("../../lib/is_object.js"); +async function generalVerify(jws, key, options) { + if (!(0, is_object_js_1.default)(jws)) { + throw new errors_js_1.JWSInvalid('General JWS must be an object'); + } + if (!Array.isArray(jws.signatures) || !jws.signatures.every(is_object_js_1.default)) { + throw new errors_js_1.JWSInvalid('JWS Signatures missing or incorrect type'); + } + for (const signature of jws.signatures) { + try { + return await (0, verify_js_1.flattenedVerify)({ + header: signature.header, + payload: jws.payload, + protected: signature.protected, + signature: signature.signature, + }, key, options); + } + catch { + } + } + throw new errors_js_1.JWSSignatureVerificationFailed(); +} +exports.generalVerify = generalVerify; diff --git a/dist/node/cjs/jwt/decrypt.js b/dist/node/cjs/jwt/decrypt.js new file mode 100644 index 0000000000..3539ceab53 --- /dev/null +++ b/dist/node/cjs/jwt/decrypt.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.jwtDecrypt = void 0; +const decrypt_js_1 = require("../jwe/compact/decrypt.js"); +const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); +const errors_js_1 = require("../util/errors.js"); +async function jwtDecrypt(jwt, key, options) { + const decrypted = await (0, decrypt_js_1.compactDecrypt)(jwt, key, options); + const payload = (0, jwt_claims_set_js_1.default)(decrypted.protectedHeader, decrypted.plaintext, options); + const { protectedHeader } = decrypted; + if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { + throw new errors_js_1.JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', 'iss', 'mismatch'); + } + if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { + throw new errors_js_1.JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', 'sub', 'mismatch'); + } + if (protectedHeader.aud !== undefined && + JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { + throw new errors_js_1.JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch'); + } + const result = { payload, protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: decrypted.key }; + } + return result; +} +exports.jwtDecrypt = jwtDecrypt; diff --git a/dist/node/cjs/jwt/encrypt.js b/dist/node/cjs/jwt/encrypt.js new file mode 100644 index 0000000000..8ce18f1e73 --- /dev/null +++ b/dist/node/cjs/jwt/encrypt.js @@ -0,0 +1,72 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EncryptJWT = void 0; +const encrypt_js_1 = require("../jwe/compact/encrypt.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const produce_js_1 = require("./produce.js"); +class EncryptJWT extends produce_js_1.ProduceJWT { + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once'); + } + this._keyManagementParameters = parameters; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once'); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once'); + } + this._iv = iv; + return this; + } + replicateIssuerAsHeader() { + this._replicateIssuerAsHeader = true; + return this; + } + replicateSubjectAsHeader() { + this._replicateSubjectAsHeader = true; + return this; + } + replicateAudienceAsHeader() { + this._replicateAudienceAsHeader = true; + return this; + } + async encrypt(key, options) { + const enc = new encrypt_js_1.CompactEncrypt(buffer_utils_js_1.encoder.encode(JSON.stringify(this._payload))); + if (this._replicateIssuerAsHeader) { + this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; + } + if (this._replicateSubjectAsHeader) { + this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; + } + if (this._replicateAudienceAsHeader) { + this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; + } + enc.setProtectedHeader(this._protectedHeader); + if (this._iv) { + enc.setInitializationVector(this._iv); + } + if (this._cek) { + enc.setContentEncryptionKey(this._cek); + } + if (this._keyManagementParameters) { + enc.setKeyManagementParameters(this._keyManagementParameters); + } + return enc.encrypt(key, options); + } +} +exports.EncryptJWT = EncryptJWT; diff --git a/dist/node/cjs/jwt/produce.js b/dist/node/cjs/jwt/produce.js new file mode 100644 index 0000000000..54d9ccb134 --- /dev/null +++ b/dist/node/cjs/jwt/produce.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ProduceJWT = void 0; +const epoch_js_1 = require("../lib/epoch.js"); +const is_object_js_1 = require("../lib/is_object.js"); +const secs_js_1 = require("../lib/secs.js"); +class ProduceJWT { + constructor(payload) { + if (!(0, is_object_js_1.default)(payload)) { + throw new TypeError('JWT Claims Set MUST be an object'); + } + this._payload = payload; + } + setIssuer(issuer) { + this._payload = { ...this._payload, iss: issuer }; + return this; + } + setSubject(subject) { + this._payload = { ...this._payload, sub: subject }; + return this; + } + setAudience(audience) { + this._payload = { ...this._payload, aud: audience }; + return this; + } + setJti(jwtId) { + this._payload = { ...this._payload, jti: jwtId }; + return this; + } + setNotBefore(input) { + if (typeof input === 'number') { + this._payload = { ...this._payload, nbf: input }; + } + else { + this._payload = { ...this._payload, nbf: (0, epoch_js_1.default)(new Date()) + (0, secs_js_1.default)(input) }; + } + return this; + } + setExpirationTime(input) { + if (typeof input === 'number') { + this._payload = { ...this._payload, exp: input }; + } + else { + this._payload = { ...this._payload, exp: (0, epoch_js_1.default)(new Date()) + (0, secs_js_1.default)(input) }; + } + return this; + } + setIssuedAt(input) { + if (typeof input === 'undefined') { + this._payload = { ...this._payload, iat: (0, epoch_js_1.default)(new Date()) }; + } + else { + this._payload = { ...this._payload, iat: input }; + } + return this; + } +} +exports.ProduceJWT = ProduceJWT; diff --git a/dist/node/cjs/jwt/sign.js b/dist/node/cjs/jwt/sign.js new file mode 100644 index 0000000000..ad9193c13a --- /dev/null +++ b/dist/node/cjs/jwt/sign.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SignJWT = void 0; +const sign_js_1 = require("../jws/compact/sign.js"); +const errors_js_1 = require("../util/errors.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const produce_js_1 = require("./produce.js"); +class SignJWT extends produce_js_1.ProduceJWT { + setProtectedHeader(protectedHeader) { + this._protectedHeader = protectedHeader; + return this; + } + async sign(key, options) { + var _a; + const sig = new sign_js_1.CompactSign(buffer_utils_js_1.encoder.encode(JSON.stringify(this._payload))); + sig.setProtectedHeader(this._protectedHeader); + if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && + this._protectedHeader.crit.includes('b64') && + this._protectedHeader.b64 === false) { + throw new errors_js_1.JWTInvalid('JWTs MUST NOT use unencoded payload'); + } + return sig.sign(key, options); + } +} +exports.SignJWT = SignJWT; diff --git a/dist/node/cjs/jwt/unsecured.js b/dist/node/cjs/jwt/unsecured.js new file mode 100644 index 0000000000..482782fed1 --- /dev/null +++ b/dist/node/cjs/jwt/unsecured.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UnsecuredJWT = void 0; +const base64url = require("../runtime/base64url.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const errors_js_1 = require("../util/errors.js"); +const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); +const produce_js_1 = require("./produce.js"); +class UnsecuredJWT extends produce_js_1.ProduceJWT { + encode() { + const header = base64url.encode(JSON.stringify({ alg: 'none' })); + const payload = base64url.encode(JSON.stringify(this._payload)); + return `${header}.${payload}.`; + } + static decode(jwt, options) { + if (typeof jwt !== 'string') { + throw new errors_js_1.JWTInvalid('Unsecured JWT must be a string'); + } + const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.'); + if (length !== 3 || signature !== '') { + throw new errors_js_1.JWTInvalid('Invalid Unsecured JWT'); + } + let header; + try { + header = JSON.parse(buffer_utils_js_1.decoder.decode(base64url.decode(encodedHeader))); + if (header.alg !== 'none') + throw new Error(); + } + catch { + throw new errors_js_1.JWTInvalid('Invalid Unsecured JWT'); + } + const payload = (0, jwt_claims_set_js_1.default)(header, base64url.decode(encodedPayload), options); + return { payload, header }; + } +} +exports.UnsecuredJWT = UnsecuredJWT; diff --git a/dist/node/cjs/jwt/verify.js b/dist/node/cjs/jwt/verify.js new file mode 100644 index 0000000000..d77bb96096 --- /dev/null +++ b/dist/node/cjs/jwt/verify.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.jwtVerify = void 0; +const verify_js_1 = require("../jws/compact/verify.js"); +const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); +const errors_js_1 = require("../util/errors.js"); +async function jwtVerify(jwt, key, options) { + var _a; + const verified = await (0, verify_js_1.compactVerify)(jwt, key, options); + if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { + throw new errors_js_1.JWTInvalid('JWTs MUST NOT use unencoded payload'); + } + const payload = (0, jwt_claims_set_js_1.default)(verified.protectedHeader, verified.payload, options); + const result = { payload, protectedHeader: verified.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: verified.key }; + } + return result; +} +exports.jwtVerify = jwtVerify; diff --git a/dist/node/cjs/key/export.js b/dist/node/cjs/key/export.js new file mode 100644 index 0000000000..1c083efe72 --- /dev/null +++ b/dist/node/cjs/key/export.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.exportJWK = exports.exportPKCS8 = exports.exportSPKI = void 0; +const asn1_js_1 = require("../runtime/asn1.js"); +const asn1_js_2 = require("../runtime/asn1.js"); +const key_to_jwk_js_1 = require("../runtime/key_to_jwk.js"); +async function exportSPKI(key) { + return (0, asn1_js_1.toSPKI)(key); +} +exports.exportSPKI = exportSPKI; +async function exportPKCS8(key) { + return (0, asn1_js_2.toPKCS8)(key); +} +exports.exportPKCS8 = exportPKCS8; +async function exportJWK(key) { + return (0, key_to_jwk_js_1.default)(key); +} +exports.exportJWK = exportJWK; diff --git a/dist/node/cjs/key/generate_key_pair.js b/dist/node/cjs/key/generate_key_pair.js new file mode 100644 index 0000000000..3d14da5c3e --- /dev/null +++ b/dist/node/cjs/key/generate_key_pair.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateKeyPair = void 0; +const generate_js_1 = require("../runtime/generate.js"); +async function generateKeyPair(alg, options) { + return (0, generate_js_1.generateKeyPair)(alg, options); +} +exports.generateKeyPair = generateKeyPair; diff --git a/dist/node/cjs/key/generate_secret.js b/dist/node/cjs/key/generate_secret.js new file mode 100644 index 0000000000..5f3c9ba214 --- /dev/null +++ b/dist/node/cjs/key/generate_secret.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateSecret = void 0; +const generate_js_1 = require("../runtime/generate.js"); +async function generateSecret(alg, options) { + return (0, generate_js_1.generateSecret)(alg, options); +} +exports.generateSecret = generateSecret; diff --git a/dist/node/cjs/key/import.js b/dist/node/cjs/key/import.js new file mode 100644 index 0000000000..e12b288006 --- /dev/null +++ b/dist/node/cjs/key/import.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.importJWK = exports.importPKCS8 = exports.importX509 = exports.importSPKI = void 0; +const base64url_js_1 = require("../runtime/base64url.js"); +const asn1_js_1 = require("../runtime/asn1.js"); +const jwk_to_key_js_1 = require("../runtime/jwk_to_key.js"); +const errors_js_1 = require("../util/errors.js"); +const is_object_js_1 = require("../lib/is_object.js"); +async function importSPKI(spki, alg, options) { + if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { + throw new TypeError('"spki" must be SPKI formatted string'); + } + return (0, asn1_js_1.fromSPKI)(spki, alg, options); +} +exports.importSPKI = importSPKI; +async function importX509(x509, alg, options) { + if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { + throw new TypeError('"x509" must be X.509 formatted string'); + } + return (0, asn1_js_1.fromX509)(x509, alg, options); +} +exports.importX509 = importX509; +async function importPKCS8(pkcs8, alg, options) { + if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { + throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); + } + return (0, asn1_js_1.fromPKCS8)(pkcs8, alg, options); +} +exports.importPKCS8 = importPKCS8; +async function importJWK(jwk, alg, octAsKeyObject) { + var _a; + if (!(0, is_object_js_1.default)(jwk)) { + throw new TypeError('JWK must be an object'); + } + alg || (alg = jwk.alg); + switch (jwk.kty) { + case 'oct': + if (typeof jwk.k !== 'string' || !jwk.k) { + throw new TypeError('missing "k" (Key Value) Parameter value'); + } + octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true); + if (octAsKeyObject) { + return (0, jwk_to_key_js_1.default)({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); + } + return (0, base64url_js_1.decode)(jwk.k); + case 'RSA': + if (jwk.oth !== undefined) { + throw new errors_js_1.JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); + } + case 'EC': + case 'OKP': + return (0, jwk_to_key_js_1.default)({ ...jwk, alg }); + default: + throw new errors_js_1.JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); + } +} +exports.importJWK = importJWK; diff --git a/dist/node/cjs/lib/aesgcmkw.js b/dist/node/cjs/lib/aesgcmkw.js new file mode 100644 index 0000000000..c3e61e8eab --- /dev/null +++ b/dist/node/cjs/lib/aesgcmkw.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.unwrap = exports.wrap = void 0; +const encrypt_js_1 = require("../runtime/encrypt.js"); +const decrypt_js_1 = require("../runtime/decrypt.js"); +const iv_js_1 = require("./iv.js"); +const base64url_js_1 = require("../runtime/base64url.js"); +async function wrap(alg, key, cek, iv) { + const jweAlgorithm = alg.slice(0, 7); + iv || (iv = (0, iv_js_1.default)(jweAlgorithm)); + const { ciphertext: encryptedKey, tag } = await (0, encrypt_js_1.default)(jweAlgorithm, cek, key, iv, new Uint8Array(0)); + return { encryptedKey, iv: (0, base64url_js_1.encode)(iv), tag: (0, base64url_js_1.encode)(tag) }; +} +exports.wrap = wrap; +async function unwrap(alg, key, encryptedKey, iv, tag) { + const jweAlgorithm = alg.slice(0, 7); + return (0, decrypt_js_1.default)(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); +} +exports.unwrap = unwrap; diff --git a/dist/node/cjs/lib/buffer_utils.js b/dist/node/cjs/lib/buffer_utils.js new file mode 100644 index 0000000000..7932178142 --- /dev/null +++ b/dist/node/cjs/lib/buffer_utils.js @@ -0,0 +1,60 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.concatKdf = exports.lengthAndInput = exports.uint32be = exports.uint64be = exports.p2s = exports.concat = exports.decoder = exports.encoder = void 0; +const digest_js_1 = require("../runtime/digest.js"); +exports.encoder = new TextEncoder(); +exports.decoder = new TextDecoder(); +const MAX_INT32 = 2 ** 32; +function concat(...buffers) { + const size = buffers.reduce((acc, { length }) => acc + length, 0); + const buf = new Uint8Array(size); + let i = 0; + buffers.forEach((buffer) => { + buf.set(buffer, i); + i += buffer.length; + }); + return buf; +} +exports.concat = concat; +function p2s(alg, p2sInput) { + return concat(exports.encoder.encode(alg), new Uint8Array([0]), p2sInput); +} +exports.p2s = p2s; +function writeUInt32BE(buf, value, offset) { + if (value < 0 || value >= MAX_INT32) { + throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); + } + buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset); +} +function uint64be(value) { + const high = Math.floor(value / MAX_INT32); + const low = value % MAX_INT32; + const buf = new Uint8Array(8); + writeUInt32BE(buf, high, 0); + writeUInt32BE(buf, low, 4); + return buf; +} +exports.uint64be = uint64be; +function uint32be(value) { + const buf = new Uint8Array(4); + writeUInt32BE(buf, value); + return buf; +} +exports.uint32be = uint32be; +function lengthAndInput(input) { + return concat(uint32be(input.length), input); +} +exports.lengthAndInput = lengthAndInput; +async function concatKdf(secret, bits, value) { + const iterations = Math.ceil((bits >> 3) / 32); + const res = new Uint8Array(iterations * 32); + for (let iter = 0; iter < iterations; iter++) { + const buf = new Uint8Array(4 + secret.length + value.length); + buf.set(uint32be(iter + 1)); + buf.set(secret, 4); + buf.set(value, 4 + secret.length); + res.set(await (0, digest_js_1.default)('sha256', buf), iter * 32); + } + return res.slice(0, bits >> 3); +} +exports.concatKdf = concatKdf; diff --git a/dist/node/cjs/lib/cek.js b/dist/node/cjs/lib/cek.js new file mode 100644 index 0000000000..e4a0133909 --- /dev/null +++ b/dist/node/cjs/lib/cek.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.bitLength = void 0; +const errors_js_1 = require("../util/errors.js"); +const random_js_1 = require("../runtime/random.js"); +function bitLength(alg) { + switch (alg) { + case 'A128GCM': + return 128; + case 'A192GCM': + return 192; + case 'A256GCM': + case 'A128CBC-HS256': + return 256; + case 'A192CBC-HS384': + return 384; + case 'A256CBC-HS512': + return 512; + default: + throw new errors_js_1.JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +exports.bitLength = bitLength; +exports.default = (alg) => (0, random_js_1.default)(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/cjs/lib/check_iv_length.js b/dist/node/cjs/lib/check_iv_length.js new file mode 100644 index 0000000000..3fbee85bb0 --- /dev/null +++ b/dist/node/cjs/lib/check_iv_length.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const errors_js_1 = require("../util/errors.js"); +const iv_js_1 = require("./iv.js"); +const checkIvLength = (enc, iv) => { + if (iv.length << 3 !== (0, iv_js_1.bitLength)(enc)) { + throw new errors_js_1.JWEInvalid('Invalid Initialization Vector length'); + } +}; +exports.default = checkIvLength; diff --git a/dist/node/cjs/lib/check_key_type.js b/dist/node/cjs/lib/check_key_type.js new file mode 100644 index 0000000000..5035f81f6b --- /dev/null +++ b/dist/node/cjs/lib/check_key_type.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const invalid_key_input_js_1 = require("./invalid_key_input.js"); +const is_key_like_js_1 = require("../runtime/is_key_like.js"); +const symmetricTypeCheck = (alg, key) => { + if (key instanceof Uint8Array) + return; + if (!(0, is_key_like_js_1.default)(key)) { + throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types, 'Uint8Array')); + } + if (key.type !== 'secret') { + throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for symmetric algorithms must be of type "secret"`); + } +}; +const asymmetricTypeCheck = (alg, key, usage) => { + if (!(0, is_key_like_js_1.default)(key)) { + throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types)); + } + if (key.type === 'secret') { + throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`); + } + if (usage === 'sign' && key.type === 'public') { + throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`); + } + if (usage === 'decrypt' && key.type === 'public') { + throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`); + } + if (key.algorithm && usage === 'verify' && key.type === 'private') { + throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`); + } + if (key.algorithm && usage === 'encrypt' && key.type === 'private') { + throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`); + } +}; +const checkKeyType = (alg, key, usage) => { + const symmetric = alg.startsWith('HS') || + alg === 'dir' || + alg.startsWith('PBES2') || + /^A\d{3}(?:GCM)?KW$/.test(alg); + if (symmetric) { + symmetricTypeCheck(alg, key); + } + else { + asymmetricTypeCheck(alg, key, usage); + } +}; +exports.default = checkKeyType; diff --git a/dist/node/cjs/lib/check_p2s.js b/dist/node/cjs/lib/check_p2s.js new file mode 100644 index 0000000000..4bdeaa766c --- /dev/null +++ b/dist/node/cjs/lib/check_p2s.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const errors_js_1 = require("../util/errors.js"); +function checkP2s(p2s) { + if (!(p2s instanceof Uint8Array) || p2s.length < 8) { + throw new errors_js_1.JWEInvalid('PBES2 Salt Input must be 8 or more octets'); + } +} +exports.default = checkP2s; diff --git a/dist/node/cjs/lib/crypto_key.js b/dist/node/cjs/lib/crypto_key.js new file mode 100644 index 0000000000..59de5e20e3 --- /dev/null +++ b/dist/node/cjs/lib/crypto_key.js @@ -0,0 +1,163 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.checkEncCryptoKey = exports.checkSigCryptoKey = void 0; +const env_js_1 = require("../runtime/env.js"); +function unusable(name, prop = 'algorithm.name') { + return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); +} +function isAlgorithm(algorithm, name) { + return algorithm.name === name; +} +function getHashLength(hash) { + return parseInt(hash.name.slice(4), 10); +} +function getNamedCurve(alg) { + switch (alg) { + case 'ES256': + return 'P-256'; + case 'ES384': + return 'P-384'; + case 'ES512': + return 'P-521'; + default: + throw new Error('unreachable'); + } +} +function checkUsage(key, usages) { + if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { + let msg = 'CryptoKey does not support this operation, its usages must include '; + if (usages.length > 2) { + const last = usages.pop(); + msg += `one of ${usages.join(', ')}, or ${last}.`; + } + else if (usages.length === 2) { + msg += `one of ${usages[0]} or ${usages[1]}.`; + } + else { + msg += `${usages[0]}.`; + } + throw new TypeError(msg); + } +} +function checkSigCryptoKey(key, alg, ...usages) { + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': { + if (!isAlgorithm(key.algorithm, 'HMAC')) + throw unusable('HMAC'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'RS256': + case 'RS384': + case 'RS512': { + if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) + throw unusable('RSASSA-PKCS1-v1_5'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'PS256': + case 'PS384': + case 'PS512': { + if (!isAlgorithm(key.algorithm, 'RSA-PSS')) + throw unusable('RSA-PSS'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'EdDSA': { + if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { + if ((0, env_js_1.isCloudflareWorkers)()) { + if (isAlgorithm(key.algorithm, 'NODE-ED25519')) + break; + throw unusable('Ed25519, Ed448, or NODE-ED25519'); + } + throw unusable('Ed25519 or Ed448'); + } + break; + } + case 'ES256': + case 'ES384': + case 'ES512': { + if (!isAlgorithm(key.algorithm, 'ECDSA')) + throw unusable('ECDSA'); + const expected = getNamedCurve(alg); + const actual = key.algorithm.namedCurve; + if (actual !== expected) + throw unusable(expected, 'algorithm.namedCurve'); + break; + } + default: + throw new TypeError('CryptoKey does not support this operation'); + } + checkUsage(key, usages); +} +exports.checkSigCryptoKey = checkSigCryptoKey; +function checkEncCryptoKey(key, alg, ...usages) { + switch (alg) { + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': { + if (!isAlgorithm(key.algorithm, 'AES-GCM')) + throw unusable('AES-GCM'); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, 'algorithm.length'); + break; + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + if (!isAlgorithm(key.algorithm, 'AES-KW')) + throw unusable('AES-KW'); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, 'algorithm.length'); + break; + } + case 'ECDH': { + switch (key.algorithm.name) { + case 'ECDH': + case 'X25519': + case 'X448': + break; + default: + throw unusable('ECDH, X25519, or X448'); + } + break; + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': + if (!isAlgorithm(key.algorithm, 'PBKDF2')) + throw unusable('PBKDF2'); + break; + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) + throw unusable('RSA-OAEP'); + const expected = parseInt(alg.slice(9), 10) || 1; + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + default: + throw new TypeError('CryptoKey does not support this operation'); + } + checkUsage(key, usages); +} +exports.checkEncCryptoKey = checkEncCryptoKey; diff --git a/dist/node/cjs/lib/decrypt_key_management.js b/dist/node/cjs/lib/decrypt_key_management.js new file mode 100644 index 0000000000..fb2aa37698 --- /dev/null +++ b/dist/node/cjs/lib/decrypt_key_management.js @@ -0,0 +1,100 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const aeskw_js_1 = require("../runtime/aeskw.js"); +const ECDH = require("../runtime/ecdhes.js"); +const pbes2kw_js_1 = require("../runtime/pbes2kw.js"); +const rsaes_js_1 = require("../runtime/rsaes.js"); +const base64url_js_1 = require("../runtime/base64url.js"); +const errors_js_1 = require("../util/errors.js"); +const cek_js_1 = require("../lib/cek.js"); +const import_js_1 = require("../key/import.js"); +const check_key_type_js_1 = require("./check_key_type.js"); +const is_object_js_1 = require("./is_object.js"); +const aesgcmkw_js_1 = require("./aesgcmkw.js"); +async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { + (0, check_key_type_js_1.default)(alg, key, 'decrypt'); + switch (alg) { + case 'dir': { + if (encryptedKey !== undefined) + throw new errors_js_1.JWEInvalid('Encountered unexpected JWE Encrypted Key'); + return key; + } + case 'ECDH-ES': + if (encryptedKey !== undefined) + throw new errors_js_1.JWEInvalid('Encountered unexpected JWE Encrypted Key'); + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + if (!(0, is_object_js_1.default)(joseHeader.epk)) + throw new errors_js_1.JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); + if (!ECDH.ecdhAllowed(key)) + throw new errors_js_1.JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); + const epk = await (0, import_js_1.importJWK)(joseHeader.epk, alg); + let partyUInfo; + let partyVInfo; + if (joseHeader.apu !== undefined) { + if (typeof joseHeader.apu !== 'string') + throw new errors_js_1.JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); + partyUInfo = (0, base64url_js_1.decode)(joseHeader.apu); + } + if (joseHeader.apv !== undefined) { + if (typeof joseHeader.apv !== 'string') + throw new errors_js_1.JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); + partyVInfo = (0, base64url_js_1.decode)(joseHeader.apv); + } + const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); + if (alg === 'ECDH-ES') + return sharedSecret; + if (encryptedKey === undefined) + throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); + return (0, aeskw_js_1.unwrap)(alg.slice(-6), sharedSecret, encryptedKey); + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + if (encryptedKey === undefined) + throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); + return (0, rsaes_js_1.decrypt)(alg, key, encryptedKey); + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + if (encryptedKey === undefined) + throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); + if (typeof joseHeader.p2c !== 'number') + throw new errors_js_1.JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); + const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 10000; + if (joseHeader.p2c > p2cLimit) + throw new errors_js_1.JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); + if (typeof joseHeader.p2s !== 'string') + throw new errors_js_1.JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); + return (0, pbes2kw_js_1.decrypt)(alg, key, encryptedKey, joseHeader.p2c, (0, base64url_js_1.decode)(joseHeader.p2s)); + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + if (encryptedKey === undefined) + throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); + return (0, aeskw_js_1.unwrap)(alg, key, encryptedKey); + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + if (encryptedKey === undefined) + throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing'); + if (typeof joseHeader.iv !== 'string') + throw new errors_js_1.JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); + if (typeof joseHeader.tag !== 'string') + throw new errors_js_1.JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); + const iv = (0, base64url_js_1.decode)(joseHeader.iv); + const tag = (0, base64url_js_1.decode)(joseHeader.tag); + return (0, aesgcmkw_js_1.unwrap)(alg, key, encryptedKey, iv, tag); + } + default: { + throw new errors_js_1.JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } +} +exports.default = decryptKeyManagement; diff --git a/dist/node/cjs/lib/encrypt_key_management.js b/dist/node/cjs/lib/encrypt_key_management.js new file mode 100644 index 0000000000..709364b064 --- /dev/null +++ b/dist/node/cjs/lib/encrypt_key_management.js @@ -0,0 +1,89 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const aeskw_js_1 = require("../runtime/aeskw.js"); +const ECDH = require("../runtime/ecdhes.js"); +const pbes2kw_js_1 = require("../runtime/pbes2kw.js"); +const rsaes_js_1 = require("../runtime/rsaes.js"); +const base64url_js_1 = require("../runtime/base64url.js"); +const cek_js_1 = require("../lib/cek.js"); +const errors_js_1 = require("../util/errors.js"); +const export_js_1 = require("../key/export.js"); +const check_key_type_js_1 = require("./check_key_type.js"); +const aesgcmkw_js_1 = require("./aesgcmkw.js"); +async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { + let encryptedKey; + let parameters; + let cek; + (0, check_key_type_js_1.default)(alg, key, 'encrypt'); + switch (alg) { + case 'dir': { + cek = key; + break; + } + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + if (!ECDH.ecdhAllowed(key)) { + throw new errors_js_1.JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); + } + const { apu, apv } = providedParameters; + let { epk: ephemeralKey } = providedParameters; + ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey); + const { x, y, crv, kty } = await (0, export_js_1.exportJWK)(ephemeralKey); + const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); + parameters = { epk: { x, crv, kty } }; + if (kty === 'EC') + parameters.epk.y = y; + if (apu) + parameters.apu = (0, base64url_js_1.encode)(apu); + if (apv) + parameters.apv = (0, base64url_js_1.encode)(apv); + if (alg === 'ECDH-ES') { + cek = sharedSecret; + break; + } + cek = providedCek || (0, cek_js_1.default)(enc); + const kwAlg = alg.slice(-6); + encryptedKey = await (0, aeskw_js_1.wrap)(kwAlg, sharedSecret, cek); + break; + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + cek = providedCek || (0, cek_js_1.default)(enc); + encryptedKey = await (0, rsaes_js_1.encrypt)(alg, key, cek); + break; + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + cek = providedCek || (0, cek_js_1.default)(enc); + const { p2c, p2s } = providedParameters; + ({ encryptedKey, ...parameters } = await (0, pbes2kw_js_1.encrypt)(alg, key, cek, p2c, p2s)); + break; + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + cek = providedCek || (0, cek_js_1.default)(enc); + encryptedKey = await (0, aeskw_js_1.wrap)(alg, key, cek); + break; + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + cek = providedCek || (0, cek_js_1.default)(enc); + const { iv } = providedParameters; + ({ encryptedKey, ...parameters } = await (0, aesgcmkw_js_1.wrap)(alg, key, cek, iv)); + break; + } + default: { + throw new errors_js_1.JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } + return { cek, encryptedKey, parameters }; +} +exports.default = encryptKeyManagement; diff --git a/dist/node/cjs/lib/epoch.js b/dist/node/cjs/lib/epoch.js new file mode 100644 index 0000000000..a0792b4f7f --- /dev/null +++ b/dist/node/cjs/lib/epoch.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (date) => Math.floor(date.getTime() / 1000); diff --git a/dist/node/cjs/lib/invalid_key_input.js b/dist/node/cjs/lib/invalid_key_input.js new file mode 100644 index 0000000000..e1d5fc1c55 --- /dev/null +++ b/dist/node/cjs/lib/invalid_key_input.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withAlg = void 0; +function message(msg, actual, ...types) { + if (types.length > 2) { + const last = types.pop(); + msg += `one of type ${types.join(', ')}, or ${last}.`; + } + else if (types.length === 2) { + msg += `one of type ${types[0]} or ${types[1]}.`; + } + else { + msg += `of type ${types[0]}.`; + } + if (actual == null) { + msg += ` Received ${actual}`; + } + else if (typeof actual === 'function' && actual.name) { + msg += ` Received function ${actual.name}`; + } + else if (typeof actual === 'object' && actual != null) { + if (actual.constructor && actual.constructor.name) { + msg += ` Received an instance of ${actual.constructor.name}`; + } + } + return msg; +} +exports.default = (actual, ...types) => { + return message('Key must be ', actual, ...types); +}; +function withAlg(alg, actual, ...types) { + return message(`Key for the ${alg} algorithm must be `, actual, ...types); +} +exports.withAlg = withAlg; diff --git a/dist/node/cjs/lib/is_disjoint.js b/dist/node/cjs/lib/is_disjoint.js new file mode 100644 index 0000000000..66c2fc6c82 --- /dev/null +++ b/dist/node/cjs/lib/is_disjoint.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const isDisjoint = (...headers) => { + const sources = headers.filter(Boolean); + if (sources.length === 0 || sources.length === 1) { + return true; + } + let acc; + for (const header of sources) { + const parameters = Object.keys(header); + if (!acc || acc.size === 0) { + acc = new Set(parameters); + continue; + } + for (const parameter of parameters) { + if (acc.has(parameter)) { + return false; + } + acc.add(parameter); + } + } + return true; +}; +exports.default = isDisjoint; diff --git a/dist/node/cjs/lib/is_object.js b/dist/node/cjs/lib/is_object.js new file mode 100644 index 0000000000..870938b59b --- /dev/null +++ b/dist/node/cjs/lib/is_object.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function isObjectLike(value) { + return typeof value === 'object' && value !== null; +} +function isObject(input) { + if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { + return false; + } + if (Object.getPrototypeOf(input) === null) { + return true; + } + let proto = input; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + return Object.getPrototypeOf(input) === proto; +} +exports.default = isObject; diff --git a/dist/node/cjs/lib/iv.js b/dist/node/cjs/lib/iv.js new file mode 100644 index 0000000000..db7d3a5912 --- /dev/null +++ b/dist/node/cjs/lib/iv.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.bitLength = void 0; +const errors_js_1 = require("../util/errors.js"); +const random_js_1 = require("../runtime/random.js"); +function bitLength(alg) { + switch (alg) { + case 'A128GCM': + case 'A128GCMKW': + case 'A192GCM': + case 'A192GCMKW': + case 'A256GCM': + case 'A256GCMKW': + return 96; + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return 128; + default: + throw new errors_js_1.JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +exports.bitLength = bitLength; +exports.default = (alg) => (0, random_js_1.default)(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/cjs/lib/jwt_claims_set.js b/dist/node/cjs/lib/jwt_claims_set.js new file mode 100644 index 0000000000..ce5e0ebbe3 --- /dev/null +++ b/dist/node/cjs/lib/jwt_claims_set.js @@ -0,0 +1,93 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const errors_js_1 = require("../util/errors.js"); +const buffer_utils_js_1 = require("./buffer_utils.js"); +const epoch_js_1 = require("./epoch.js"); +const secs_js_1 = require("./secs.js"); +const is_object_js_1 = require("./is_object.js"); +const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ''); +const checkAudiencePresence = (audPayload, audOption) => { + if (typeof audPayload === 'string') { + return audOption.includes(audPayload); + } + if (Array.isArray(audPayload)) { + return audOption.some(Set.prototype.has.bind(new Set(audPayload))); + } + return false; +}; +exports.default = (protectedHeader, encodedPayload, options = {}) => { + const { typ } = options; + if (typ && + (typeof protectedHeader.typ !== 'string' || + normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { + throw new errors_js_1.JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed'); + } + let payload; + try { + payload = JSON.parse(buffer_utils_js_1.decoder.decode(encodedPayload)); + } + catch { + } + if (!(0, is_object_js_1.default)(payload)) { + throw new errors_js_1.JWTInvalid('JWT Claims Set must be a top-level JSON object'); + } + const { issuer } = options; + if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { + throw new errors_js_1.JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed'); + } + const { subject } = options; + if (subject && payload.sub !== subject) { + throw new errors_js_1.JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed'); + } + const { audience } = options; + if (audience && + !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) { + throw new errors_js_1.JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed'); + } + let tolerance; + switch (typeof options.clockTolerance) { + case 'string': + tolerance = (0, secs_js_1.default)(options.clockTolerance); + break; + case 'number': + tolerance = options.clockTolerance; + break; + case 'undefined': + tolerance = 0; + break; + default: + throw new TypeError('Invalid clockTolerance option type'); + } + const { currentDate } = options; + const now = (0, epoch_js_1.default)(currentDate || new Date()); + if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { + throw new errors_js_1.JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid'); + } + if (payload.nbf !== undefined) { + if (typeof payload.nbf !== 'number') { + throw new errors_js_1.JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid'); + } + if (payload.nbf > now + tolerance) { + throw new errors_js_1.JWTClaimValidationFailed('"nbf" claim timestamp check failed', 'nbf', 'check_failed'); + } + } + if (payload.exp !== undefined) { + if (typeof payload.exp !== 'number') { + throw new errors_js_1.JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid'); + } + if (payload.exp <= now - tolerance) { + throw new errors_js_1.JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed'); + } + } + if (options.maxTokenAge) { + const age = now - payload.iat; + const max = typeof options.maxTokenAge === 'number' ? options.maxTokenAge : (0, secs_js_1.default)(options.maxTokenAge); + if (age - tolerance > max) { + throw new errors_js_1.JWTExpired('"iat" claim timestamp check failed (too far in the past)', 'iat', 'check_failed'); + } + if (age < 0 - tolerance) { + throw new errors_js_1.JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed'); + } + } + return payload; +}; diff --git a/dist/node/cjs/lib/secs.js b/dist/node/cjs/lib/secs.js new file mode 100644 index 0000000000..f1b6a0c15d --- /dev/null +++ b/dist/node/cjs/lib/secs.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const minute = 60; +const hour = minute * 60; +const day = hour * 24; +const week = day * 7; +const year = day * 365.25; +const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; +exports.default = (str) => { + const matched = REGEX.exec(str); + if (!matched) { + throw new TypeError('Invalid time period format'); + } + const value = parseFloat(matched[1]); + const unit = matched[2].toLowerCase(); + switch (unit) { + case 'sec': + case 'secs': + case 'second': + case 'seconds': + case 's': + return Math.round(value); + case 'minute': + case 'minutes': + case 'min': + case 'mins': + case 'm': + return Math.round(value * minute); + case 'hour': + case 'hours': + case 'hr': + case 'hrs': + case 'h': + return Math.round(value * hour); + case 'day': + case 'days': + case 'd': + return Math.round(value * day); + case 'week': + case 'weeks': + case 'w': + return Math.round(value * week); + default: + return Math.round(value * year); + } +}; diff --git a/dist/node/cjs/lib/validate_algorithms.js b/dist/node/cjs/lib/validate_algorithms.js new file mode 100644 index 0000000000..29f4e80df9 --- /dev/null +++ b/dist/node/cjs/lib/validate_algorithms.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const validateAlgorithms = (option, algorithms) => { + if (algorithms !== undefined && + (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) { + throw new TypeError(`"${option}" option must be an array of strings`); + } + if (!algorithms) { + return undefined; + } + return new Set(algorithms); +}; +exports.default = validateAlgorithms; diff --git a/dist/node/cjs/lib/validate_crit.js b/dist/node/cjs/lib/validate_crit.js new file mode 100644 index 0000000000..b0229e3b72 --- /dev/null +++ b/dist/node/cjs/lib/validate_crit.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const errors_js_1 = require("../util/errors.js"); +function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { + if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { + throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); + } + if (!protectedHeader || protectedHeader.crit === undefined) { + return new Set(); + } + if (!Array.isArray(protectedHeader.crit) || + protectedHeader.crit.length === 0 || + protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) { + throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); + } + let recognized; + if (recognizedOption !== undefined) { + recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); + } + else { + recognized = recognizedDefault; + } + for (const parameter of protectedHeader.crit) { + if (!recognized.has(parameter)) { + throw new errors_js_1.JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); + } + if (joseHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" is missing`); + } + else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); + } + } + return new Set(protectedHeader.crit); +} +exports.default = validateCrit; diff --git a/dist/node/cjs/runtime/aeskw.js b/dist/node/cjs/runtime/aeskw.js new file mode 100644 index 0000000000..ca26086881 --- /dev/null +++ b/dist/node/cjs/runtime/aeskw.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.unwrap = exports.wrap = void 0; +const buffer_1 = require("buffer"); +const crypto_1 = require("crypto"); +const errors_js_1 = require("../util/errors.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const crypto_key_js_1 = require("../lib/crypto_key.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const ciphers_js_1 = require("./ciphers.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +function checkKeySize(key, alg) { + if (key.symmetricKeySize << 3 !== parseInt(alg.slice(1, 4), 10)) { + throw new TypeError(`Invalid key size for alg: ${alg}`); + } +} +function ensureKeyObject(key, alg, usage) { + if ((0, is_key_object_js_1.default)(key)) { + return key; + } + if (key instanceof Uint8Array) { + return (0, crypto_1.createSecretKey)(key); + } + if ((0, webcrypto_js_1.isCryptoKey)(key)) { + (0, crypto_key_js_1.checkEncCryptoKey)(key, alg, usage); + return crypto_1.KeyObject.from(key); + } + throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); +} +const wrap = (alg, key, cek) => { + const size = parseInt(alg.slice(1, 4), 10); + const algorithm = `aes${size}-wrap`; + if (!(0, ciphers_js_1.default)(algorithm)) { + throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } + const keyObject = ensureKeyObject(key, alg, 'wrapKey'); + checkKeySize(keyObject, alg); + const cipher = (0, crypto_1.createCipheriv)(algorithm, keyObject, buffer_1.Buffer.alloc(8, 0xa6)); + return (0, buffer_utils_js_1.concat)(cipher.update(cek), cipher.final()); +}; +exports.wrap = wrap; +const unwrap = (alg, key, encryptedKey) => { + const size = parseInt(alg.slice(1, 4), 10); + const algorithm = `aes${size}-wrap`; + if (!(0, ciphers_js_1.default)(algorithm)) { + throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } + const keyObject = ensureKeyObject(key, alg, 'unwrapKey'); + checkKeySize(keyObject, alg); + const cipher = (0, crypto_1.createDecipheriv)(algorithm, keyObject, buffer_1.Buffer.alloc(8, 0xa6)); + return (0, buffer_utils_js_1.concat)(cipher.update(encryptedKey), cipher.final()); +}; +exports.unwrap = unwrap; diff --git a/dist/node/cjs/runtime/asn1.js b/dist/node/cjs/runtime/asn1.js new file mode 100644 index 0000000000..3695dae247 --- /dev/null +++ b/dist/node/cjs/runtime/asn1.js @@ -0,0 +1,54 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.fromX509 = exports.fromSPKI = exports.fromPKCS8 = exports.toPKCS8 = exports.toSPKI = void 0; +const crypto_1 = require("crypto"); +const buffer_1 = require("buffer"); +const webcrypto_js_1 = require("./webcrypto.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +const genericExport = (keyType, keyFormat, key) => { + let keyObject; + if ((0, webcrypto_js_1.isCryptoKey)(key)) { + if (!key.extractable) { + throw new TypeError('CryptoKey is not extractable'); + } + keyObject = crypto_1.KeyObject.from(key); + } + else if ((0, is_key_object_js_1.default)(key)) { + keyObject = key; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types)); + } + if (keyObject.type !== keyType) { + throw new TypeError(`key is not a ${keyType} key`); + } + return keyObject.export({ format: 'pem', type: keyFormat }); +}; +const toSPKI = (key) => { + return genericExport('public', 'spki', key); +}; +exports.toSPKI = toSPKI; +const toPKCS8 = (key) => { + return genericExport('private', 'pkcs8', key); +}; +exports.toPKCS8 = toPKCS8; +const fromPKCS8 = (pem) => (0, crypto_1.createPrivateKey)({ + key: buffer_1.Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, ''), 'base64'), + type: 'pkcs8', + format: 'der', +}); +exports.fromPKCS8 = fromPKCS8; +const fromSPKI = (pem) => (0, crypto_1.createPublicKey)({ + key: buffer_1.Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, ''), 'base64'), + type: 'spki', + format: 'der', +}); +exports.fromSPKI = fromSPKI; +const fromX509 = (pem) => (0, crypto_1.createPublicKey)({ + key: pem, + type: 'spki', + format: 'pem', +}); +exports.fromX509 = fromX509; diff --git a/dist/node/cjs/runtime/asn1_sequence_decoder.js b/dist/node/cjs/runtime/asn1_sequence_decoder.js new file mode 100644 index 0000000000..4f96522335 --- /dev/null +++ b/dist/node/cjs/runtime/asn1_sequence_decoder.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const tagInteger = 0x02; +const tagSequence = 0x30; +class Asn1SequenceDecoder { + constructor(buffer) { + if (buffer[0] !== tagSequence) { + throw new TypeError(); + } + this.buffer = buffer; + this.offset = 1; + const len = this.decodeLength(); + if (len !== buffer.length - this.offset) { + throw new TypeError(); + } + } + decodeLength() { + let length = this.buffer[this.offset++]; + if (length & 0x80) { + const nBytes = length & ~0x80; + length = 0; + for (let i = 0; i < nBytes; i++) + length = (length << 8) | this.buffer[this.offset + i]; + this.offset += nBytes; + } + return length; + } + unsignedInteger() { + if (this.buffer[this.offset++] !== tagInteger) { + throw new TypeError(); + } + let length = this.decodeLength(); + if (this.buffer[this.offset] === 0) { + this.offset++; + length--; + } + const result = this.buffer.slice(this.offset, this.offset + length); + this.offset += length; + return result; + } + end() { + if (this.offset !== this.buffer.length) { + throw new TypeError(); + } + } +} +exports.default = Asn1SequenceDecoder; diff --git a/dist/node/cjs/runtime/asn1_sequence_encoder.js b/dist/node/cjs/runtime/asn1_sequence_encoder.js new file mode 100644 index 0000000000..8b71d6dc28 --- /dev/null +++ b/dist/node/cjs/runtime/asn1_sequence_encoder.js @@ -0,0 +1,91 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const buffer_1 = require("buffer"); +const errors_js_1 = require("../util/errors.js"); +const tagInteger = 0x02; +const tagBitStr = 0x03; +const tagOctStr = 0x04; +const tagSequence = 0x30; +const bZero = buffer_1.Buffer.from([0x00]); +const bTagInteger = buffer_1.Buffer.from([tagInteger]); +const bTagBitStr = buffer_1.Buffer.from([tagBitStr]); +const bTagSequence = buffer_1.Buffer.from([tagSequence]); +const bTagOctStr = buffer_1.Buffer.from([tagOctStr]); +const encodeLength = (len) => { + if (len < 128) + return buffer_1.Buffer.from([len]); + const buffer = buffer_1.Buffer.alloc(5); + buffer.writeUInt32BE(len, 1); + let offset = 1; + while (buffer[offset] === 0) + offset++; + buffer[offset - 1] = 0x80 | (5 - offset); + return buffer.slice(offset - 1); +}; +const oids = new Map([ + ['P-256', buffer_1.Buffer.from('06 08 2A 86 48 CE 3D 03 01 07'.replace(/ /g, ''), 'hex')], + ['secp256k1', buffer_1.Buffer.from('06 05 2B 81 04 00 0A'.replace(/ /g, ''), 'hex')], + ['P-384', buffer_1.Buffer.from('06 05 2B 81 04 00 22'.replace(/ /g, ''), 'hex')], + ['P-521', buffer_1.Buffer.from('06 05 2B 81 04 00 23'.replace(/ /g, ''), 'hex')], + ['ecPublicKey', buffer_1.Buffer.from('06 07 2A 86 48 CE 3D 02 01'.replace(/ /g, ''), 'hex')], + ['X25519', buffer_1.Buffer.from('06 03 2B 65 6E'.replace(/ /g, ''), 'hex')], + ['X448', buffer_1.Buffer.from('06 03 2B 65 6F'.replace(/ /g, ''), 'hex')], + ['Ed25519', buffer_1.Buffer.from('06 03 2B 65 70'.replace(/ /g, ''), 'hex')], + ['Ed448', buffer_1.Buffer.from('06 03 2B 65 71'.replace(/ /g, ''), 'hex')], +]); +class DumbAsn1Encoder { + constructor() { + this.length = 0; + this.elements = []; + } + oidFor(oid) { + const bOid = oids.get(oid); + if (!bOid) { + throw new errors_js_1.JOSENotSupported('Invalid or unsupported OID'); + } + this.elements.push(bOid); + this.length += bOid.length; + } + zero() { + this.elements.push(bTagInteger, buffer_1.Buffer.from([0x01]), bZero); + this.length += 3; + } + one() { + this.elements.push(bTagInteger, buffer_1.Buffer.from([0x01]), buffer_1.Buffer.from([0x01])); + this.length += 3; + } + unsignedInteger(integer) { + if (integer[0] & 0x80) { + const len = encodeLength(integer.length + 1); + this.elements.push(bTagInteger, len, bZero, integer); + this.length += 2 + len.length + integer.length; + } + else { + let i = 0; + while (integer[i] === 0 && (integer[i + 1] & 0x80) === 0) + i++; + const len = encodeLength(integer.length - i); + this.elements.push(bTagInteger, encodeLength(integer.length - i), integer.slice(i)); + this.length += 1 + len.length + integer.length - i; + } + } + octStr(octStr) { + const len = encodeLength(octStr.length); + this.elements.push(bTagOctStr, encodeLength(octStr.length), octStr); + this.length += 1 + len.length + octStr.length; + } + bitStr(bitS) { + const len = encodeLength(bitS.length + 1); + this.elements.push(bTagBitStr, encodeLength(bitS.length + 1), bZero, bitS); + this.length += 1 + len.length + bitS.length + 1; + } + add(seq) { + this.elements.push(seq); + this.length += seq.length; + } + end(tag = bTagSequence) { + const len = encodeLength(this.length); + return buffer_1.Buffer.concat([tag, len, ...this.elements], 1 + len.length + this.length); + } +} +exports.default = DumbAsn1Encoder; diff --git a/dist/node/cjs/runtime/base64url.js b/dist/node/cjs/runtime/base64url.js new file mode 100644 index 0000000000..3a38a4ba74 --- /dev/null +++ b/dist/node/cjs/runtime/base64url.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decode = exports.encode = exports.encodeBase64 = exports.decodeBase64 = void 0; +const buffer_1 = require("buffer"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +let encode; +exports.encode = encode; +function normalize(input) { + let encoded = input; + if (encoded instanceof Uint8Array) { + encoded = buffer_utils_js_1.decoder.decode(encoded); + } + return encoded; +} +if (buffer_1.Buffer.isEncoding('base64url')) { + exports.encode = encode = (input) => buffer_1.Buffer.from(input).toString('base64url'); +} +else { + exports.encode = encode = (input) => buffer_1.Buffer.from(input).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); +} +const decodeBase64 = (input) => buffer_1.Buffer.from(input, 'base64'); +exports.decodeBase64 = decodeBase64; +const encodeBase64 = (input) => buffer_1.Buffer.from(input).toString('base64'); +exports.encodeBase64 = encodeBase64; +const decode = (input) => buffer_1.Buffer.from(normalize(input), 'base64'); +exports.decode = decode; diff --git a/dist/node/cjs/runtime/cbc_tag.js b/dist/node/cjs/runtime/cbc_tag.js new file mode 100644 index 0000000000..03412c2cfb --- /dev/null +++ b/dist/node/cjs/runtime/cbc_tag.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +function cbcTag(aad, iv, ciphertext, macSize, macKey, keySize) { + const macData = (0, buffer_utils_js_1.concat)(aad, iv, ciphertext, (0, buffer_utils_js_1.uint64be)(aad.length << 3)); + const hmac = (0, crypto_1.createHmac)(`sha${macSize}`, macKey); + hmac.update(macData); + return hmac.digest().slice(0, keySize >> 3); +} +exports.default = cbcTag; diff --git a/dist/node/cjs/runtime/check_cek_length.js b/dist/node/cjs/runtime/check_cek_length.js new file mode 100644 index 0000000000..5192e750db --- /dev/null +++ b/dist/node/cjs/runtime/check_cek_length.js @@ -0,0 +1,37 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const errors_js_1 = require("../util/errors.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const checkCekLength = (enc, cek) => { + let expected; + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + expected = parseInt(enc.slice(-3), 10); + break; + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + expected = parseInt(enc.slice(1, 4), 10); + break; + default: + throw new errors_js_1.JOSENotSupported(`Content Encryption Algorithm ${enc} is not supported either by JOSE or your javascript runtime`); + } + if (cek instanceof Uint8Array) { + const actual = cek.byteLength << 3; + if (actual !== expected) { + throw new errors_js_1.JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); + } + return; + } + if ((0, is_key_object_js_1.default)(cek) && cek.type === 'secret') { + const actual = cek.symmetricKeySize << 3; + if (actual !== expected) { + throw new errors_js_1.JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); + } + return; + } + throw new TypeError('Invalid Content Encryption Key type'); +}; +exports.default = checkCekLength; diff --git a/dist/node/cjs/runtime/check_modulus_length.js b/dist/node/cjs/runtime/check_modulus_length.js new file mode 100644 index 0000000000..72c670eba3 --- /dev/null +++ b/dist/node/cjs/runtime/check_modulus_length.js @@ -0,0 +1,52 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.setModulusLength = exports.weakMap = void 0; +exports.weakMap = new WeakMap(); +const getLength = (buf, index) => { + let len = buf.readUInt8(1); + if ((len & 0x80) === 0) { + if (index === 0) { + return len; + } + return getLength(buf.subarray(2 + len), index - 1); + } + const num = len & 0x7f; + len = 0; + for (let i = 0; i < num; i++) { + len <<= 8; + const j = buf.readUInt8(2 + i); + len |= j; + } + if (index === 0) { + return len; + } + return getLength(buf.subarray(2 + len), index - 1); +}; +const getLengthOfSeqIndex = (sequence, index) => { + const len = sequence.readUInt8(1); + if ((len & 0x80) === 0) { + return getLength(sequence.subarray(2), index); + } + const num = len & 0x7f; + return getLength(sequence.subarray(2 + num), index); +}; +const getModulusLength = (key) => { + var _a, _b; + if (exports.weakMap.has(key)) { + return exports.weakMap.get(key); + } + const modulusLength = (_b = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.modulusLength) !== null && _b !== void 0 ? _b : (getLengthOfSeqIndex(key.export({ format: 'der', type: 'pkcs1' }), key.type === 'private' ? 1 : 0) - + 1) << + 3; + exports.weakMap.set(key, modulusLength); + return modulusLength; +}; +const setModulusLength = (keyObject, modulusLength) => { + exports.weakMap.set(keyObject, modulusLength); +}; +exports.setModulusLength = setModulusLength; +exports.default = (key, alg) => { + if (getModulusLength(key) < 2048) { + throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); + } +}; diff --git a/dist/node/cjs/runtime/ciphers.js b/dist/node/cjs/runtime/ciphers.js new file mode 100644 index 0000000000..e004c84562 --- /dev/null +++ b/dist/node/cjs/runtime/ciphers.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +let ciphers; +exports.default = (algorithm) => { + ciphers || (ciphers = new Set((0, crypto_1.getCiphers)())); + return ciphers.has(algorithm); +}; diff --git a/dist/node/cjs/runtime/decrypt.js b/dist/node/cjs/runtime/decrypt.js new file mode 100644 index 0000000000..6e0de6d472 --- /dev/null +++ b/dist/node/cjs/runtime/decrypt.js @@ -0,0 +1,97 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const check_iv_length_js_1 = require("../lib/check_iv_length.js"); +const check_cek_length_js_1 = require("./check_cek_length.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const errors_js_1 = require("../util/errors.js"); +const timing_safe_equal_js_1 = require("./timing_safe_equal.js"); +const cbc_tag_js_1 = require("./cbc_tag.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const crypto_key_js_1 = require("../lib/crypto_key.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const ciphers_js_1 = require("./ciphers.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + if ((0, is_key_object_js_1.default)(cek)) { + cek = cek.export(); + } + const encKey = cek.subarray(keySize >> 3); + const macKey = cek.subarray(0, keySize >> 3); + const macSize = parseInt(enc.slice(-3), 10); + const algorithm = `aes-${keySize}-cbc`; + if (!(0, ciphers_js_1.default)(algorithm)) { + throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + const expectedTag = (0, cbc_tag_js_1.default)(aad, iv, ciphertext, macSize, macKey, keySize); + let macCheckPassed; + try { + macCheckPassed = (0, timing_safe_equal_js_1.default)(tag, expectedTag); + } + catch { + } + if (!macCheckPassed) { + throw new errors_js_1.JWEDecryptionFailed(); + } + let plaintext; + try { + const decipher = (0, crypto_1.createDecipheriv)(algorithm, encKey, iv); + plaintext = (0, buffer_utils_js_1.concat)(decipher.update(ciphertext), decipher.final()); + } + catch { + } + if (!plaintext) { + throw new errors_js_1.JWEDecryptionFailed(); + } + return plaintext; +} +function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + const algorithm = `aes-${keySize}-gcm`; + if (!(0, ciphers_js_1.default)(algorithm)) { + throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + try { + const decipher = (0, crypto_1.createDecipheriv)(algorithm, cek, iv, { authTagLength: 16 }); + decipher.setAuthTag(tag); + if (aad.byteLength) { + decipher.setAAD(aad, { plaintextLength: ciphertext.length }); + } + const plaintext = decipher.update(ciphertext); + decipher.final(); + return plaintext; + } + catch { + throw new errors_js_1.JWEDecryptionFailed(); + } +} +const decrypt = (enc, cek, ciphertext, iv, tag, aad) => { + let key; + if ((0, webcrypto_js_1.isCryptoKey)(cek)) { + (0, crypto_key_js_1.checkEncCryptoKey)(cek, enc, 'decrypt'); + key = crypto_1.KeyObject.from(cek); + } + else if (cek instanceof Uint8Array || (0, is_key_object_js_1.default)(cek)) { + key = cek; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(cek, ...is_key_like_js_1.types, 'Uint8Array')); + } + (0, check_cek_length_js_1.default)(enc, key); + (0, check_iv_length_js_1.default)(enc, iv); + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return cbcDecrypt(enc, key, ciphertext, iv, tag, aad); + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + return gcmDecrypt(enc, key, ciphertext, iv, tag, aad); + default: + throw new errors_js_1.JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); + } +}; +exports.default = decrypt; diff --git a/dist/node/cjs/runtime/digest.js b/dist/node/cjs/runtime/digest.js new file mode 100644 index 0000000000..13c194a8ed --- /dev/null +++ b/dist/node/cjs/runtime/digest.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const digest = (algorithm, data) => (0, crypto_1.createHash)(algorithm).update(data).digest(); +exports.default = digest; diff --git a/dist/node/cjs/runtime/dsa_digest.js b/dist/node/cjs/runtime/dsa_digest.js new file mode 100644 index 0000000000..fde4883e81 --- /dev/null +++ b/dist/node/cjs/runtime/dsa_digest.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const errors_js_1 = require("../util/errors.js"); +function dsaDigest(alg) { + switch (alg) { + case 'PS256': + case 'RS256': + case 'ES256': + case 'ES256K': + return 'sha256'; + case 'PS384': + case 'RS384': + case 'ES384': + return 'sha384'; + case 'PS512': + case 'RS512': + case 'ES512': + return 'sha512'; + case 'EdDSA': + return undefined; + default: + throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} +exports.default = dsaDigest; diff --git a/dist/node/cjs/runtime/ecdhes.js b/dist/node/cjs/runtime/ecdhes.js new file mode 100644 index 0000000000..d769af7603 --- /dev/null +++ b/dist/node/cjs/runtime/ecdhes.js @@ -0,0 +1,70 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ecdhAllowed = exports.generateEpk = exports.deriveKey = void 0; +const crypto_1 = require("crypto"); +const util_1 = require("util"); +const get_named_curve_js_1 = require("./get_named_curve.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const errors_js_1 = require("../util/errors.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const crypto_key_js_1 = require("../lib/crypto_key.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +const generateKeyPair = (0, util_1.promisify)(crypto_1.generateKeyPair); +async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { + let publicKey; + if ((0, webcrypto_js_1.isCryptoKey)(publicKee)) { + (0, crypto_key_js_1.checkEncCryptoKey)(publicKee, 'ECDH'); + publicKey = crypto_1.KeyObject.from(publicKee); + } + else if ((0, is_key_object_js_1.default)(publicKee)) { + publicKey = publicKee; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(publicKee, ...is_key_like_js_1.types)); + } + let privateKey; + if ((0, webcrypto_js_1.isCryptoKey)(privateKee)) { + (0, crypto_key_js_1.checkEncCryptoKey)(privateKee, 'ECDH', 'deriveBits'); + privateKey = crypto_1.KeyObject.from(privateKee); + } + else if ((0, is_key_object_js_1.default)(privateKee)) { + privateKey = privateKee; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(privateKee, ...is_key_like_js_1.types)); + } + const value = (0, buffer_utils_js_1.concat)((0, buffer_utils_js_1.lengthAndInput)(buffer_utils_js_1.encoder.encode(algorithm)), (0, buffer_utils_js_1.lengthAndInput)(apu), (0, buffer_utils_js_1.lengthAndInput)(apv), (0, buffer_utils_js_1.uint32be)(keyLength)); + const sharedSecret = (0, crypto_1.diffieHellman)({ privateKey, publicKey }); + return (0, buffer_utils_js_1.concatKdf)(sharedSecret, keyLength, value); +} +exports.deriveKey = deriveKey; +async function generateEpk(kee) { + let key; + if ((0, webcrypto_js_1.isCryptoKey)(kee)) { + key = crypto_1.KeyObject.from(kee); + } + else if ((0, is_key_object_js_1.default)(kee)) { + key = kee; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(kee, ...is_key_like_js_1.types)); + } + switch (key.asymmetricKeyType) { + case 'x25519': + return generateKeyPair('x25519'); + case 'x448': { + return generateKeyPair('x448'); + } + case 'ec': { + const namedCurve = (0, get_named_curve_js_1.default)(key); + return generateKeyPair('ec', { namedCurve }); + } + default: + throw new errors_js_1.JOSENotSupported('Invalid or unsupported EPK'); + } +} +exports.generateEpk = generateEpk; +const ecdhAllowed = (key) => ['P-256', 'P-384', 'P-521', 'X25519', 'X448'].includes((0, get_named_curve_js_1.default)(key)); +exports.ecdhAllowed = ecdhAllowed; diff --git a/dist/node/cjs/runtime/encrypt.js b/dist/node/cjs/runtime/encrypt.js new file mode 100644 index 0000000000..940a1ed28b --- /dev/null +++ b/dist/node/cjs/runtime/encrypt.js @@ -0,0 +1,74 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const check_iv_length_js_1 = require("../lib/check_iv_length.js"); +const check_cek_length_js_1 = require("./check_cek_length.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const cbc_tag_js_1 = require("./cbc_tag.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const crypto_key_js_1 = require("../lib/crypto_key.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const errors_js_1 = require("../util/errors.js"); +const ciphers_js_1 = require("./ciphers.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +function cbcEncrypt(enc, plaintext, cek, iv, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + if ((0, is_key_object_js_1.default)(cek)) { + cek = cek.export(); + } + const encKey = cek.subarray(keySize >> 3); + const macKey = cek.subarray(0, keySize >> 3); + const algorithm = `aes-${keySize}-cbc`; + if (!(0, ciphers_js_1.default)(algorithm)) { + throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + const cipher = (0, crypto_1.createCipheriv)(algorithm, encKey, iv); + const ciphertext = (0, buffer_utils_js_1.concat)(cipher.update(plaintext), cipher.final()); + const macSize = parseInt(enc.slice(-3), 10); + const tag = (0, cbc_tag_js_1.default)(aad, iv, ciphertext, macSize, macKey, keySize); + return { ciphertext, tag }; +} +function gcmEncrypt(enc, plaintext, cek, iv, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + const algorithm = `aes-${keySize}-gcm`; + if (!(0, ciphers_js_1.default)(algorithm)) { + throw new errors_js_1.JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + const cipher = (0, crypto_1.createCipheriv)(algorithm, cek, iv, { authTagLength: 16 }); + if (aad.byteLength) { + cipher.setAAD(aad, { plaintextLength: plaintext.length }); + } + const ciphertext = cipher.update(plaintext); + cipher.final(); + const tag = cipher.getAuthTag(); + return { ciphertext, tag }; +} +const encrypt = (enc, plaintext, cek, iv, aad) => { + let key; + if ((0, webcrypto_js_1.isCryptoKey)(cek)) { + (0, crypto_key_js_1.checkEncCryptoKey)(cek, enc, 'encrypt'); + key = crypto_1.KeyObject.from(cek); + } + else if (cek instanceof Uint8Array || (0, is_key_object_js_1.default)(cek)) { + key = cek; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(cek, ...is_key_like_js_1.types, 'Uint8Array')); + } + (0, check_cek_length_js_1.default)(enc, key); + (0, check_iv_length_js_1.default)(enc, iv); + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return cbcEncrypt(enc, plaintext, key, iv, aad); + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + return gcmEncrypt(enc, plaintext, key, iv, aad); + default: + throw new errors_js_1.JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); + } +}; +exports.default = encrypt; diff --git a/dist/node/cjs/runtime/env.js b/dist/node/cjs/runtime/env.js new file mode 100644 index 0000000000..e6a6f4acfe --- /dev/null +++ b/dist/node/cjs/runtime/env.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isCloudflareWorkers = void 0; +function isCloudflareWorkers() { + return false; +} +exports.isCloudflareWorkers = isCloudflareWorkers; diff --git a/dist/node/cjs/runtime/fetch_jwks.js b/dist/node/cjs/runtime/fetch_jwks.js new file mode 100644 index 0000000000..b034fd5bb4 --- /dev/null +++ b/dist/node/cjs/runtime/fetch_jwks.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http = require("http"); +const https = require("https"); +const events_1 = require("events"); +const errors_js_1 = require("../util/errors.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const fetchJwks = async (url, timeout, options) => { + let get; + switch (url.protocol) { + case 'https:': + get = https.get; + break; + case 'http:': + get = http.get; + break; + default: + throw new TypeError('Unsupported URL protocol.'); + } + const { agent, headers } = options; + const req = get(url.href, { + agent, + timeout, + headers, + }); + const [response] = (await Promise.race([(0, events_1.once)(req, 'response'), (0, events_1.once)(req, 'timeout')])); + if (!response) { + req.destroy(); + throw new errors_js_1.JWKSTimeout(); + } + if (response.statusCode !== 200) { + throw new errors_js_1.JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response'); + } + const parts = []; + for await (const part of response) { + parts.push(part); + } + try { + return JSON.parse(buffer_utils_js_1.decoder.decode((0, buffer_utils_js_1.concat)(...parts))); + } + catch { + throw new errors_js_1.JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON'); + } +}; +exports.default = fetchJwks; diff --git a/dist/node/cjs/runtime/flags.js b/dist/node/cjs/runtime/flags.js new file mode 100644 index 0000000000..7a4e64dd74 --- /dev/null +++ b/dist/node/cjs/runtime/flags.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.jwkImport = exports.jwkExport = exports.rsaPssParams = exports.oneShotCallback = void 0; +const [major, minor] = process.versions.node.split('.').map((str) => parseInt(str, 10)); +exports.oneShotCallback = major >= 16 || (major === 15 && minor >= 13); +exports.rsaPssParams = !('electron' in process.versions) && (major >= 17 || (major === 16 && minor >= 9)); +exports.jwkExport = major >= 16 || (major === 15 && minor >= 9); +exports.jwkImport = major >= 16 || (major === 15 && minor >= 12); diff --git a/dist/node/cjs/runtime/generate.js b/dist/node/cjs/runtime/generate.js new file mode 100644 index 0000000000..38aa92bae3 --- /dev/null +++ b/dist/node/cjs/runtime/generate.js @@ -0,0 +1,105 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateKeyPair = exports.generateSecret = void 0; +const crypto_1 = require("crypto"); +const util_1 = require("util"); +const random_js_1 = require("./random.js"); +const check_modulus_length_js_1 = require("./check_modulus_length.js"); +const errors_js_1 = require("../util/errors.js"); +const generate = (0, util_1.promisify)(crypto_1.generateKeyPair); +async function generateSecret(alg, options) { + let length; + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + length = parseInt(alg.slice(-3), 10); + break; + case 'A128KW': + case 'A192KW': + case 'A256KW': + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + length = parseInt(alg.slice(1, 4), 10); + break; + default: + throw new errors_js_1.JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + return (0, crypto_1.createSecretKey)((0, random_js_1.default)(new Uint8Array(length >> 3))); +} +exports.generateSecret = generateSecret; +async function generateKeyPair(alg, options) { + var _a, _b; + switch (alg) { + case 'RS256': + case 'RS384': + case 'RS512': + case 'PS256': + case 'PS384': + case 'PS512': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + case 'RSA1_5': { + const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; + if (typeof modulusLength !== 'number' || modulusLength < 2048) { + throw new errors_js_1.JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used'); + } + const keypair = await generate('rsa', { + modulusLength, + publicExponent: 0x10001, + }); + (0, check_modulus_length_js_1.setModulusLength)(keypair.privateKey, modulusLength); + (0, check_modulus_length_js_1.setModulusLength)(keypair.publicKey, modulusLength); + return keypair; + } + case 'ES256': + return generate('ec', { namedCurve: 'P-256' }); + case 'ES256K': + return generate('ec', { namedCurve: 'secp256k1' }); + case 'ES384': + return generate('ec', { namedCurve: 'P-384' }); + case 'ES512': + return generate('ec', { namedCurve: 'P-521' }); + case 'EdDSA': { + switch (options === null || options === void 0 ? void 0 : options.crv) { + case undefined: + case 'Ed25519': + return generate('ed25519'); + case 'Ed448': + return generate('ed448'); + default: + throw new errors_js_1.JOSENotSupported('Invalid or unsupported crv option provided, supported values are Ed25519 and Ed448'); + } + } + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': + const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256'; + switch (crv) { + case undefined: + case 'P-256': + case 'P-384': + case 'P-521': + return generate('ec', { namedCurve: crv }); + case 'X25519': + return generate('x25519'); + case 'X448': + return generate('x448'); + default: + throw new errors_js_1.JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448'); + } + default: + throw new errors_js_1.JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } +} +exports.generateKeyPair = generateKeyPair; diff --git a/dist/node/cjs/runtime/get_named_curve.js b/dist/node/cjs/runtime/get_named_curve.js new file mode 100644 index 0000000000..bb46729e3d --- /dev/null +++ b/dist/node/cjs/runtime/get_named_curve.js @@ -0,0 +1,95 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.setCurve = exports.weakMap = void 0; +const buffer_1 = require("buffer"); +const crypto_1 = require("crypto"); +const errors_js_1 = require("../util/errors.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +const p256 = buffer_1.Buffer.from([42, 134, 72, 206, 61, 3, 1, 7]); +const p384 = buffer_1.Buffer.from([43, 129, 4, 0, 34]); +const p521 = buffer_1.Buffer.from([43, 129, 4, 0, 35]); +const secp256k1 = buffer_1.Buffer.from([43, 129, 4, 0, 10]); +exports.weakMap = new WeakMap(); +const namedCurveToJOSE = (namedCurve) => { + switch (namedCurve) { + case 'prime256v1': + return 'P-256'; + case 'secp384r1': + return 'P-384'; + case 'secp521r1': + return 'P-521'; + case 'secp256k1': + return 'secp256k1'; + default: + throw new errors_js_1.JOSENotSupported('Unsupported key curve for this operation'); + } +}; +const getNamedCurve = (kee, raw) => { + var _a; + let key; + if ((0, webcrypto_js_1.isCryptoKey)(kee)) { + key = crypto_1.KeyObject.from(kee); + } + else if ((0, is_key_object_js_1.default)(kee)) { + key = kee; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(kee, ...is_key_like_js_1.types)); + } + if (key.type === 'secret') { + throw new TypeError('only "private" or "public" type keys can be used for this operation'); + } + switch (key.asymmetricKeyType) { + case 'ed25519': + case 'ed448': + return `Ed${key.asymmetricKeyType.slice(2)}`; + case 'x25519': + case 'x448': + return `X${key.asymmetricKeyType.slice(1)}`; + case 'ec': { + if (exports.weakMap.has(key)) { + return exports.weakMap.get(key); + } + let namedCurve = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.namedCurve; + if (!namedCurve && key.type === 'private') { + namedCurve = getNamedCurve((0, crypto_1.createPublicKey)(key), true); + } + else if (!namedCurve) { + const buf = key.export({ format: 'der', type: 'spki' }); + const i = buf[1] < 128 ? 14 : 15; + const len = buf[i]; + const curveOid = buf.slice(i + 1, i + 1 + len); + if (curveOid.equals(p256)) { + namedCurve = 'prime256v1'; + } + else if (curveOid.equals(p384)) { + namedCurve = 'secp384r1'; + } + else if (curveOid.equals(p521)) { + namedCurve = 'secp521r1'; + } + else if (curveOid.equals(secp256k1)) { + namedCurve = 'secp256k1'; + } + else { + throw new errors_js_1.JOSENotSupported('Unsupported key curve for this operation'); + } + } + if (raw) + return namedCurve; + const curve = namedCurveToJOSE(namedCurve); + exports.weakMap.set(key, curve); + return curve; + } + default: + throw new TypeError('Invalid asymmetric key type for this operation'); + } +}; +function setCurve(keyObject, curve) { + exports.weakMap.set(keyObject, curve); +} +exports.setCurve = setCurve; +exports.default = getNamedCurve; diff --git a/dist/node/cjs/runtime/get_sign_verify_key.js b/dist/node/cjs/runtime/get_sign_verify_key.js new file mode 100644 index 0000000000..fea98c71d5 --- /dev/null +++ b/dist/node/cjs/runtime/get_sign_verify_key.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const webcrypto_js_1 = require("./webcrypto.js"); +const crypto_key_js_1 = require("../lib/crypto_key.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +function getSignVerifyKey(alg, key, usage) { + if (key instanceof Uint8Array) { + if (!alg.startsWith('HS')) { + throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types)); + } + return (0, crypto_1.createSecretKey)(key); + } + if (key instanceof crypto_1.KeyObject) { + return key; + } + if ((0, webcrypto_js_1.isCryptoKey)(key)) { + (0, crypto_key_js_1.checkSigCryptoKey)(key, alg, usage); + return crypto_1.KeyObject.from(key); + } + throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); +} +exports.default = getSignVerifyKey; diff --git a/dist/node/cjs/runtime/hmac_digest.js b/dist/node/cjs/runtime/hmac_digest.js new file mode 100644 index 0000000000..c3935124c7 --- /dev/null +++ b/dist/node/cjs/runtime/hmac_digest.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const errors_js_1 = require("../util/errors.js"); +function hmacDigest(alg) { + switch (alg) { + case 'HS256': + return 'sha256'; + case 'HS384': + return 'sha384'; + case 'HS512': + return 'sha512'; + default: + throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} +exports.default = hmacDigest; diff --git a/dist/node/cjs/runtime/is_key_like.js b/dist/node/cjs/runtime/is_key_like.js new file mode 100644 index 0000000000..cd157df0a3 --- /dev/null +++ b/dist/node/cjs/runtime/is_key_like.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.types = void 0; +const webcrypto_js_1 = require("./webcrypto.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +exports.default = (key) => (0, is_key_object_js_1.default)(key) || (0, webcrypto_js_1.isCryptoKey)(key); +const types = ['KeyObject']; +exports.types = types; +if (globalThis.CryptoKey || (webcrypto_js_1.default === null || webcrypto_js_1.default === void 0 ? void 0 : webcrypto_js_1.default.CryptoKey)) { + types.push('CryptoKey'); +} diff --git a/dist/node/cjs/runtime/is_key_object.js b/dist/node/cjs/runtime/is_key_object.js new file mode 100644 index 0000000000..54b02cca1b --- /dev/null +++ b/dist/node/cjs/runtime/is_key_object.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const util = require("util"); +exports.default = util.types.isKeyObject + ? (obj) => util.types.isKeyObject(obj) + : (obj) => obj != null && obj instanceof crypto_1.KeyObject; diff --git a/dist/node/cjs/runtime/jwk_to_key.js b/dist/node/cjs/runtime/jwk_to_key.js new file mode 100644 index 0000000000..8a3ead7800 --- /dev/null +++ b/dist/node/cjs/runtime/jwk_to_key.js @@ -0,0 +1,118 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const buffer_1 = require("buffer"); +const crypto_1 = require("crypto"); +const base64url_js_1 = require("./base64url.js"); +const errors_js_1 = require("../util/errors.js"); +const get_named_curve_js_1 = require("./get_named_curve.js"); +const check_modulus_length_js_1 = require("./check_modulus_length.js"); +const asn1_sequence_encoder_js_1 = require("./asn1_sequence_encoder.js"); +const flags_js_1 = require("./flags.js"); +const parse = (jwk) => { + if (flags_js_1.jwkImport && jwk.kty !== 'oct') { + return jwk.d + ? (0, crypto_1.createPrivateKey)({ format: 'jwk', key: jwk }) + : (0, crypto_1.createPublicKey)({ format: 'jwk', key: jwk }); + } + switch (jwk.kty) { + case 'oct': { + return (0, crypto_1.createSecretKey)((0, base64url_js_1.decode)(jwk.k)); + } + case 'RSA': { + const enc = new asn1_sequence_encoder_js_1.default(); + const isPrivate = jwk.d !== undefined; + const modulus = buffer_1.Buffer.from(jwk.n, 'base64'); + const exponent = buffer_1.Buffer.from(jwk.e, 'base64'); + if (isPrivate) { + enc.zero(); + enc.unsignedInteger(modulus); + enc.unsignedInteger(exponent); + enc.unsignedInteger(buffer_1.Buffer.from(jwk.d, 'base64')); + enc.unsignedInteger(buffer_1.Buffer.from(jwk.p, 'base64')); + enc.unsignedInteger(buffer_1.Buffer.from(jwk.q, 'base64')); + enc.unsignedInteger(buffer_1.Buffer.from(jwk.dp, 'base64')); + enc.unsignedInteger(buffer_1.Buffer.from(jwk.dq, 'base64')); + enc.unsignedInteger(buffer_1.Buffer.from(jwk.qi, 'base64')); + } + else { + enc.unsignedInteger(modulus); + enc.unsignedInteger(exponent); + } + const der = enc.end(); + const createInput = { + key: der, + format: 'der', + type: 'pkcs1', + }; + const keyObject = isPrivate ? (0, crypto_1.createPrivateKey)(createInput) : (0, crypto_1.createPublicKey)(createInput); + (0, check_modulus_length_js_1.setModulusLength)(keyObject, modulus.length << 3); + return keyObject; + } + case 'EC': { + const enc = new asn1_sequence_encoder_js_1.default(); + const isPrivate = jwk.d !== undefined; + const pub = buffer_1.Buffer.concat([ + buffer_1.Buffer.alloc(1, 4), + buffer_1.Buffer.from(jwk.x, 'base64'), + buffer_1.Buffer.from(jwk.y, 'base64'), + ]); + if (isPrivate) { + enc.zero(); + const enc$1 = new asn1_sequence_encoder_js_1.default(); + enc$1.oidFor('ecPublicKey'); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + const enc$2 = new asn1_sequence_encoder_js_1.default(); + enc$2.one(); + enc$2.octStr(buffer_1.Buffer.from(jwk.d, 'base64')); + const enc$3 = new asn1_sequence_encoder_js_1.default(); + enc$3.bitStr(pub); + const f2 = enc$3.end(buffer_1.Buffer.from([0xa1])); + enc$2.add(f2); + const f = enc$2.end(); + const enc$4 = new asn1_sequence_encoder_js_1.default(); + enc$4.add(f); + const f3 = enc$4.end(buffer_1.Buffer.from([0x04])); + enc.add(f3); + const der = enc.end(); + const keyObject = (0, crypto_1.createPrivateKey)({ key: der, format: 'der', type: 'pkcs8' }); + (0, get_named_curve_js_1.setCurve)(keyObject, jwk.crv); + return keyObject; + } + const enc$1 = new asn1_sequence_encoder_js_1.default(); + enc$1.oidFor('ecPublicKey'); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + enc.bitStr(pub); + const der = enc.end(); + const keyObject = (0, crypto_1.createPublicKey)({ key: der, format: 'der', type: 'spki' }); + (0, get_named_curve_js_1.setCurve)(keyObject, jwk.crv); + return keyObject; + } + case 'OKP': { + const enc = new asn1_sequence_encoder_js_1.default(); + const isPrivate = jwk.d !== undefined; + if (isPrivate) { + enc.zero(); + const enc$1 = new asn1_sequence_encoder_js_1.default(); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + const enc$2 = new asn1_sequence_encoder_js_1.default(); + enc$2.octStr(buffer_1.Buffer.from(jwk.d, 'base64')); + const f = enc$2.end(buffer_1.Buffer.from([0x04])); + enc.add(f); + const der = enc.end(); + return (0, crypto_1.createPrivateKey)({ key: der, format: 'der', type: 'pkcs8' }); + } + const enc$1 = new asn1_sequence_encoder_js_1.default(); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + enc.bitStr(buffer_1.Buffer.from(jwk.x, 'base64')); + const der = enc.end(); + return (0, crypto_1.createPublicKey)({ key: der, format: 'der', type: 'spki' }); + } + default: + throw new errors_js_1.JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); + } +}; +exports.default = parse; diff --git a/dist/node/cjs/runtime/key_to_jwk.js b/dist/node/cjs/runtime/key_to_jwk.js new file mode 100644 index 0000000000..6ee2127570 --- /dev/null +++ b/dist/node/cjs/runtime/key_to_jwk.js @@ -0,0 +1,160 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const base64url_js_1 = require("./base64url.js"); +const asn1_sequence_decoder_js_1 = require("./asn1_sequence_decoder.js"); +const errors_js_1 = require("../util/errors.js"); +const get_named_curve_js_1 = require("./get_named_curve.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +const flags_js_1 = require("./flags.js"); +const keyToJWK = (key) => { + let keyObject; + if ((0, webcrypto_js_1.isCryptoKey)(key)) { + if (!key.extractable) { + throw new TypeError('CryptoKey is not extractable'); + } + keyObject = crypto_1.KeyObject.from(key); + } + else if ((0, is_key_object_js_1.default)(key)) { + keyObject = key; + } + else if (key instanceof Uint8Array) { + return { + kty: 'oct', + k: (0, base64url_js_1.encode)(key), + }; + } + else { + throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); + } + if (flags_js_1.jwkExport) { + if (keyObject.type !== 'secret' && + !['rsa', 'ec', 'ed25519', 'x25519', 'ed448', 'x448'].includes(keyObject.asymmetricKeyType)) { + throw new errors_js_1.JOSENotSupported('Unsupported key asymmetricKeyType'); + } + return keyObject.export({ format: 'jwk' }); + } + switch (keyObject.type) { + case 'secret': + return { + kty: 'oct', + k: (0, base64url_js_1.encode)(keyObject.export()), + }; + case 'private': + case 'public': { + switch (keyObject.asymmetricKeyType) { + case 'rsa': { + const der = keyObject.export({ format: 'der', type: 'pkcs1' }); + const dec = new asn1_sequence_decoder_js_1.default(der); + if (keyObject.type === 'private') { + dec.unsignedInteger(); + } + const n = (0, base64url_js_1.encode)(dec.unsignedInteger()); + const e = (0, base64url_js_1.encode)(dec.unsignedInteger()); + let jwk; + if (keyObject.type === 'private') { + jwk = { + d: (0, base64url_js_1.encode)(dec.unsignedInteger()), + p: (0, base64url_js_1.encode)(dec.unsignedInteger()), + q: (0, base64url_js_1.encode)(dec.unsignedInteger()), + dp: (0, base64url_js_1.encode)(dec.unsignedInteger()), + dq: (0, base64url_js_1.encode)(dec.unsignedInteger()), + qi: (0, base64url_js_1.encode)(dec.unsignedInteger()), + }; + } + dec.end(); + return { kty: 'RSA', n, e, ...jwk }; + } + case 'ec': { + const crv = (0, get_named_curve_js_1.default)(keyObject); + let len; + let offset; + let correction; + switch (crv) { + case 'secp256k1': + len = 64; + offset = 31 + 2; + correction = -1; + break; + case 'P-256': + len = 64; + offset = 34 + 2; + correction = -1; + break; + case 'P-384': + len = 96; + offset = 33 + 2; + correction = -3; + break; + case 'P-521': + len = 132; + offset = 33 + 2; + correction = -3; + break; + default: + throw new errors_js_1.JOSENotSupported('Unsupported curve'); + } + if (keyObject.type === 'public') { + const der = keyObject.export({ type: 'spki', format: 'der' }); + return { + kty: 'EC', + crv, + x: (0, base64url_js_1.encode)(der.subarray(-len, -len / 2)), + y: (0, base64url_js_1.encode)(der.subarray(-len / 2)), + }; + } + const der = keyObject.export({ type: 'pkcs8', format: 'der' }); + if (der.length < 100) { + offset += correction; + } + return { + ...keyToJWK((0, crypto_1.createPublicKey)(keyObject)), + d: (0, base64url_js_1.encode)(der.subarray(offset, offset + len / 2)), + }; + } + case 'ed25519': + case 'x25519': { + const crv = (0, get_named_curve_js_1.default)(keyObject); + if (keyObject.type === 'public') { + const der = keyObject.export({ type: 'spki', format: 'der' }); + return { + kty: 'OKP', + crv, + x: (0, base64url_js_1.encode)(der.subarray(-32)), + }; + } + const der = keyObject.export({ type: 'pkcs8', format: 'der' }); + return { + ...keyToJWK((0, crypto_1.createPublicKey)(keyObject)), + d: (0, base64url_js_1.encode)(der.subarray(-32)), + }; + } + case 'ed448': + case 'x448': { + const crv = (0, get_named_curve_js_1.default)(keyObject); + if (keyObject.type === 'public') { + const der = keyObject.export({ type: 'spki', format: 'der' }); + return { + kty: 'OKP', + crv, + x: (0, base64url_js_1.encode)(der.subarray(crv === 'Ed448' ? -57 : -56)), + }; + } + const der = keyObject.export({ type: 'pkcs8', format: 'der' }); + return { + ...keyToJWK((0, crypto_1.createPublicKey)(keyObject)), + d: (0, base64url_js_1.encode)(der.subarray(crv === 'Ed448' ? -57 : -56)), + }; + } + default: + throw new errors_js_1.JOSENotSupported('Unsupported key asymmetricKeyType'); + } + } + default: + throw new errors_js_1.JOSENotSupported('Unsupported key type'); + } +}; +exports.default = keyToJWK; diff --git a/dist/node/cjs/runtime/node_key.js b/dist/node/cjs/runtime/node_key.js new file mode 100644 index 0000000000..df67562ab4 --- /dev/null +++ b/dist/node/cjs/runtime/node_key.js @@ -0,0 +1,78 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const get_named_curve_js_1 = require("./get_named_curve.js"); +const errors_js_1 = require("../util/errors.js"); +const check_modulus_length_js_1 = require("./check_modulus_length.js"); +const flags_js_1 = require("./flags.js"); +const PSS = { + padding: crypto_1.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto_1.constants.RSA_PSS_SALTLEN_DIGEST, +}; +const ecCurveAlgMap = new Map([ + ['ES256', 'P-256'], + ['ES256K', 'secp256k1'], + ['ES384', 'P-384'], + ['ES512', 'P-521'], +]); +function keyForCrypto(alg, key) { + switch (alg) { + case 'EdDSA': + if (!['ed25519', 'ed448'].includes(key.asymmetricKeyType)) { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ed25519 or ed448'); + } + return key; + case 'RS256': + case 'RS384': + case 'RS512': + if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); + } + (0, check_modulus_length_js_1.default)(key, alg); + return key; + case flags_js_1.rsaPssParams && 'PS256': + case flags_js_1.rsaPssParams && 'PS384': + case flags_js_1.rsaPssParams && 'PS512': + if (key.asymmetricKeyType === 'rsa-pss') { + const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails; + const length = parseInt(alg.slice(-3), 10); + if (hashAlgorithm !== undefined && + (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm)) { + throw new TypeError(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${alg}`); + } + if (saltLength !== undefined && saltLength > length >> 3) { + throw new TypeError(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of "alg" ${alg}`); + } + } + else if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa or rsa-pss'); + } + (0, check_modulus_length_js_1.default)(key, alg); + return { key, ...PSS }; + case !flags_js_1.rsaPssParams && 'PS256': + case !flags_js_1.rsaPssParams && 'PS384': + case !flags_js_1.rsaPssParams && 'PS512': + if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); + } + (0, check_modulus_length_js_1.default)(key, alg); + return { key, ...PSS }; + case 'ES256': + case 'ES256K': + case 'ES384': + case 'ES512': { + if (key.asymmetricKeyType !== 'ec') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ec'); + } + const actual = (0, get_named_curve_js_1.default)(key); + const expected = ecCurveAlgMap.get(alg); + if (actual !== expected) { + throw new TypeError(`Invalid key curve for the algorithm, its curve must be ${expected}, got ${actual}`); + } + return { dsaEncoding: 'ieee-p1363', key }; + } + default: + throw new errors_js_1.JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} +exports.default = keyForCrypto; diff --git a/dist/node/cjs/runtime/pbes2kw.js b/dist/node/cjs/runtime/pbes2kw.js new file mode 100644 index 0000000000..8298b0e7d8 --- /dev/null +++ b/dist/node/cjs/runtime/pbes2kw.js @@ -0,0 +1,48 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decrypt = exports.encrypt = void 0; +const util_1 = require("util"); +const crypto_1 = require("crypto"); +const random_js_1 = require("./random.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const base64url_js_1 = require("./base64url.js"); +const aeskw_js_1 = require("./aeskw.js"); +const check_p2s_js_1 = require("../lib/check_p2s.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const crypto_key_js_1 = require("../lib/crypto_key.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +const pbkdf2 = (0, util_1.promisify)(crypto_1.pbkdf2); +function getPassword(key, alg) { + if ((0, is_key_object_js_1.default)(key)) { + return key.export(); + } + if (key instanceof Uint8Array) { + return key; + } + if ((0, webcrypto_js_1.isCryptoKey)(key)) { + (0, crypto_key_js_1.checkEncCryptoKey)(key, alg, 'deriveBits', 'deriveKey'); + return crypto_1.KeyObject.from(key).export(); + } + throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array')); +} +const encrypt = async (alg, key, cek, p2c = 2048, p2s = (0, random_js_1.default)(new Uint8Array(16))) => { + (0, check_p2s_js_1.default)(p2s); + const salt = (0, buffer_utils_js_1.p2s)(alg, p2s); + const keylen = parseInt(alg.slice(13, 16), 10) >> 3; + const password = getPassword(key, alg); + const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); + const encryptedKey = await (0, aeskw_js_1.wrap)(alg.slice(-6), derivedKey, cek); + return { encryptedKey, p2c, p2s: (0, base64url_js_1.encode)(p2s) }; +}; +exports.encrypt = encrypt; +const decrypt = async (alg, key, encryptedKey, p2c, p2s) => { + (0, check_p2s_js_1.default)(p2s); + const salt = (0, buffer_utils_js_1.p2s)(alg, p2s); + const keylen = parseInt(alg.slice(13, 16), 10) >> 3; + const password = getPassword(key, alg); + const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); + return (0, aeskw_js_1.unwrap)(alg.slice(-6), derivedKey, encryptedKey); +}; +exports.decrypt = decrypt; diff --git a/dist/node/cjs/runtime/random.js b/dist/node/cjs/runtime/random.js new file mode 100644 index 0000000000..459da2bb08 --- /dev/null +++ b/dist/node/cjs/runtime/random.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; +var crypto_1 = require("crypto"); +Object.defineProperty(exports, "default", { enumerable: true, get: function () { return crypto_1.randomFillSync; } }); diff --git a/dist/node/cjs/runtime/rsaes.js b/dist/node/cjs/runtime/rsaes.js new file mode 100644 index 0000000000..4e625226b8 --- /dev/null +++ b/dist/node/cjs/runtime/rsaes.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decrypt = exports.encrypt = void 0; +const crypto_1 = require("crypto"); +const check_modulus_length_js_1 = require("./check_modulus_length.js"); +const webcrypto_js_1 = require("./webcrypto.js"); +const crypto_key_js_1 = require("../lib/crypto_key.js"); +const is_key_object_js_1 = require("./is_key_object.js"); +const invalid_key_input_js_1 = require("../lib/invalid_key_input.js"); +const is_key_like_js_1 = require("./is_key_like.js"); +const checkKey = (key, alg) => { + if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); + } + (0, check_modulus_length_js_1.default)(key, alg); +}; +const resolvePadding = (alg) => { + switch (alg) { + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + return crypto_1.constants.RSA_PKCS1_OAEP_PADDING; + case 'RSA1_5': + return crypto_1.constants.RSA_PKCS1_PADDING; + default: + return undefined; + } +}; +const resolveOaepHash = (alg) => { + switch (alg) { + case 'RSA-OAEP': + return 'sha1'; + case 'RSA-OAEP-256': + return 'sha256'; + case 'RSA-OAEP-384': + return 'sha384'; + case 'RSA-OAEP-512': + return 'sha512'; + default: + return undefined; + } +}; +function ensureKeyObject(key, alg, ...usages) { + if ((0, is_key_object_js_1.default)(key)) { + return key; + } + if ((0, webcrypto_js_1.isCryptoKey)(key)) { + (0, crypto_key_js_1.checkEncCryptoKey)(key, alg, ...usages); + return crypto_1.KeyObject.from(key); + } + throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types)); +} +const encrypt = (alg, key, cek) => { + const padding = resolvePadding(alg); + const oaepHash = resolveOaepHash(alg); + const keyObject = ensureKeyObject(key, alg, 'wrapKey', 'encrypt'); + checkKey(keyObject, alg); + return (0, crypto_1.publicEncrypt)({ key: keyObject, oaepHash, padding }, cek); +}; +exports.encrypt = encrypt; +const decrypt = (alg, key, encryptedKey) => { + const padding = resolvePadding(alg); + const oaepHash = resolveOaepHash(alg); + const keyObject = ensureKeyObject(key, alg, 'unwrapKey', 'decrypt'); + checkKey(keyObject, alg); + return (0, crypto_1.privateDecrypt)({ key: keyObject, oaepHash, padding }, encryptedKey); +}; +exports.decrypt = decrypt; diff --git a/dist/node/cjs/runtime/sign.js b/dist/node/cjs/runtime/sign.js new file mode 100644 index 0000000000..cc19300d9e --- /dev/null +++ b/dist/node/cjs/runtime/sign.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto = require("crypto"); +const util_1 = require("util"); +const dsa_digest_js_1 = require("./dsa_digest.js"); +const hmac_digest_js_1 = require("./hmac_digest.js"); +const node_key_js_1 = require("./node_key.js"); +const get_sign_verify_key_js_1 = require("./get_sign_verify_key.js"); +let oneShotSign; +if (crypto.sign.length > 3) { + oneShotSign = (0, util_1.promisify)(crypto.sign); +} +else { + oneShotSign = crypto.sign; +} +const sign = async (alg, key, data) => { + const keyObject = (0, get_sign_verify_key_js_1.default)(alg, key, 'sign'); + if (alg.startsWith('HS')) { + const hmac = crypto.createHmac((0, hmac_digest_js_1.default)(alg), keyObject); + hmac.update(data); + return hmac.digest(); + } + return oneShotSign((0, dsa_digest_js_1.default)(alg), data, (0, node_key_js_1.default)(alg, keyObject)); +}; +exports.default = sign; diff --git a/dist/node/cjs/runtime/timing_safe_equal.js b/dist/node/cjs/runtime/timing_safe_equal.js new file mode 100644 index 0000000000..e1e4ef6100 --- /dev/null +++ b/dist/node/cjs/runtime/timing_safe_equal.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const timingSafeEqual = crypto_1.timingSafeEqual; +exports.default = timingSafeEqual; diff --git a/dist/node/cjs/runtime/verify.js b/dist/node/cjs/runtime/verify.js new file mode 100644 index 0000000000..c9a1549020 --- /dev/null +++ b/dist/node/cjs/runtime/verify.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto = require("crypto"); +const util_1 = require("util"); +const dsa_digest_js_1 = require("./dsa_digest.js"); +const node_key_js_1 = require("./node_key.js"); +const sign_js_1 = require("./sign.js"); +const get_sign_verify_key_js_1 = require("./get_sign_verify_key.js"); +const flags_js_1 = require("./flags.js"); +let oneShotVerify; +if (crypto.verify.length > 4 && flags_js_1.oneShotCallback) { + oneShotVerify = (0, util_1.promisify)(crypto.verify); +} +else { + oneShotVerify = crypto.verify; +} +const verify = async (alg, key, signature, data) => { + const keyObject = (0, get_sign_verify_key_js_1.default)(alg, key, 'verify'); + if (alg.startsWith('HS')) { + const expected = await (0, sign_js_1.default)(alg, keyObject, data); + const actual = signature; + try { + return crypto.timingSafeEqual(actual, expected); + } + catch { + return false; + } + } + const algorithm = (0, dsa_digest_js_1.default)(alg); + const keyInput = (0, node_key_js_1.default)(alg, keyObject); + try { + return await oneShotVerify(algorithm, data, keyInput, signature); + } + catch { + return false; + } +}; +exports.default = verify; diff --git a/dist/node/cjs/runtime/webcrypto.js b/dist/node/cjs/runtime/webcrypto.js new file mode 100644 index 0000000000..8a3e72e06e --- /dev/null +++ b/dist/node/cjs/runtime/webcrypto.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isCryptoKey = void 0; +const crypto = require("crypto"); +const util = require("util"); +const webcrypto = crypto.webcrypto; +exports.default = webcrypto; +exports.isCryptoKey = util.types.isCryptoKey + ? (key) => util.types.isCryptoKey(key) + : + (key) => false; diff --git a/dist/node/cjs/runtime/zlib.js b/dist/node/cjs/runtime/zlib.js new file mode 100644 index 0000000000..7dcfddf49b --- /dev/null +++ b/dist/node/cjs/runtime/zlib.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.deflate = exports.inflate = void 0; +const util_1 = require("util"); +const zlib_1 = require("zlib"); +const inflateRaw = (0, util_1.promisify)(zlib_1.inflateRaw); +const deflateRaw = (0, util_1.promisify)(zlib_1.deflateRaw); +const inflate = (input) => inflateRaw(input); +exports.inflate = inflate; +const deflate = (input) => deflateRaw(input); +exports.deflate = deflate; diff --git a/dist/node/cjs/util/base64url.js b/dist/node/cjs/util/base64url.js new file mode 100644 index 0000000000..4d383b5167 --- /dev/null +++ b/dist/node/cjs/util/base64url.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decode = exports.encode = void 0; +const base64url = require("../runtime/base64url.js"); +exports.encode = base64url.encode; +exports.decode = base64url.decode; diff --git a/dist/node/cjs/util/decode_jwt.js b/dist/node/cjs/util/decode_jwt.js new file mode 100644 index 0000000000..f5b6122e46 --- /dev/null +++ b/dist/node/cjs/util/decode_jwt.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decodeJwt = void 0; +const base64url_js_1 = require("./base64url.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const is_object_js_1 = require("../lib/is_object.js"); +const errors_js_1 = require("./errors.js"); +function decodeJwt(jwt) { + if (typeof jwt !== 'string') + throw new errors_js_1.JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string'); + const { 1: payload, length } = jwt.split('.'); + if (length === 5) + throw new errors_js_1.JWTInvalid('Only JWTs using Compact JWS serialization can be decoded'); + if (length !== 3) + throw new errors_js_1.JWTInvalid('Invalid JWT'); + if (!payload) + throw new errors_js_1.JWTInvalid('JWTs must contain a payload'); + let decoded; + try { + decoded = (0, base64url_js_1.decode)(payload); + } + catch { + throw new errors_js_1.JWTInvalid('Failed to parse the base64url encoded payload'); + } + let result; + try { + result = JSON.parse(buffer_utils_js_1.decoder.decode(decoded)); + } + catch { + throw new errors_js_1.JWTInvalid('Failed to parse the decoded payload as JSON'); + } + if (!(0, is_object_js_1.default)(result)) + throw new errors_js_1.JWTInvalid('Invalid JWT Claims Set'); + return result; +} +exports.decodeJwt = decodeJwt; diff --git a/dist/node/cjs/util/decode_protected_header.js b/dist/node/cjs/util/decode_protected_header.js new file mode 100644 index 0000000000..601ebb7297 --- /dev/null +++ b/dist/node/cjs/util/decode_protected_header.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decodeProtectedHeader = void 0; +const base64url_js_1 = require("./base64url.js"); +const buffer_utils_js_1 = require("../lib/buffer_utils.js"); +const is_object_js_1 = require("../lib/is_object.js"); +function decodeProtectedHeader(token) { + let protectedB64u; + if (typeof token === 'string') { + const parts = token.split('.'); + if (parts.length === 3 || parts.length === 5) { + ; + [protectedB64u] = parts; + } + } + else if (typeof token === 'object' && token) { + if ('protected' in token) { + protectedB64u = token.protected; + } + else { + throw new TypeError('Token does not contain a Protected Header'); + } + } + try { + if (typeof protectedB64u !== 'string' || !protectedB64u) { + throw new Error(); + } + const result = JSON.parse(buffer_utils_js_1.decoder.decode((0, base64url_js_1.decode)(protectedB64u))); + if (!(0, is_object_js_1.default)(result)) { + throw new Error(); + } + return result; + } + catch { + throw new TypeError('Invalid Token or Protected Header formatting'); + } +} +exports.decodeProtectedHeader = decodeProtectedHeader; diff --git a/dist/node/cjs/util/errors.js b/dist/node/cjs/util/errors.js new file mode 100644 index 0000000000..5ec68a5b12 --- /dev/null +++ b/dist/node/cjs/util/errors.js @@ -0,0 +1,166 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.JWSSignatureVerificationFailed = exports.JWKSTimeout = exports.JWKSMultipleMatchingKeys = exports.JWKSNoMatchingKey = exports.JWKSInvalid = exports.JWKInvalid = exports.JWTInvalid = exports.JWSInvalid = exports.JWEInvalid = exports.JWEDecryptionFailed = exports.JOSENotSupported = exports.JOSEAlgNotAllowed = exports.JWTExpired = exports.JWTClaimValidationFailed = exports.JOSEError = void 0; +class JOSEError extends Error { + static get code() { + return 'ERR_JOSE_GENERIC'; + } + constructor(message) { + var _a; + super(message); + this.code = 'ERR_JOSE_GENERIC'; + this.name = this.constructor.name; + (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); + } +} +exports.JOSEError = JOSEError; +class JWTClaimValidationFailed extends JOSEError { + static get code() { + return 'ERR_JWT_CLAIM_VALIDATION_FAILED'; + } + constructor(message, claim = 'unspecified', reason = 'unspecified') { + super(message); + this.code = 'ERR_JWT_CLAIM_VALIDATION_FAILED'; + this.claim = claim; + this.reason = reason; + } +} +exports.JWTClaimValidationFailed = JWTClaimValidationFailed; +class JWTExpired extends JOSEError { + static get code() { + return 'ERR_JWT_EXPIRED'; + } + constructor(message, claim = 'unspecified', reason = 'unspecified') { + super(message); + this.code = 'ERR_JWT_EXPIRED'; + this.claim = claim; + this.reason = reason; + } +} +exports.JWTExpired = JWTExpired; +class JOSEAlgNotAllowed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JOSE_ALG_NOT_ALLOWED'; + } + static get code() { + return 'ERR_JOSE_ALG_NOT_ALLOWED'; + } +} +exports.JOSEAlgNotAllowed = JOSEAlgNotAllowed; +class JOSENotSupported extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JOSE_NOT_SUPPORTED'; + } + static get code() { + return 'ERR_JOSE_NOT_SUPPORTED'; + } +} +exports.JOSENotSupported = JOSENotSupported; +class JWEDecryptionFailed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWE_DECRYPTION_FAILED'; + this.message = 'decryption operation failed'; + } + static get code() { + return 'ERR_JWE_DECRYPTION_FAILED'; + } +} +exports.JWEDecryptionFailed = JWEDecryptionFailed; +class JWEInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWE_INVALID'; + } + static get code() { + return 'ERR_JWE_INVALID'; + } +} +exports.JWEInvalid = JWEInvalid; +class JWSInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWS_INVALID'; + } + static get code() { + return 'ERR_JWS_INVALID'; + } +} +exports.JWSInvalid = JWSInvalid; +class JWTInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWT_INVALID'; + } + static get code() { + return 'ERR_JWT_INVALID'; + } +} +exports.JWTInvalid = JWTInvalid; +class JWKInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWK_INVALID'; + } + static get code() { + return 'ERR_JWK_INVALID'; + } +} +exports.JWKInvalid = JWKInvalid; +class JWKSInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_INVALID'; + } + static get code() { + return 'ERR_JWKS_INVALID'; + } +} +exports.JWKSInvalid = JWKSInvalid; +class JWKSNoMatchingKey extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_NO_MATCHING_KEY'; + this.message = 'no applicable key found in the JSON Web Key Set'; + } + static get code() { + return 'ERR_JWKS_NO_MATCHING_KEY'; + } +} +exports.JWKSNoMatchingKey = JWKSNoMatchingKey; +class JWKSMultipleMatchingKeys extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; + this.message = 'multiple matching keys found in the JSON Web Key Set'; + } + static get code() { + return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; + } +} +exports.JWKSMultipleMatchingKeys = JWKSMultipleMatchingKeys; +Symbol.asyncIterator; +class JWKSTimeout extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_TIMEOUT'; + this.message = 'request timed out'; + } + static get code() { + return 'ERR_JWKS_TIMEOUT'; + } +} +exports.JWKSTimeout = JWKSTimeout; +class JWSSignatureVerificationFailed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; + this.message = 'signature verification failed'; + } + static get code() { + return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; + } +} +exports.JWSSignatureVerificationFailed = JWSSignatureVerificationFailed; diff --git a/dist/node/esm/index.js b/dist/node/esm/index.js new file mode 100644 index 0000000000..d2ce09d71a --- /dev/null +++ b/dist/node/esm/index.js @@ -0,0 +1,29 @@ +export { compactDecrypt } from './jwe/compact/decrypt.js'; +export { flattenedDecrypt } from './jwe/flattened/decrypt.js'; +export { generalDecrypt } from './jwe/general/decrypt.js'; +export { GeneralEncrypt } from './jwe/general/encrypt.js'; +export { compactVerify } from './jws/compact/verify.js'; +export { flattenedVerify } from './jws/flattened/verify.js'; +export { generalVerify } from './jws/general/verify.js'; +export { jwtVerify } from './jwt/verify.js'; +export { jwtDecrypt } from './jwt/decrypt.js'; +export { CompactEncrypt } from './jwe/compact/encrypt.js'; +export { FlattenedEncrypt } from './jwe/flattened/encrypt.js'; +export { CompactSign } from './jws/compact/sign.js'; +export { FlattenedSign } from './jws/flattened/sign.js'; +export { GeneralSign } from './jws/general/sign.js'; +export { SignJWT } from './jwt/sign.js'; +export { EncryptJWT } from './jwt/encrypt.js'; +export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.js'; +export { EmbeddedJWK } from './jwk/embedded.js'; +export { createLocalJWKSet } from './jwks/local.js'; +export { createRemoteJWKSet } from './jwks/remote.js'; +export { UnsecuredJWT } from './jwt/unsecured.js'; +export { exportPKCS8, exportSPKI, exportJWK } from './key/export.js'; +export { importSPKI, importPKCS8, importX509, importJWK } from './key/import.js'; +export { decodeProtectedHeader } from './util/decode_protected_header.js'; +export { decodeJwt } from './util/decode_jwt.js'; +export * as errors from './util/errors.js'; +export { generateKeyPair } from './key/generate_key_pair.js'; +export { generateSecret } from './key/generate_secret.js'; +export * as base64url from './util/base64url.js'; diff --git a/dist/node/esm/jwe/compact/decrypt.js b/dist/node/esm/jwe/compact/decrypt.js new file mode 100644 index 0000000000..129aeb6e39 --- /dev/null +++ b/dist/node/esm/jwe/compact/decrypt.js @@ -0,0 +1,27 @@ +import { flattenedDecrypt } from '../flattened/decrypt.js'; +import { JWEInvalid } from '../../util/errors.js'; +import { decoder } from '../../lib/buffer_utils.js'; +export async function compactDecrypt(jwe, key, options) { + if (jwe instanceof Uint8Array) { + jwe = decoder.decode(jwe); + } + if (typeof jwe !== 'string') { + throw new JWEInvalid('Compact JWE must be a string or Uint8Array'); + } + const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.'); + if (length !== 5) { + throw new JWEInvalid('Invalid Compact JWE'); + } + const decrypted = await flattenedDecrypt({ + ciphertext, + iv: (iv || undefined), + protected: protectedHeader || undefined, + tag: (tag || undefined), + encrypted_key: encryptedKey || undefined, + }, key, options); + const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: decrypted.key }; + } + return result; +} diff --git a/dist/node/esm/jwe/compact/encrypt.js b/dist/node/esm/jwe/compact/encrypt.js new file mode 100644 index 0000000000..e689139465 --- /dev/null +++ b/dist/node/esm/jwe/compact/encrypt.js @@ -0,0 +1,26 @@ +import { FlattenedEncrypt } from '../flattened/encrypt.js'; +export class CompactEncrypt { + constructor(plaintext) { + this._flattened = new FlattenedEncrypt(plaintext); + } + setContentEncryptionKey(cek) { + this._flattened.setContentEncryptionKey(cek); + return this; + } + setInitializationVector(iv) { + this._flattened.setInitializationVector(iv); + return this; + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + setKeyManagementParameters(parameters) { + this._flattened.setKeyManagementParameters(parameters); + return this; + } + async encrypt(key, options) { + const jwe = await this._flattened.encrypt(key, options); + return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.'); + } +} diff --git a/dist/node/esm/jwe/flattened/decrypt.js b/dist/node/esm/jwe/flattened/decrypt.js new file mode 100644 index 0000000000..e918c88954 --- /dev/null +++ b/dist/node/esm/jwe/flattened/decrypt.js @@ -0,0 +1,137 @@ +import { decode as base64url } from '../../runtime/base64url.js'; +import decrypt from '../../runtime/decrypt.js'; +import { inflate } from '../../runtime/zlib.js'; +import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import isObject from '../../lib/is_object.js'; +import decryptKeyManagement from '../../lib/decrypt_key_management.js'; +import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; +import generateCek from '../../lib/cek.js'; +import validateCrit from '../../lib/validate_crit.js'; +import validateAlgorithms from '../../lib/validate_algorithms.js'; +export async function flattenedDecrypt(jwe, key, options) { + var _a; + if (!isObject(jwe)) { + throw new JWEInvalid('Flattened JWE must be an object'); + } + if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) { + throw new JWEInvalid('JOSE Header missing'); + } + if (typeof jwe.iv !== 'string') { + throw new JWEInvalid('JWE Initialization Vector missing or incorrect type'); + } + if (typeof jwe.ciphertext !== 'string') { + throw new JWEInvalid('JWE Ciphertext missing or incorrect type'); + } + if (typeof jwe.tag !== 'string') { + throw new JWEInvalid('JWE Authentication Tag missing or incorrect type'); + } + if (jwe.protected !== undefined && typeof jwe.protected !== 'string') { + throw new JWEInvalid('JWE Protected Header incorrect type'); + } + if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') { + throw new JWEInvalid('JWE Encrypted Key incorrect type'); + } + if (jwe.aad !== undefined && typeof jwe.aad !== 'string') { + throw new JWEInvalid('JWE AAD incorrect type'); + } + if (jwe.header !== undefined && !isObject(jwe.header)) { + throw new JWEInvalid('JWE Shared Unprotected Header incorrect type'); + } + if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) { + throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type'); + } + let parsedProt; + if (jwe.protected) { + try { + const protectedHeader = base64url(jwe.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader)); + } + catch { + throw new JWEInvalid('JWE Protected Header is invalid'); + } + } + if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) { + throw new JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...parsedProt, + ...jwe.header, + ...jwe.unprotected, + }; + validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + if (joseHeader.zip !== undefined) { + if (!parsedProt || !parsedProt.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== 'DEF') { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header'); + } + if (typeof enc !== 'string' || !enc) { + throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header'); + } + const keyManagementAlgorithms = options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms); + const contentEncryptionAlgorithms = options && + validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms); + if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) { + throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed'); + } + let encryptedKey; + if (jwe.encrypted_key !== undefined) { + encryptedKey = base64url(jwe.encrypted_key); + } + let resolvedKey = false; + if (typeof key === 'function') { + key = await key(parsedProt, jwe); + resolvedKey = true; + } + let cek; + try { + cek = await decryptKeyManagement(alg, key, encryptedKey, joseHeader, options); + } + catch (err) { + if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) { + throw err; + } + cek = generateCek(enc); + } + const iv = base64url(jwe.iv); + const tag = base64url(jwe.tag); + const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : ''); + let additionalData; + if (jwe.aad !== undefined) { + additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(jwe.aad)); + } + else { + additionalData = protectedHeader; + } + let plaintext = await decrypt(enc, cek, base64url(jwe.ciphertext), iv, tag, additionalData); + if (joseHeader.zip === 'DEF') { + plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext); + } + const result = { plaintext }; + if (jwe.protected !== undefined) { + result.protectedHeader = parsedProt; + } + if (jwe.aad !== undefined) { + result.additionalAuthenticatedData = base64url(jwe.aad); + } + if (jwe.unprotected !== undefined) { + result.sharedUnprotectedHeader = jwe.unprotected; + } + if (jwe.header !== undefined) { + result.unprotectedHeader = jwe.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} diff --git a/dist/node/esm/jwe/flattened/encrypt.js b/dist/node/esm/jwe/flattened/encrypt.js new file mode 100644 index 0000000000..1e60ecd8c4 --- /dev/null +++ b/dist/node/esm/jwe/flattened/encrypt.js @@ -0,0 +1,175 @@ +import { encode as base64url } from '../../runtime/base64url.js'; +import encrypt from '../../runtime/encrypt.js'; +import { deflate } from '../../runtime/zlib.js'; +import generateIv from '../../lib/iv.js'; +import encryptKeyManagement from '../../lib/encrypt_key_management.js'; +import { JOSENotSupported, JWEInvalid } from '../../util/errors.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; +import validateCrit from '../../lib/validate_crit.js'; +export const unprotected = Symbol(); +export class FlattenedEncrypt { + constructor(plaintext) { + if (!(plaintext instanceof Uint8Array)) { + throw new TypeError('plaintext must be an instance of Uint8Array'); + } + this._plaintext = plaintext; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once'); + } + this._keyManagementParameters = parameters; + return this; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._sharedUnprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once'); + } + this._sharedUnprotectedHeader = sharedUnprotectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once'); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once'); + } + this._iv = iv; + return this; + } + async encrypt(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) { + throw new JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()'); + } + if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) { + throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...this._sharedUnprotectedHeader, + }; + validateCrit(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + if (joseHeader.zip !== 'DEF') { + throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value'); + } + } + const { alg, enc } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (typeof enc !== 'string' || !enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + let encryptedKey; + if (alg === 'dir') { + if (this._cek) { + throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption'); + } + } + else if (alg === 'ECDH-ES') { + if (this._cek) { + throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement'); + } + } + let cek; + { + let parameters; + ({ cek, encryptedKey, parameters } = await encryptKeyManagement(alg, enc, key, this._cek, this._keyManagementParameters)); + if (parameters) { + if (options && unprotected in options) { + if (!this._unprotectedHeader) { + this.setUnprotectedHeader(parameters); + } + else { + this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters }; + } + } + else { + if (!this._protectedHeader) { + this.setProtectedHeader(parameters); + } + else { + this._protectedHeader = { ...this._protectedHeader, ...parameters }; + } + } + } + } + this._iv || (this._iv = generateIv(enc)); + let additionalData; + let protectedHeader; + let aadMember; + if (this._protectedHeader) { + protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); + } + else { + protectedHeader = encoder.encode(''); + } + if (this._aad) { + aadMember = base64url(this._aad); + additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember)); + } + else { + additionalData = protectedHeader; + } + let ciphertext; + let tag; + if (joseHeader.zip === 'DEF') { + const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext); + ({ ciphertext, tag } = await encrypt(enc, deflated, cek, this._iv, additionalData)); + } + else { + ; + ({ ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData)); + } + const jwe = { + ciphertext: base64url(ciphertext), + iv: base64url(this._iv), + tag: base64url(tag), + }; + if (encryptedKey) { + jwe.encrypted_key = base64url(encryptedKey); + } + if (aadMember) { + jwe.aad = aadMember; + } + if (this._protectedHeader) { + jwe.protected = decoder.decode(protectedHeader); + } + if (this._sharedUnprotectedHeader) { + jwe.unprotected = this._sharedUnprotectedHeader; + } + if (this._unprotectedHeader) { + jwe.header = this._unprotectedHeader; + } + return jwe; + } +} diff --git a/dist/node/esm/jwe/general/decrypt.js b/dist/node/esm/jwe/general/decrypt.js new file mode 100644 index 0000000000..659958a8bc --- /dev/null +++ b/dist/node/esm/jwe/general/decrypt.js @@ -0,0 +1,31 @@ +import { flattenedDecrypt } from '../flattened/decrypt.js'; +import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.js'; +import isObject from '../../lib/is_object.js'; +export async function generalDecrypt(jwe, key, options) { + if (!isObject(jwe)) { + throw new JWEInvalid('General JWE must be an object'); + } + if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) { + throw new JWEInvalid('JWE Recipients missing or incorrect type'); + } + if (!jwe.recipients.length) { + throw new JWEInvalid('JWE Recipients has no members'); + } + for (const recipient of jwe.recipients) { + try { + return await flattenedDecrypt({ + aad: jwe.aad, + ciphertext: jwe.ciphertext, + encrypted_key: recipient.encrypted_key, + header: recipient.header, + iv: jwe.iv, + protected: jwe.protected, + tag: jwe.tag, + unprotected: jwe.unprotected, + }, key, options); + } + catch { + } + } + throw new JWEDecryptionFailed(); +} diff --git a/dist/node/esm/jwe/general/encrypt.js b/dist/node/esm/jwe/general/encrypt.js new file mode 100644 index 0000000000..3ee53dec44 --- /dev/null +++ b/dist/node/esm/jwe/general/encrypt.js @@ -0,0 +1,178 @@ +import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.js'; +import { JWEInvalid } from '../../util/errors.js'; +import generateCek from '../../lib/cek.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import encryptKeyManagement from '../../lib/encrypt_key_management.js'; +import { encode as base64url } from '../../runtime/base64url.js'; +import validateCrit from '../../lib/validate_crit.js'; +class IndividualRecipient { + constructor(enc, key, options) { + this.parent = enc; + this.key = key; + this.options = options; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addRecipient(...args) { + return this.parent.addRecipient(...args); + } + encrypt(...args) { + return this.parent.encrypt(...args); + } + done() { + return this.parent; + } +} +export class GeneralEncrypt { + constructor(plaintext) { + this._recipients = []; + this._plaintext = plaintext; + } + addRecipient(key, options) { + const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit }); + this._recipients.push(recipient); + return recipient; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setSharedUnprotectedHeader(sharedUnprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setSharedUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = sharedUnprotectedHeader; + return this; + } + setAdditionalAuthenticatedData(aad) { + this._aad = aad; + return this; + } + async encrypt(options) { + var _a, _b, _c; + if (!this._recipients.length) { + throw new JWEInvalid('at least one recipient must be added'); + } + options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw }; + if (this._recipients.length === 1) { + const [recipient] = this._recipients; + const flattened = await new FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader) + .encrypt(recipient.key, { ...recipient.options, ...options }); + let jwe = { + ciphertext: flattened.ciphertext, + iv: flattened.iv, + recipients: [{}], + tag: flattened.tag, + }; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + if (flattened.encrypted_key) + jwe.recipients[0].encrypted_key = flattened.encrypted_key; + if (flattened.header) + jwe.recipients[0].header = flattened.header; + return jwe; + } + let enc; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) { + throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + }; + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid'); + } + if (alg === 'dir' || alg === 'ECDH-ES') { + throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient'); + } + if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid'); + } + if (!enc) { + enc = joseHeader.enc; + } + else if (enc !== joseHeader.enc) { + throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients'); + } + validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader); + if (joseHeader.zip !== undefined) { + if (!this._protectedHeader || !this._protectedHeader.zip) { + throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected'); + } + } + } + const cek = generateCek(enc); + let jwe = { + ciphertext: '', + iv: '', + recipients: [], + tag: '', + }; + for (let i = 0; i < this._recipients.length; i++) { + const recipient = this._recipients[i]; + const target = {}; + jwe.recipients.push(target); + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + ...recipient.unprotectedHeader, + }; + const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined; + if (i === 0) { + const flattened = await new FlattenedEncrypt(this._plaintext) + .setAdditionalAuthenticatedData(this._aad) + .setContentEncryptionKey(cek) + .setProtectedHeader(this._protectedHeader) + .setSharedUnprotectedHeader(this._unprotectedHeader) + .setUnprotectedHeader(recipient.unprotectedHeader) + .setKeyManagementParameters({ p2c }) + .encrypt(recipient.key, { + ...recipient.options, + ...options, + [unprotected]: true, + }); + jwe.ciphertext = flattened.ciphertext; + jwe.iv = flattened.iv; + jwe.tag = flattened.tag; + if (flattened.aad) + jwe.aad = flattened.aad; + if (flattened.protected) + jwe.protected = flattened.protected; + if (flattened.unprotected) + jwe.unprotected = flattened.unprotected; + target.encrypted_key = flattened.encrypted_key; + if (flattened.header) + target.header = flattened.header; + continue; + } + const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || + ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || + ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek, { p2c }); + target.encrypted_key = base64url(encryptedKey); + if (recipient.unprotectedHeader || parameters) + target.header = { ...recipient.unprotectedHeader, ...parameters }; + } + return jwe; + } +} diff --git a/dist/node/esm/jwk/embedded.js b/dist/node/esm/jwk/embedded.js new file mode 100644 index 0000000000..58db282552 --- /dev/null +++ b/dist/node/esm/jwk/embedded.js @@ -0,0 +1,17 @@ +import { importJWK } from '../key/import.js'; +import isObject from '../lib/is_object.js'; +import { JWSInvalid } from '../util/errors.js'; +export async function EmbeddedJWK(protectedHeader, token) { + const joseHeader = { + ...protectedHeader, + ...token.header, + }; + if (!isObject(joseHeader.jwk)) { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object'); + } + const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true); + if (key instanceof Uint8Array || key.type !== 'public') { + throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key'); + } + return key; +} diff --git a/dist/node/esm/jwk/thumbprint.js b/dist/node/esm/jwk/thumbprint.js new file mode 100644 index 0000000000..49f86b1743 --- /dev/null +++ b/dist/node/esm/jwk/thumbprint.js @@ -0,0 +1,53 @@ +import digest from '../runtime/digest.js'; +import { encode as base64url } from '../runtime/base64url.js'; +import { JOSENotSupported, JWKInvalid } from '../util/errors.js'; +import { encoder } from '../lib/buffer_utils.js'; +import isObject from '../lib/is_object.js'; +const check = (value, description) => { + if (typeof value !== 'string' || !value) { + throw new JWKInvalid(`${description} missing or invalid`); + } +}; +export async function calculateJwkThumbprint(jwk, digestAlgorithm) { + if (!isObject(jwk)) { + throw new TypeError('JWK must be an object'); + } + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); + if (digestAlgorithm !== 'sha256' && + digestAlgorithm !== 'sha384' && + digestAlgorithm !== 'sha512') { + throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); + } + let components; + switch (jwk.kty) { + case 'EC': + check(jwk.crv, '"crv" (Curve) Parameter'); + check(jwk.x, '"x" (X Coordinate) Parameter'); + check(jwk.y, '"y" (Y Coordinate) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; + break; + case 'OKP': + check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); + check(jwk.x, '"x" (Public Key) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; + break; + case 'RSA': + check(jwk.e, '"e" (Exponent) Parameter'); + check(jwk.n, '"n" (Modulus) Parameter'); + components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; + break; + case 'oct': + check(jwk.k, '"k" (Key Value) Parameter'); + components = { k: jwk.k, kty: jwk.kty }; + break; + default: + throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported'); + } + const data = encoder.encode(JSON.stringify(components)); + return base64url(await digest(digestAlgorithm, data)); +} +export async function calculateJwkThumbprintUri(jwk, digestAlgorithm) { + digestAlgorithm !== null && digestAlgorithm !== void 0 ? digestAlgorithm : (digestAlgorithm = 'sha256'); + const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); + return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; +} diff --git a/dist/node/esm/jwks/local.js b/dist/node/esm/jwks/local.js new file mode 100644 index 0000000000..bfe2130fad --- /dev/null +++ b/dist/node/esm/jwks/local.js @@ -0,0 +1,113 @@ +import { importJWK } from '../key/import.js'; +import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js'; +import isObject from '../lib/is_object.js'; +function getKtyFromAlg(alg) { + switch (typeof alg === 'string' && alg.slice(0, 2)) { + case 'RS': + case 'PS': + return 'RSA'; + case 'ES': + return 'EC'; + case 'Ed': + return 'OKP'; + default: + throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); + } +} +export function isJWKSLike(jwks) { + return (jwks && + typeof jwks === 'object' && + Array.isArray(jwks.keys) && + jwks.keys.every(isJWKLike)); +} +function isJWKLike(key) { + return isObject(key); +} +function clone(obj) { + if (typeof structuredClone === 'function') { + return structuredClone(obj); + } + return JSON.parse(JSON.stringify(obj)); +} +export class LocalJWKSet { + constructor(jwks) { + this._cached = new WeakMap(); + if (!isJWKSLike(jwks)) { + throw new JWKSInvalid('JSON Web Key Set malformed'); + } + this._jwks = clone(jwks); + } + async getKey(protectedHeader, token) { + const { alg, kid } = { ...protectedHeader, ...token === null || token === void 0 ? void 0 : token.header }; + const kty = getKtyFromAlg(alg); + const candidates = this._jwks.keys.filter((jwk) => { + let candidate = kty === jwk.kty; + if (candidate && typeof kid === 'string') { + candidate = kid === jwk.kid; + } + if (candidate && typeof jwk.alg === 'string') { + candidate = alg === jwk.alg; + } + if (candidate && typeof jwk.use === 'string') { + candidate = jwk.use === 'sig'; + } + if (candidate && Array.isArray(jwk.key_ops)) { + candidate = jwk.key_ops.includes('verify'); + } + if (candidate && alg === 'EdDSA') { + candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'; + } + if (candidate) { + switch (alg) { + case 'ES256': + candidate = jwk.crv === 'P-256'; + break; + case 'ES256K': + candidate = jwk.crv === 'secp256k1'; + break; + case 'ES384': + candidate = jwk.crv === 'P-384'; + break; + case 'ES512': + candidate = jwk.crv === 'P-521'; + break; + } + } + return candidate; + }); + const { 0: jwk, length } = candidates; + if (length === 0) { + throw new JWKSNoMatchingKey(); + } + else if (length !== 1) { + const error = new JWKSMultipleMatchingKeys(); + const { _cached } = this; + error[Symbol.asyncIterator] = async function* () { + for (const jwk of candidates) { + try { + yield await importWithAlgCache(_cached, jwk, alg); + } + catch { + continue; + } + } + }; + throw error; + } + return importWithAlgCache(this._cached, jwk, alg); + } +} +async function importWithAlgCache(cache, jwk, alg) { + const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk); + if (cached[alg] === undefined) { + const keyObject = await importJWK({ ...jwk, ext: true }, alg); + if (keyObject.type !== 'public') { + throw new JWKSInvalid('JSON Web Key Set members must be public keys'); + } + cached[alg] = keyObject; + } + return cached[alg]; +} +export function createLocalJWKSet(jwks) { + return LocalJWKSet.prototype.getKey.bind(new LocalJWKSet(jwks)); +} diff --git a/dist/node/esm/jwks/remote.js b/dist/node/esm/jwks/remote.js new file mode 100644 index 0000000000..574ccff83b --- /dev/null +++ b/dist/node/esm/jwks/remote.js @@ -0,0 +1,81 @@ +import fetchJwks from '../runtime/fetch_jwks.js'; +import { isCloudflareWorkers } from '../runtime/env.js'; +import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.js'; +import { isJWKSLike, LocalJWKSet } from './local.js'; +class RemoteJWKSet extends LocalJWKSet { + constructor(url, options) { + super({ keys: [] }); + this._jwks = undefined; + if (!(url instanceof URL)) { + throw new TypeError('url must be an instance of URL'); + } + this._url = new URL(url.href); + this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers }; + this._timeoutDuration = + typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000; + this._cooldownDuration = + typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000; + this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000; + } + coolingDown() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cooldownDuration + : false; + } + fresh() { + return typeof this._jwksTimestamp === 'number' + ? Date.now() < this._jwksTimestamp + this._cacheMaxAge + : false; + } + async getKey(protectedHeader, token) { + if (!this._jwks || !this.fresh()) { + await this.reload(); + } + try { + return await super.getKey(protectedHeader, token); + } + catch (err) { + if (err instanceof JWKSNoMatchingKey) { + if (this.coolingDown() === false) { + await this.reload(); + return super.getKey(protectedHeader, token); + } + } + throw err; + } + } + async reload() { + if (this._pendingFetch && isCloudflareWorkers()) { + return new Promise((resolve) => { + const isDone = () => { + if (this._pendingFetch === undefined) { + resolve(); + } + else { + setTimeout(isDone, 5); + } + }; + isDone(); + }); + } + if (!this._pendingFetch) { + this._pendingFetch = fetchJwks(this._url, this._timeoutDuration, this._options) + .then((json) => { + if (!isJWKSLike(json)) { + throw new JWKSInvalid('JSON Web Key Set malformed'); + } + this._jwks = { keys: json.keys }; + this._jwksTimestamp = Date.now(); + this._pendingFetch = undefined; + }) + .catch((err) => { + this._pendingFetch = undefined; + throw err; + }); + } + await this._pendingFetch; + } +} +export function createRemoteJWKSet(url, options) { + return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options)); +} diff --git a/dist/node/esm/jws/compact/sign.js b/dist/node/esm/jws/compact/sign.js new file mode 100644 index 0000000000..b8e5ba0e2b --- /dev/null +++ b/dist/node/esm/jws/compact/sign.js @@ -0,0 +1,17 @@ +import { FlattenedSign } from '../flattened/sign.js'; +export class CompactSign { + constructor(payload) { + this._flattened = new FlattenedSign(payload); + } + setProtectedHeader(protectedHeader) { + this._flattened.setProtectedHeader(protectedHeader); + return this; + } + async sign(key, options) { + const jws = await this._flattened.sign(key, options); + if (jws.payload === undefined) { + throw new TypeError('use the flattened module for creating JWS with b64: false'); + } + return `${jws.protected}.${jws.payload}.${jws.signature}`; + } +} diff --git a/dist/node/esm/jws/compact/verify.js b/dist/node/esm/jws/compact/verify.js new file mode 100644 index 0000000000..c651ffb944 --- /dev/null +++ b/dist/node/esm/jws/compact/verify.js @@ -0,0 +1,21 @@ +import { flattenedVerify } from '../flattened/verify.js'; +import { JWSInvalid } from '../../util/errors.js'; +import { decoder } from '../../lib/buffer_utils.js'; +export async function compactVerify(jws, key, options) { + if (jws instanceof Uint8Array) { + jws = decoder.decode(jws); + } + if (typeof jws !== 'string') { + throw new JWSInvalid('Compact JWS must be a string or Uint8Array'); + } + const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.'); + if (length !== 3) { + throw new JWSInvalid('Invalid Compact JWS'); + } + const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); + const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: verified.key }; + } + return result; +} diff --git a/dist/node/esm/jws/flattened/sign.js b/dist/node/esm/jws/flattened/sign.js new file mode 100644 index 0000000000..76ae289654 --- /dev/null +++ b/dist/node/esm/jws/flattened/sign.js @@ -0,0 +1,81 @@ +import { encode as base64url } from '../../runtime/base64url.js'; +import sign from '../../runtime/sign.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import { JWSInvalid } from '../../util/errors.js'; +import { encoder, decoder, concat } from '../../lib/buffer_utils.js'; +import checkKeyType from '../../lib/check_key_type.js'; +import validateCrit from '../../lib/validate_crit.js'; +export class FlattenedSign { + constructor(payload) { + if (!(payload instanceof Uint8Array)) { + throw new TypeError('payload must be an instance of Uint8Array'); + } + this._payload = payload; + } + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this._unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this._unprotectedHeader = unprotectedHeader; + return this; + } + async sign(key, options) { + if (!this._protectedHeader && !this._unprotectedHeader) { + throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); + } + if (!isDisjoint(this._protectedHeader, this._unprotectedHeader)) { + throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...this._protectedHeader, + ...this._unprotectedHeader, + }; + const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); + let b64 = true; + if (extensions.has('b64')) { + b64 = this._protectedHeader.b64; + if (typeof b64 !== 'boolean') { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + checkKeyType(alg, key, 'sign'); + let payload = this._payload; + if (b64) { + payload = encoder.encode(base64url(payload)); + } + let protectedHeader; + if (this._protectedHeader) { + protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader))); + } + else { + protectedHeader = encoder.encode(''); + } + const data = concat(protectedHeader, encoder.encode('.'), payload); + const signature = await sign(alg, key, data); + const jws = { + signature: base64url(signature), + payload: '', + }; + if (b64) { + jws.payload = decoder.decode(payload); + } + if (this._unprotectedHeader) { + jws.header = this._unprotectedHeader; + } + if (this._protectedHeader) { + jws.protected = decoder.decode(protectedHeader); + } + return jws; + } +} diff --git a/dist/node/esm/jws/flattened/verify.js b/dist/node/esm/jws/flattened/verify.js new file mode 100644 index 0000000000..a6ea3c8a12 --- /dev/null +++ b/dist/node/esm/jws/flattened/verify.js @@ -0,0 +1,104 @@ +import { decode as base64url } from '../../runtime/base64url.js'; +import verify from '../../runtime/verify.js'; +import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; +import { concat, encoder, decoder } from '../../lib/buffer_utils.js'; +import isDisjoint from '../../lib/is_disjoint.js'; +import isObject from '../../lib/is_object.js'; +import checkKeyType from '../../lib/check_key_type.js'; +import validateCrit from '../../lib/validate_crit.js'; +import validateAlgorithms from '../../lib/validate_algorithms.js'; +export async function flattenedVerify(jws, key, options) { + var _a; + if (!isObject(jws)) { + throw new JWSInvalid('Flattened JWS must be an object'); + } + if (jws.protected === undefined && jws.header === undefined) { + throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); + } + if (jws.protected !== undefined && typeof jws.protected !== 'string') { + throw new JWSInvalid('JWS Protected Header incorrect type'); + } + if (jws.payload === undefined) { + throw new JWSInvalid('JWS Payload missing'); + } + if (typeof jws.signature !== 'string') { + throw new JWSInvalid('JWS Signature missing or incorrect type'); + } + if (jws.header !== undefined && !isObject(jws.header)) { + throw new JWSInvalid('JWS Unprotected Header incorrect type'); + } + let parsedProt = {}; + if (jws.protected) { + try { + const protectedHeader = base64url(jws.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader)); + } + catch { + throw new JWSInvalid('JWS Protected Header is invalid'); + } + } + if (!isDisjoint(parsedProt, jws.header)) { + throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint'); + } + const joseHeader = { + ...parsedProt, + ...jws.header, + }; + const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); + let b64 = true; + if (extensions.has('b64')) { + b64 = parsedProt.b64; + if (typeof b64 !== 'boolean') { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== 'string' || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + const algorithms = options && validateAlgorithms('algorithms', options.algorithms); + if (algorithms && !algorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed'); + } + if (b64) { + if (typeof jws.payload !== 'string') { + throw new JWSInvalid('JWS Payload must be a string'); + } + } + else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) { + throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance'); + } + let resolvedKey = false; + if (typeof key === 'function') { + key = await key(parsedProt, jws); + resolvedKey = true; + } + checkKeyType(alg, key, 'verify'); + const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload); + const signature = base64url(jws.signature); + const verified = await verify(alg, key, signature, data); + if (!verified) { + throw new JWSSignatureVerificationFailed(); + } + let payload; + if (b64) { + payload = base64url(jws.payload); + } + else if (typeof jws.payload === 'string') { + payload = encoder.encode(jws.payload); + } + else { + payload = jws.payload; + } + const result = { payload }; + if (jws.protected !== undefined) { + result.protectedHeader = parsedProt; + } + if (jws.header !== undefined) { + result.unprotectedHeader = jws.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; +} diff --git a/dist/node/esm/jws/general/sign.js b/dist/node/esm/jws/general/sign.js new file mode 100644 index 0000000000..38d5a6d766 --- /dev/null +++ b/dist/node/esm/jws/general/sign.js @@ -0,0 +1,67 @@ +import { FlattenedSign } from '../flattened/sign.js'; +import { JWSInvalid } from '../../util/errors.js'; +class IndividualSignature { + constructor(sig, key, options) { + this.parent = sig; + this.key = key; + this.options = options; + } + setProtectedHeader(protectedHeader) { + if (this.protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this.protectedHeader = protectedHeader; + return this; + } + setUnprotectedHeader(unprotectedHeader) { + if (this.unprotectedHeader) { + throw new TypeError('setUnprotectedHeader can only be called once'); + } + this.unprotectedHeader = unprotectedHeader; + return this; + } + addSignature(...args) { + return this.parent.addSignature(...args); + } + sign(...args) { + return this.parent.sign(...args); + } + done() { + return this.parent; + } +} +export class GeneralSign { + constructor(payload) { + this._signatures = []; + this._payload = payload; + } + addSignature(key, options) { + const signature = new IndividualSignature(this, key, options); + this._signatures.push(signature); + return signature; + } + async sign() { + if (!this._signatures.length) { + throw new JWSInvalid('at least one signature must be added'); + } + const jws = { + signatures: [], + payload: '', + }; + for (let i = 0; i < this._signatures.length; i++) { + const signature = this._signatures[i]; + const flattened = new FlattenedSign(this._payload); + flattened.setProtectedHeader(signature.protectedHeader); + flattened.setUnprotectedHeader(signature.unprotectedHeader); + const { payload, ...rest } = await flattened.sign(signature.key, signature.options); + if (i === 0) { + jws.payload = payload; + } + else if (jws.payload !== payload) { + throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)'); + } + jws.signatures.push(rest); + } + return jws; + } +} diff --git a/dist/node/esm/jws/general/verify.js b/dist/node/esm/jws/general/verify.js new file mode 100644 index 0000000000..c511b722dc --- /dev/null +++ b/dist/node/esm/jws/general/verify.js @@ -0,0 +1,24 @@ +import { flattenedVerify } from '../flattened/verify.js'; +import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; +import isObject from '../../lib/is_object.js'; +export async function generalVerify(jws, key, options) { + if (!isObject(jws)) { + throw new JWSInvalid('General JWS must be an object'); + } + if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) { + throw new JWSInvalid('JWS Signatures missing or incorrect type'); + } + for (const signature of jws.signatures) { + try { + return await flattenedVerify({ + header: signature.header, + payload: jws.payload, + protected: signature.protected, + signature: signature.signature, + }, key, options); + } + catch { + } + } + throw new JWSSignatureVerificationFailed(); +} diff --git a/dist/node/esm/jwt/decrypt.js b/dist/node/esm/jwt/decrypt.js new file mode 100644 index 0000000000..1ec2be28f2 --- /dev/null +++ b/dist/node/esm/jwt/decrypt.js @@ -0,0 +1,23 @@ +import { compactDecrypt } from '../jwe/compact/decrypt.js'; +import jwtPayload from '../lib/jwt_claims_set.js'; +import { JWTClaimValidationFailed } from '../util/errors.js'; +export async function jwtDecrypt(jwt, key, options) { + const decrypted = await compactDecrypt(jwt, key, options); + const payload = jwtPayload(decrypted.protectedHeader, decrypted.plaintext, options); + const { protectedHeader } = decrypted; + if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) { + throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', 'iss', 'mismatch'); + } + if (protectedHeader.sub !== undefined && protectedHeader.sub !== payload.sub) { + throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', 'sub', 'mismatch'); + } + if (protectedHeader.aud !== undefined && + JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) { + throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch'); + } + const result = { payload, protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: decrypted.key }; + } + return result; +} diff --git a/dist/node/esm/jwt/encrypt.js b/dist/node/esm/jwt/encrypt.js new file mode 100644 index 0000000000..15252957ae --- /dev/null +++ b/dist/node/esm/jwt/encrypt.js @@ -0,0 +1,68 @@ +import { CompactEncrypt } from '../jwe/compact/encrypt.js'; +import { encoder } from '../lib/buffer_utils.js'; +import { ProduceJWT } from './produce.js'; +export class EncryptJWT extends ProduceJWT { + setProtectedHeader(protectedHeader) { + if (this._protectedHeader) { + throw new TypeError('setProtectedHeader can only be called once'); + } + this._protectedHeader = protectedHeader; + return this; + } + setKeyManagementParameters(parameters) { + if (this._keyManagementParameters) { + throw new TypeError('setKeyManagementParameters can only be called once'); + } + this._keyManagementParameters = parameters; + return this; + } + setContentEncryptionKey(cek) { + if (this._cek) { + throw new TypeError('setContentEncryptionKey can only be called once'); + } + this._cek = cek; + return this; + } + setInitializationVector(iv) { + if (this._iv) { + throw new TypeError('setInitializationVector can only be called once'); + } + this._iv = iv; + return this; + } + replicateIssuerAsHeader() { + this._replicateIssuerAsHeader = true; + return this; + } + replicateSubjectAsHeader() { + this._replicateSubjectAsHeader = true; + return this; + } + replicateAudienceAsHeader() { + this._replicateAudienceAsHeader = true; + return this; + } + async encrypt(key, options) { + const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload))); + if (this._replicateIssuerAsHeader) { + this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss }; + } + if (this._replicateSubjectAsHeader) { + this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub }; + } + if (this._replicateAudienceAsHeader) { + this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud }; + } + enc.setProtectedHeader(this._protectedHeader); + if (this._iv) { + enc.setInitializationVector(this._iv); + } + if (this._cek) { + enc.setContentEncryptionKey(this._cek); + } + if (this._keyManagementParameters) { + enc.setKeyManagementParameters(this._keyManagementParameters); + } + return enc.encrypt(key, options); + } +} diff --git a/dist/node/esm/jwt/produce.js b/dist/node/esm/jwt/produce.js new file mode 100644 index 0000000000..31c929a07c --- /dev/null +++ b/dist/node/esm/jwt/produce.js @@ -0,0 +1,54 @@ +import epoch from '../lib/epoch.js'; +import isObject from '../lib/is_object.js'; +import secs from '../lib/secs.js'; +export class ProduceJWT { + constructor(payload) { + if (!isObject(payload)) { + throw new TypeError('JWT Claims Set MUST be an object'); + } + this._payload = payload; + } + setIssuer(issuer) { + this._payload = { ...this._payload, iss: issuer }; + return this; + } + setSubject(subject) { + this._payload = { ...this._payload, sub: subject }; + return this; + } + setAudience(audience) { + this._payload = { ...this._payload, aud: audience }; + return this; + } + setJti(jwtId) { + this._payload = { ...this._payload, jti: jwtId }; + return this; + } + setNotBefore(input) { + if (typeof input === 'number') { + this._payload = { ...this._payload, nbf: input }; + } + else { + this._payload = { ...this._payload, nbf: epoch(new Date()) + secs(input) }; + } + return this; + } + setExpirationTime(input) { + if (typeof input === 'number') { + this._payload = { ...this._payload, exp: input }; + } + else { + this._payload = { ...this._payload, exp: epoch(new Date()) + secs(input) }; + } + return this; + } + setIssuedAt(input) { + if (typeof input === 'undefined') { + this._payload = { ...this._payload, iat: epoch(new Date()) }; + } + else { + this._payload = { ...this._payload, iat: input }; + } + return this; + } +} diff --git a/dist/node/esm/jwt/sign.js b/dist/node/esm/jwt/sign.js new file mode 100644 index 0000000000..62352fbfa2 --- /dev/null +++ b/dist/node/esm/jwt/sign.js @@ -0,0 +1,21 @@ +import { CompactSign } from '../jws/compact/sign.js'; +import { JWTInvalid } from '../util/errors.js'; +import { encoder } from '../lib/buffer_utils.js'; +import { ProduceJWT } from './produce.js'; +export class SignJWT extends ProduceJWT { + setProtectedHeader(protectedHeader) { + this._protectedHeader = protectedHeader; + return this; + } + async sign(key, options) { + var _a; + const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); + sig.setProtectedHeader(this._protectedHeader); + if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && + this._protectedHeader.crit.includes('b64') && + this._protectedHeader.b64 === false) { + throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); + } + return sig.sign(key, options); + } +} diff --git a/dist/node/esm/jwt/unsecured.js b/dist/node/esm/jwt/unsecured.js new file mode 100644 index 0000000000..41c7c33bb5 --- /dev/null +++ b/dist/node/esm/jwt/unsecured.js @@ -0,0 +1,32 @@ +import * as base64url from '../runtime/base64url.js'; +import { decoder } from '../lib/buffer_utils.js'; +import { JWTInvalid } from '../util/errors.js'; +import jwtPayload from '../lib/jwt_claims_set.js'; +import { ProduceJWT } from './produce.js'; +export class UnsecuredJWT extends ProduceJWT { + encode() { + const header = base64url.encode(JSON.stringify({ alg: 'none' })); + const payload = base64url.encode(JSON.stringify(this._payload)); + return `${header}.${payload}.`; + } + static decode(jwt, options) { + if (typeof jwt !== 'string') { + throw new JWTInvalid('Unsecured JWT must be a string'); + } + const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.'); + if (length !== 3 || signature !== '') { + throw new JWTInvalid('Invalid Unsecured JWT'); + } + let header; + try { + header = JSON.parse(decoder.decode(base64url.decode(encodedHeader))); + if (header.alg !== 'none') + throw new Error(); + } + catch { + throw new JWTInvalid('Invalid Unsecured JWT'); + } + const payload = jwtPayload(header, base64url.decode(encodedPayload), options); + return { payload, header }; + } +} diff --git a/dist/node/esm/jwt/verify.js b/dist/node/esm/jwt/verify.js new file mode 100644 index 0000000000..89571c1847 --- /dev/null +++ b/dist/node/esm/jwt/verify.js @@ -0,0 +1,16 @@ +import { compactVerify } from '../jws/compact/verify.js'; +import jwtPayload from '../lib/jwt_claims_set.js'; +import { JWTInvalid } from '../util/errors.js'; +export async function jwtVerify(jwt, key, options) { + var _a; + const verified = await compactVerify(jwt, key, options); + if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { + throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); + } + const payload = jwtPayload(verified.protectedHeader, verified.payload, options); + const result = { payload, protectedHeader: verified.protectedHeader }; + if (typeof key === 'function') { + return { ...result, key: verified.key }; + } + return result; +} diff --git a/dist/node/esm/key/export.js b/dist/node/esm/key/export.js new file mode 100644 index 0000000000..e4017047cd --- /dev/null +++ b/dist/node/esm/key/export.js @@ -0,0 +1,12 @@ +import { toSPKI as exportPublic } from '../runtime/asn1.js'; +import { toPKCS8 as exportPrivate } from '../runtime/asn1.js'; +import keyToJWK from '../runtime/key_to_jwk.js'; +export async function exportSPKI(key) { + return exportPublic(key); +} +export async function exportPKCS8(key) { + return exportPrivate(key); +} +export async function exportJWK(key) { + return keyToJWK(key); +} diff --git a/dist/node/esm/key/generate_key_pair.js b/dist/node/esm/key/generate_key_pair.js new file mode 100644 index 0000000000..03b9ee54cd --- /dev/null +++ b/dist/node/esm/key/generate_key_pair.js @@ -0,0 +1,4 @@ +import { generateKeyPair as generate } from '../runtime/generate.js'; +export async function generateKeyPair(alg, options) { + return generate(alg, options); +} diff --git a/dist/node/esm/key/generate_secret.js b/dist/node/esm/key/generate_secret.js new file mode 100644 index 0000000000..58f308a543 --- /dev/null +++ b/dist/node/esm/key/generate_secret.js @@ -0,0 +1,4 @@ +import { generateSecret as generate } from '../runtime/generate.js'; +export async function generateSecret(alg, options) { + return generate(alg, options); +} diff --git a/dist/node/esm/key/import.js b/dist/node/esm/key/import.js new file mode 100644 index 0000000000..25bb0e1659 --- /dev/null +++ b/dist/node/esm/key/import.js @@ -0,0 +1,50 @@ +import { decode as decodeBase64URL } from '../runtime/base64url.js'; +import { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.js'; +import asKeyObject from '../runtime/jwk_to_key.js'; +import { JOSENotSupported } from '../util/errors.js'; +import isObject from '../lib/is_object.js'; +export async function importSPKI(spki, alg, options) { + if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) { + throw new TypeError('"spki" must be SPKI formatted string'); + } + return fromSPKI(spki, alg, options); +} +export async function importX509(x509, alg, options) { + if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) { + throw new TypeError('"x509" must be X.509 formatted string'); + } + return fromX509(x509, alg, options); +} +export async function importPKCS8(pkcs8, alg, options) { + if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) { + throw new TypeError('"pkcs8" must be PKCS#8 formatted string'); + } + return fromPKCS8(pkcs8, alg, options); +} +export async function importJWK(jwk, alg, octAsKeyObject) { + var _a; + if (!isObject(jwk)) { + throw new TypeError('JWK must be an object'); + } + alg || (alg = jwk.alg); + switch (jwk.kty) { + case 'oct': + if (typeof jwk.k !== 'string' || !jwk.k) { + throw new TypeError('missing "k" (Key Value) Parameter value'); + } + octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true); + if (octAsKeyObject) { + return asKeyObject({ ...jwk, alg, ext: (_a = jwk.ext) !== null && _a !== void 0 ? _a : false }); + } + return decodeBase64URL(jwk.k); + case 'RSA': + if (jwk.oth !== undefined) { + throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); + } + case 'EC': + case 'OKP': + return asKeyObject({ ...jwk, alg }); + default: + throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); + } +} diff --git a/dist/node/esm/lib/aesgcmkw.js b/dist/node/esm/lib/aesgcmkw.js new file mode 100644 index 0000000000..de3f4f91df --- /dev/null +++ b/dist/node/esm/lib/aesgcmkw.js @@ -0,0 +1,14 @@ +import encrypt from '../runtime/encrypt.js'; +import decrypt from '../runtime/decrypt.js'; +import generateIv from './iv.js'; +import { encode as base64url } from '../runtime/base64url.js'; +export async function wrap(alg, key, cek, iv) { + const jweAlgorithm = alg.slice(0, 7); + iv || (iv = generateIv(jweAlgorithm)); + const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0)); + return { encryptedKey, iv: base64url(iv), tag: base64url(tag) }; +} +export async function unwrap(alg, key, encryptedKey, iv, tag) { + const jweAlgorithm = alg.slice(0, 7); + return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0)); +} diff --git a/dist/node/esm/lib/buffer_utils.js b/dist/node/esm/lib/buffer_utils.js new file mode 100644 index 0000000000..5a1a7b334d --- /dev/null +++ b/dist/node/esm/lib/buffer_utils.js @@ -0,0 +1,51 @@ +import digest from '../runtime/digest.js'; +export const encoder = new TextEncoder(); +export const decoder = new TextDecoder(); +const MAX_INT32 = 2 ** 32; +export function concat(...buffers) { + const size = buffers.reduce((acc, { length }) => acc + length, 0); + const buf = new Uint8Array(size); + let i = 0; + buffers.forEach((buffer) => { + buf.set(buffer, i); + i += buffer.length; + }); + return buf; +} +export function p2s(alg, p2sInput) { + return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput); +} +function writeUInt32BE(buf, value, offset) { + if (value < 0 || value >= MAX_INT32) { + throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`); + } + buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset); +} +export function uint64be(value) { + const high = Math.floor(value / MAX_INT32); + const low = value % MAX_INT32; + const buf = new Uint8Array(8); + writeUInt32BE(buf, high, 0); + writeUInt32BE(buf, low, 4); + return buf; +} +export function uint32be(value) { + const buf = new Uint8Array(4); + writeUInt32BE(buf, value); + return buf; +} +export function lengthAndInput(input) { + return concat(uint32be(input.length), input); +} +export async function concatKdf(secret, bits, value) { + const iterations = Math.ceil((bits >> 3) / 32); + const res = new Uint8Array(iterations * 32); + for (let iter = 0; iter < iterations; iter++) { + const buf = new Uint8Array(4 + secret.length + value.length); + buf.set(uint32be(iter + 1)); + buf.set(secret, 4); + buf.set(value, 4 + secret.length); + res.set(await digest('sha256', buf), iter * 32); + } + return res.slice(0, bits >> 3); +} diff --git a/dist/node/esm/lib/cek.js b/dist/node/esm/lib/cek.js new file mode 100644 index 0000000000..34697d3ac2 --- /dev/null +++ b/dist/node/esm/lib/cek.js @@ -0,0 +1,20 @@ +import { JOSENotSupported } from '../util/errors.js'; +import random from '../runtime/random.js'; +export function bitLength(alg) { + switch (alg) { + case 'A128GCM': + return 128; + case 'A192GCM': + return 192; + case 'A256GCM': + case 'A128CBC-HS256': + return 256; + case 'A192CBC-HS384': + return 384; + case 'A256CBC-HS512': + return 512; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/esm/lib/check_iv_length.js b/dist/node/esm/lib/check_iv_length.js new file mode 100644 index 0000000000..dcd28d3a9d --- /dev/null +++ b/dist/node/esm/lib/check_iv_length.js @@ -0,0 +1,8 @@ +import { JWEInvalid } from '../util/errors.js'; +import { bitLength } from './iv.js'; +const checkIvLength = (enc, iv) => { + if (iv.length << 3 !== bitLength(enc)) { + throw new JWEInvalid('Invalid Initialization Vector length'); + } +}; +export default checkIvLength; diff --git a/dist/node/esm/lib/check_key_type.js b/dist/node/esm/lib/check_key_type.js new file mode 100644 index 0000000000..43f3dcbf14 --- /dev/null +++ b/dist/node/esm/lib/check_key_type.js @@ -0,0 +1,45 @@ +import { withAlg as invalidKeyInput } from './invalid_key_input.js'; +import isKeyLike, { types } from '../runtime/is_key_like.js'; +const symmetricTypeCheck = (alg, key) => { + if (key instanceof Uint8Array) + return; + if (!isKeyLike(key)) { + throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array')); + } + if (key.type !== 'secret') { + throw new TypeError(`${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`); + } +}; +const asymmetricTypeCheck = (alg, key, usage) => { + if (!isKeyLike(key)) { + throw new TypeError(invalidKeyInput(alg, key, ...types)); + } + if (key.type === 'secret') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`); + } + if (usage === 'sign' && key.type === 'public') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`); + } + if (usage === 'decrypt' && key.type === 'public') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`); + } + if (key.algorithm && usage === 'verify' && key.type === 'private') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`); + } + if (key.algorithm && usage === 'encrypt' && key.type === 'private') { + throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`); + } +}; +const checkKeyType = (alg, key, usage) => { + const symmetric = alg.startsWith('HS') || + alg === 'dir' || + alg.startsWith('PBES2') || + /^A\d{3}(?:GCM)?KW$/.test(alg); + if (symmetric) { + symmetricTypeCheck(alg, key); + } + else { + asymmetricTypeCheck(alg, key, usage); + } +}; +export default checkKeyType; diff --git a/dist/node/esm/lib/check_p2s.js b/dist/node/esm/lib/check_p2s.js new file mode 100644 index 0000000000..a65289fa7a --- /dev/null +++ b/dist/node/esm/lib/check_p2s.js @@ -0,0 +1,6 @@ +import { JWEInvalid } from '../util/errors.js'; +export default function checkP2s(p2s) { + if (!(p2s instanceof Uint8Array) || p2s.length < 8) { + throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets'); + } +} diff --git a/dist/node/esm/lib/crypto_key.js b/dist/node/esm/lib/crypto_key.js new file mode 100644 index 0000000000..4405b1915c --- /dev/null +++ b/dist/node/esm/lib/crypto_key.js @@ -0,0 +1,158 @@ +import { isCloudflareWorkers } from '../runtime/env.js'; +function unusable(name, prop = 'algorithm.name') { + return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); +} +function isAlgorithm(algorithm, name) { + return algorithm.name === name; +} +function getHashLength(hash) { + return parseInt(hash.name.slice(4), 10); +} +function getNamedCurve(alg) { + switch (alg) { + case 'ES256': + return 'P-256'; + case 'ES384': + return 'P-384'; + case 'ES512': + return 'P-521'; + default: + throw new Error('unreachable'); + } +} +function checkUsage(key, usages) { + if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { + let msg = 'CryptoKey does not support this operation, its usages must include '; + if (usages.length > 2) { + const last = usages.pop(); + msg += `one of ${usages.join(', ')}, or ${last}.`; + } + else if (usages.length === 2) { + msg += `one of ${usages[0]} or ${usages[1]}.`; + } + else { + msg += `${usages[0]}.`; + } + throw new TypeError(msg); + } +} +export function checkSigCryptoKey(key, alg, ...usages) { + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': { + if (!isAlgorithm(key.algorithm, 'HMAC')) + throw unusable('HMAC'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'RS256': + case 'RS384': + case 'RS512': { + if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) + throw unusable('RSASSA-PKCS1-v1_5'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'PS256': + case 'PS384': + case 'PS512': { + if (!isAlgorithm(key.algorithm, 'RSA-PSS')) + throw unusable('RSA-PSS'); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + case 'EdDSA': { + if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { + if (isCloudflareWorkers()) { + if (isAlgorithm(key.algorithm, 'NODE-ED25519')) + break; + throw unusable('Ed25519, Ed448, or NODE-ED25519'); + } + throw unusable('Ed25519 or Ed448'); + } + break; + } + case 'ES256': + case 'ES384': + case 'ES512': { + if (!isAlgorithm(key.algorithm, 'ECDSA')) + throw unusable('ECDSA'); + const expected = getNamedCurve(alg); + const actual = key.algorithm.namedCurve; + if (actual !== expected) + throw unusable(expected, 'algorithm.namedCurve'); + break; + } + default: + throw new TypeError('CryptoKey does not support this operation'); + } + checkUsage(key, usages); +} +export function checkEncCryptoKey(key, alg, ...usages) { + switch (alg) { + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': { + if (!isAlgorithm(key.algorithm, 'AES-GCM')) + throw unusable('AES-GCM'); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, 'algorithm.length'); + break; + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + if (!isAlgorithm(key.algorithm, 'AES-KW')) + throw unusable('AES-KW'); + const expected = parseInt(alg.slice(1, 4), 10); + const actual = key.algorithm.length; + if (actual !== expected) + throw unusable(expected, 'algorithm.length'); + break; + } + case 'ECDH': { + switch (key.algorithm.name) { + case 'ECDH': + case 'X25519': + case 'X448': + break; + default: + throw unusable('ECDH, X25519, or X448'); + } + break; + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': + if (!isAlgorithm(key.algorithm, 'PBKDF2')) + throw unusable('PBKDF2'); + break; + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + if (!isAlgorithm(key.algorithm, 'RSA-OAEP')) + throw unusable('RSA-OAEP'); + const expected = parseInt(alg.slice(9), 10) || 1; + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, 'algorithm.hash'); + break; + } + default: + throw new TypeError('CryptoKey does not support this operation'); + } + checkUsage(key, usages); +} diff --git a/dist/node/esm/lib/decrypt_key_management.js b/dist/node/esm/lib/decrypt_key_management.js new file mode 100644 index 0000000000..87890a4fa0 --- /dev/null +++ b/dist/node/esm/lib/decrypt_key_management.js @@ -0,0 +1,98 @@ +import { unwrap as aesKw } from '../runtime/aeskw.js'; +import * as ECDH from '../runtime/ecdhes.js'; +import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js'; +import { decrypt as rsaEs } from '../runtime/rsaes.js'; +import { decode as base64url } from '../runtime/base64url.js'; +import { JOSENotSupported, JWEInvalid } from '../util/errors.js'; +import { bitLength as cekLength } from '../lib/cek.js'; +import { importJWK } from '../key/import.js'; +import checkKeyType from './check_key_type.js'; +import isObject from './is_object.js'; +import { unwrap as aesGcmKw } from './aesgcmkw.js'; +async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) { + checkKeyType(alg, key, 'decrypt'); + switch (alg) { + case 'dir': { + if (encryptedKey !== undefined) + throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); + return key; + } + case 'ECDH-ES': + if (encryptedKey !== undefined) + throw new JWEInvalid('Encountered unexpected JWE Encrypted Key'); + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + if (!isObject(joseHeader.epk)) + throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`); + if (!ECDH.ecdhAllowed(key)) + throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); + const epk = await importJWK(joseHeader.epk, alg); + let partyUInfo; + let partyVInfo; + if (joseHeader.apu !== undefined) { + if (typeof joseHeader.apu !== 'string') + throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`); + partyUInfo = base64url(joseHeader.apu); + } + if (joseHeader.apv !== undefined) { + if (typeof joseHeader.apv !== 'string') + throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`); + partyVInfo = base64url(joseHeader.apv); + } + const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo); + if (alg === 'ECDH-ES') + return sharedSecret; + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + return aesKw(alg.slice(-6), sharedSecret, encryptedKey); + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + return rsaEs(alg, key, encryptedKey); + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + if (typeof joseHeader.p2c !== 'number') + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`); + const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 10000; + if (joseHeader.p2c > p2cLimit) + throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`); + if (typeof joseHeader.p2s !== 'string') + throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`); + return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s)); + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + return aesKw(alg, key, encryptedKey); + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + if (encryptedKey === undefined) + throw new JWEInvalid('JWE Encrypted Key missing'); + if (typeof joseHeader.iv !== 'string') + throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`); + if (typeof joseHeader.tag !== 'string') + throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`); + const iv = base64url(joseHeader.iv); + const tag = base64url(joseHeader.tag); + return aesGcmKw(alg, key, encryptedKey, iv, tag); + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } +} +export default decryptKeyManagement; diff --git a/dist/node/esm/lib/encrypt_key_management.js b/dist/node/esm/lib/encrypt_key_management.js new file mode 100644 index 0000000000..eb9022c63e --- /dev/null +++ b/dist/node/esm/lib/encrypt_key_management.js @@ -0,0 +1,87 @@ +import { wrap as aesKw } from '../runtime/aeskw.js'; +import * as ECDH from '../runtime/ecdhes.js'; +import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js'; +import { encrypt as rsaEs } from '../runtime/rsaes.js'; +import { encode as base64url } from '../runtime/base64url.js'; +import generateCek, { bitLength as cekLength } from '../lib/cek.js'; +import { JOSENotSupported } from '../util/errors.js'; +import { exportJWK } from '../key/export.js'; +import checkKeyType from './check_key_type.js'; +import { wrap as aesGcmKw } from './aesgcmkw.js'; +async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) { + let encryptedKey; + let parameters; + let cek; + checkKeyType(alg, key, 'encrypt'); + switch (alg) { + case 'dir': { + cek = key; + break; + } + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': { + if (!ECDH.ecdhAllowed(key)) { + throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime'); + } + const { apu, apv } = providedParameters; + let { epk: ephemeralKey } = providedParameters; + ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey); + const { x, y, crv, kty } = await exportJWK(ephemeralKey); + const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv); + parameters = { epk: { x, crv, kty } }; + if (kty === 'EC') + parameters.epk.y = y; + if (apu) + parameters.apu = base64url(apu); + if (apv) + parameters.apv = base64url(apv); + if (alg === 'ECDH-ES') { + cek = sharedSecret; + break; + } + cek = providedCek || generateCek(enc); + const kwAlg = alg.slice(-6); + encryptedKey = await aesKw(kwAlg, sharedSecret, cek); + break; + } + case 'RSA1_5': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': { + cek = providedCek || generateCek(enc); + encryptedKey = await rsaEs(alg, key, cek); + break; + } + case 'PBES2-HS256+A128KW': + case 'PBES2-HS384+A192KW': + case 'PBES2-HS512+A256KW': { + cek = providedCek || generateCek(enc); + const { p2c, p2s } = providedParameters; + ({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s)); + break; + } + case 'A128KW': + case 'A192KW': + case 'A256KW': { + cek = providedCek || generateCek(enc); + encryptedKey = await aesKw(alg, key, cek); + break; + } + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': { + cek = providedCek || generateCek(enc); + const { iv } = providedParameters; + ({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv)); + break; + } + default: { + throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value'); + } + } + return { cek, encryptedKey, parameters }; +} +export default encryptKeyManagement; diff --git a/dist/node/esm/lib/epoch.js b/dist/node/esm/lib/epoch.js new file mode 100644 index 0000000000..e405e4b2df --- /dev/null +++ b/dist/node/esm/lib/epoch.js @@ -0,0 +1 @@ +export default (date) => Math.floor(date.getTime() / 1000); diff --git a/dist/node/esm/lib/invalid_key_input.js b/dist/node/esm/lib/invalid_key_input.js new file mode 100644 index 0000000000..049e66ece0 --- /dev/null +++ b/dist/node/esm/lib/invalid_key_input.js @@ -0,0 +1,30 @@ +function message(msg, actual, ...types) { + if (types.length > 2) { + const last = types.pop(); + msg += `one of type ${types.join(', ')}, or ${last}.`; + } + else if (types.length === 2) { + msg += `one of type ${types[0]} or ${types[1]}.`; + } + else { + msg += `of type ${types[0]}.`; + } + if (actual == null) { + msg += ` Received ${actual}`; + } + else if (typeof actual === 'function' && actual.name) { + msg += ` Received function ${actual.name}`; + } + else if (typeof actual === 'object' && actual != null) { + if (actual.constructor && actual.constructor.name) { + msg += ` Received an instance of ${actual.constructor.name}`; + } + } + return msg; +} +export default (actual, ...types) => { + return message('Key must be ', actual, ...types); +}; +export function withAlg(alg, actual, ...types) { + return message(`Key for the ${alg} algorithm must be `, actual, ...types); +} diff --git a/dist/node/esm/lib/is_disjoint.js b/dist/node/esm/lib/is_disjoint.js new file mode 100644 index 0000000000..6f643502dc --- /dev/null +++ b/dist/node/esm/lib/is_disjoint.js @@ -0,0 +1,22 @@ +const isDisjoint = (...headers) => { + const sources = headers.filter(Boolean); + if (sources.length === 0 || sources.length === 1) { + return true; + } + let acc; + for (const header of sources) { + const parameters = Object.keys(header); + if (!acc || acc.size === 0) { + acc = new Set(parameters); + continue; + } + for (const parameter of parameters) { + if (acc.has(parameter)) { + return false; + } + acc.add(parameter); + } + } + return true; +}; +export default isDisjoint; diff --git a/dist/node/esm/lib/is_object.js b/dist/node/esm/lib/is_object.js new file mode 100644 index 0000000000..4955e93225 --- /dev/null +++ b/dist/node/esm/lib/is_object.js @@ -0,0 +1,16 @@ +function isObjectLike(value) { + return typeof value === 'object' && value !== null; +} +export default function isObject(input) { + if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') { + return false; + } + if (Object.getPrototypeOf(input) === null) { + return true; + } + let proto = input; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + return Object.getPrototypeOf(input) === proto; +} diff --git a/dist/node/esm/lib/iv.js b/dist/node/esm/lib/iv.js new file mode 100644 index 0000000000..cab2a12729 --- /dev/null +++ b/dist/node/esm/lib/iv.js @@ -0,0 +1,20 @@ +import { JOSENotSupported } from '../util/errors.js'; +import random from '../runtime/random.js'; +export function bitLength(alg) { + switch (alg) { + case 'A128GCM': + case 'A128GCMKW': + case 'A192GCM': + case 'A192GCMKW': + case 'A256GCM': + case 'A256GCMKW': + return 96; + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return 128; + default: + throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`); + } +} +export default (alg) => random(new Uint8Array(bitLength(alg) >> 3)); diff --git a/dist/node/esm/lib/jwt_claims_set.js b/dist/node/esm/lib/jwt_claims_set.js new file mode 100644 index 0000000000..fc4193ad90 --- /dev/null +++ b/dist/node/esm/lib/jwt_claims_set.js @@ -0,0 +1,91 @@ +import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js'; +import { decoder } from './buffer_utils.js'; +import epoch from './epoch.js'; +import secs from './secs.js'; +import isObject from './is_object.js'; +const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ''); +const checkAudiencePresence = (audPayload, audOption) => { + if (typeof audPayload === 'string') { + return audOption.includes(audPayload); + } + if (Array.isArray(audPayload)) { + return audOption.some(Set.prototype.has.bind(new Set(audPayload))); + } + return false; +}; +export default (protectedHeader, encodedPayload, options = {}) => { + const { typ } = options; + if (typ && + (typeof protectedHeader.typ !== 'string' || + normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { + throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed'); + } + let payload; + try { + payload = JSON.parse(decoder.decode(encodedPayload)); + } + catch { + } + if (!isObject(payload)) { + throw new JWTInvalid('JWT Claims Set must be a top-level JSON object'); + } + const { issuer } = options; + if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { + throw new JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed'); + } + const { subject } = options; + if (subject && payload.sub !== subject) { + throw new JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed'); + } + const { audience } = options; + if (audience && + !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) { + throw new JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed'); + } + let tolerance; + switch (typeof options.clockTolerance) { + case 'string': + tolerance = secs(options.clockTolerance); + break; + case 'number': + tolerance = options.clockTolerance; + break; + case 'undefined': + tolerance = 0; + break; + default: + throw new TypeError('Invalid clockTolerance option type'); + } + const { currentDate } = options; + const now = epoch(currentDate || new Date()); + if ((payload.iat !== undefined || options.maxTokenAge) && typeof payload.iat !== 'number') { + throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid'); + } + if (payload.nbf !== undefined) { + if (typeof payload.nbf !== 'number') { + throw new JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid'); + } + if (payload.nbf > now + tolerance) { + throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', 'nbf', 'check_failed'); + } + } + if (payload.exp !== undefined) { + if (typeof payload.exp !== 'number') { + throw new JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid'); + } + if (payload.exp <= now - tolerance) { + throw new JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed'); + } + } + if (options.maxTokenAge) { + const age = now - payload.iat; + const max = typeof options.maxTokenAge === 'number' ? options.maxTokenAge : secs(options.maxTokenAge); + if (age - tolerance > max) { + throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', 'iat', 'check_failed'); + } + if (age < 0 - tolerance) { + throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed'); + } + } + return payload; +}; diff --git a/dist/node/esm/lib/secs.js b/dist/node/esm/lib/secs.js new file mode 100644 index 0000000000..cf470ed8ad --- /dev/null +++ b/dist/node/esm/lib/secs.js @@ -0,0 +1,44 @@ +const minute = 60; +const hour = minute * 60; +const day = hour * 24; +const week = day * 7; +const year = day * 365.25; +const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i; +export default (str) => { + const matched = REGEX.exec(str); + if (!matched) { + throw new TypeError('Invalid time period format'); + } + const value = parseFloat(matched[1]); + const unit = matched[2].toLowerCase(); + switch (unit) { + case 'sec': + case 'secs': + case 'second': + case 'seconds': + case 's': + return Math.round(value); + case 'minute': + case 'minutes': + case 'min': + case 'mins': + case 'm': + return Math.round(value * minute); + case 'hour': + case 'hours': + case 'hr': + case 'hrs': + case 'h': + return Math.round(value * hour); + case 'day': + case 'days': + case 'd': + return Math.round(value * day); + case 'week': + case 'weeks': + case 'w': + return Math.round(value * week); + default: + return Math.round(value * year); + } +}; diff --git a/dist/node/esm/lib/validate_algorithms.js b/dist/node/esm/lib/validate_algorithms.js new file mode 100644 index 0000000000..a6a7918571 --- /dev/null +++ b/dist/node/esm/lib/validate_algorithms.js @@ -0,0 +1,11 @@ +const validateAlgorithms = (option, algorithms) => { + if (algorithms !== undefined && + (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) { + throw new TypeError(`"${option}" option must be an array of strings`); + } + if (!algorithms) { + return undefined; + } + return new Set(algorithms); +}; +export default validateAlgorithms; diff --git a/dist/node/esm/lib/validate_crit.js b/dist/node/esm/lib/validate_crit.js new file mode 100644 index 0000000000..68c69f18f5 --- /dev/null +++ b/dist/node/esm/lib/validate_crit.js @@ -0,0 +1,34 @@ +import { JOSENotSupported } from '../util/errors.js'; +function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { + if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { + throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); + } + if (!protectedHeader || protectedHeader.crit === undefined) { + return new Set(); + } + if (!Array.isArray(protectedHeader.crit) || + protectedHeader.crit.length === 0 || + protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) { + throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); + } + let recognized; + if (recognizedOption !== undefined) { + recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); + } + else { + recognized = recognizedDefault; + } + for (const parameter of protectedHeader.crit) { + if (!recognized.has(parameter)) { + throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); + } + if (joseHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" is missing`); + } + else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { + throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); + } + } + return new Set(protectedHeader.crit); +} +export default validateCrit; diff --git a/dist/node/esm/package.json b/dist/node/esm/package.json new file mode 100644 index 0000000000..6990891ff3 --- /dev/null +++ b/dist/node/esm/package.json @@ -0,0 +1 @@ +{"type": "module"} diff --git a/dist/node/esm/runtime/aeskw.js b/dist/node/esm/runtime/aeskw.js new file mode 100644 index 0000000000..722b8b37e5 --- /dev/null +++ b/dist/node/esm/runtime/aeskw.js @@ -0,0 +1,50 @@ +import { Buffer } from 'buffer'; +import { KeyObject, createDecipheriv, createCipheriv, createSecretKey } from 'crypto'; +import { JOSENotSupported } from '../util/errors.js'; +import { concat } from '../lib/buffer_utils.js'; +import { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import supported from './ciphers.js'; +import { types } from './is_key_like.js'; +function checkKeySize(key, alg) { + if (key.symmetricKeySize << 3 !== parseInt(alg.slice(1, 4), 10)) { + throw new TypeError(`Invalid key size for alg: ${alg}`); + } +} +function ensureKeyObject(key, alg, usage) { + if (isKeyObject(key)) { + return key; + } + if (key instanceof Uint8Array) { + return createSecretKey(key); + } + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, usage); + return KeyObject.from(key); + } + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); +} +export const wrap = (alg, key, cek) => { + const size = parseInt(alg.slice(1, 4), 10); + const algorithm = `aes${size}-wrap`; + if (!supported(algorithm)) { + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } + const keyObject = ensureKeyObject(key, alg, 'wrapKey'); + checkKeySize(keyObject, alg); + const cipher = createCipheriv(algorithm, keyObject, Buffer.alloc(8, 0xa6)); + return concat(cipher.update(cek), cipher.final()); +}; +export const unwrap = (alg, key, encryptedKey) => { + const size = parseInt(alg.slice(1, 4), 10); + const algorithm = `aes${size}-wrap`; + if (!supported(algorithm)) { + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } + const keyObject = ensureKeyObject(key, alg, 'unwrapKey'); + checkKeySize(keyObject, alg); + const cipher = createDecipheriv(algorithm, keyObject, Buffer.alloc(8, 0xa6)); + return concat(cipher.update(encryptedKey), cipher.final()); +}; diff --git a/dist/node/esm/runtime/asn1.js b/dist/node/esm/runtime/asn1.js new file mode 100644 index 0000000000..d6f447eac0 --- /dev/null +++ b/dist/node/esm/runtime/asn1.js @@ -0,0 +1,46 @@ +import { createPrivateKey, createPublicKey, KeyObject } from 'crypto'; +import { Buffer } from 'buffer'; +import { isCryptoKey } from './webcrypto.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +const genericExport = (keyType, keyFormat, key) => { + let keyObject; + if (isCryptoKey(key)) { + if (!key.extractable) { + throw new TypeError('CryptoKey is not extractable'); + } + keyObject = KeyObject.from(key); + } + else if (isKeyObject(key)) { + keyObject = key; + } + else { + throw new TypeError(invalidKeyInput(key, ...types)); + } + if (keyObject.type !== keyType) { + throw new TypeError(`key is not a ${keyType} key`); + } + return keyObject.export({ format: 'pem', type: keyFormat }); +}; +export const toSPKI = (key) => { + return genericExport('public', 'spki', key); +}; +export const toPKCS8 = (key) => { + return genericExport('private', 'pkcs8', key); +}; +export const fromPKCS8 = (pem) => createPrivateKey({ + key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, ''), 'base64'), + type: 'pkcs8', + format: 'der', +}); +export const fromSPKI = (pem) => createPublicKey({ + key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, ''), 'base64'), + type: 'spki', + format: 'der', +}); +export const fromX509 = (pem) => createPublicKey({ + key: pem, + type: 'spki', + format: 'pem', +}); diff --git a/dist/node/esm/runtime/asn1_sequence_decoder.js b/dist/node/esm/runtime/asn1_sequence_decoder.js new file mode 100644 index 0000000000..61ba4c3116 --- /dev/null +++ b/dist/node/esm/runtime/asn1_sequence_decoder.js @@ -0,0 +1,44 @@ +const tagInteger = 0x02; +const tagSequence = 0x30; +export default class Asn1SequenceDecoder { + constructor(buffer) { + if (buffer[0] !== tagSequence) { + throw new TypeError(); + } + this.buffer = buffer; + this.offset = 1; + const len = this.decodeLength(); + if (len !== buffer.length - this.offset) { + throw new TypeError(); + } + } + decodeLength() { + let length = this.buffer[this.offset++]; + if (length & 0x80) { + const nBytes = length & ~0x80; + length = 0; + for (let i = 0; i < nBytes; i++) + length = (length << 8) | this.buffer[this.offset + i]; + this.offset += nBytes; + } + return length; + } + unsignedInteger() { + if (this.buffer[this.offset++] !== tagInteger) { + throw new TypeError(); + } + let length = this.decodeLength(); + if (this.buffer[this.offset] === 0) { + this.offset++; + length--; + } + const result = this.buffer.slice(this.offset, this.offset + length); + this.offset += length; + return result; + } + end() { + if (this.offset !== this.buffer.length) { + throw new TypeError(); + } + } +} diff --git a/dist/node/esm/runtime/asn1_sequence_encoder.js b/dist/node/esm/runtime/asn1_sequence_encoder.js new file mode 100644 index 0000000000..ac672776a4 --- /dev/null +++ b/dist/node/esm/runtime/asn1_sequence_encoder.js @@ -0,0 +1,88 @@ +import { Buffer } from 'buffer'; +import { JOSENotSupported } from '../util/errors.js'; +const tagInteger = 0x02; +const tagBitStr = 0x03; +const tagOctStr = 0x04; +const tagSequence = 0x30; +const bZero = Buffer.from([0x00]); +const bTagInteger = Buffer.from([tagInteger]); +const bTagBitStr = Buffer.from([tagBitStr]); +const bTagSequence = Buffer.from([tagSequence]); +const bTagOctStr = Buffer.from([tagOctStr]); +const encodeLength = (len) => { + if (len < 128) + return Buffer.from([len]); + const buffer = Buffer.alloc(5); + buffer.writeUInt32BE(len, 1); + let offset = 1; + while (buffer[offset] === 0) + offset++; + buffer[offset - 1] = 0x80 | (5 - offset); + return buffer.slice(offset - 1); +}; +const oids = new Map([ + ['P-256', Buffer.from('06 08 2A 86 48 CE 3D 03 01 07'.replace(/ /g, ''), 'hex')], + ['secp256k1', Buffer.from('06 05 2B 81 04 00 0A'.replace(/ /g, ''), 'hex')], + ['P-384', Buffer.from('06 05 2B 81 04 00 22'.replace(/ /g, ''), 'hex')], + ['P-521', Buffer.from('06 05 2B 81 04 00 23'.replace(/ /g, ''), 'hex')], + ['ecPublicKey', Buffer.from('06 07 2A 86 48 CE 3D 02 01'.replace(/ /g, ''), 'hex')], + ['X25519', Buffer.from('06 03 2B 65 6E'.replace(/ /g, ''), 'hex')], + ['X448', Buffer.from('06 03 2B 65 6F'.replace(/ /g, ''), 'hex')], + ['Ed25519', Buffer.from('06 03 2B 65 70'.replace(/ /g, ''), 'hex')], + ['Ed448', Buffer.from('06 03 2B 65 71'.replace(/ /g, ''), 'hex')], +]); +export default class DumbAsn1Encoder { + constructor() { + this.length = 0; + this.elements = []; + } + oidFor(oid) { + const bOid = oids.get(oid); + if (!bOid) { + throw new JOSENotSupported('Invalid or unsupported OID'); + } + this.elements.push(bOid); + this.length += bOid.length; + } + zero() { + this.elements.push(bTagInteger, Buffer.from([0x01]), bZero); + this.length += 3; + } + one() { + this.elements.push(bTagInteger, Buffer.from([0x01]), Buffer.from([0x01])); + this.length += 3; + } + unsignedInteger(integer) { + if (integer[0] & 0x80) { + const len = encodeLength(integer.length + 1); + this.elements.push(bTagInteger, len, bZero, integer); + this.length += 2 + len.length + integer.length; + } + else { + let i = 0; + while (integer[i] === 0 && (integer[i + 1] & 0x80) === 0) + i++; + const len = encodeLength(integer.length - i); + this.elements.push(bTagInteger, encodeLength(integer.length - i), integer.slice(i)); + this.length += 1 + len.length + integer.length - i; + } + } + octStr(octStr) { + const len = encodeLength(octStr.length); + this.elements.push(bTagOctStr, encodeLength(octStr.length), octStr); + this.length += 1 + len.length + octStr.length; + } + bitStr(bitS) { + const len = encodeLength(bitS.length + 1); + this.elements.push(bTagBitStr, encodeLength(bitS.length + 1), bZero, bitS); + this.length += 1 + len.length + bitS.length + 1; + } + add(seq) { + this.elements.push(seq); + this.length += seq.length; + } + end(tag = bTagSequence) { + const len = encodeLength(this.length); + return Buffer.concat([tag, len, ...this.elements], 1 + len.length + this.length); + } +} diff --git a/dist/node/esm/runtime/base64url.js b/dist/node/esm/runtime/base64url.js new file mode 100644 index 0000000000..1579359fdf --- /dev/null +++ b/dist/node/esm/runtime/base64url.js @@ -0,0 +1,20 @@ +import { Buffer } from 'buffer'; +import { decoder } from '../lib/buffer_utils.js'; +let encode; +function normalize(input) { + let encoded = input; + if (encoded instanceof Uint8Array) { + encoded = decoder.decode(encoded); + } + return encoded; +} +if (Buffer.isEncoding('base64url')) { + encode = (input) => Buffer.from(input).toString('base64url'); +} +else { + encode = (input) => Buffer.from(input).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); +} +export const decodeBase64 = (input) => Buffer.from(input, 'base64'); +export const encodeBase64 = (input) => Buffer.from(input).toString('base64'); +export { encode }; +export const decode = (input) => Buffer.from(normalize(input), 'base64'); diff --git a/dist/node/esm/runtime/cbc_tag.js b/dist/node/esm/runtime/cbc_tag.js new file mode 100644 index 0000000000..fa58c38b6c --- /dev/null +++ b/dist/node/esm/runtime/cbc_tag.js @@ -0,0 +1,8 @@ +import { createHmac } from 'crypto'; +import { concat, uint64be } from '../lib/buffer_utils.js'; +export default function cbcTag(aad, iv, ciphertext, macSize, macKey, keySize) { + const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); + const hmac = createHmac(`sha${macSize}`, macKey); + hmac.update(macData); + return hmac.digest().slice(0, keySize >> 3); +} diff --git a/dist/node/esm/runtime/check_cek_length.js b/dist/node/esm/runtime/check_cek_length.js new file mode 100644 index 0000000000..60884c0ea5 --- /dev/null +++ b/dist/node/esm/runtime/check_cek_length.js @@ -0,0 +1,35 @@ +import { JWEInvalid, JOSENotSupported } from '../util/errors.js'; +import isKeyObject from './is_key_object.js'; +const checkCekLength = (enc, cek) => { + let expected; + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + expected = parseInt(enc.slice(-3), 10); + break; + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + expected = parseInt(enc.slice(1, 4), 10); + break; + default: + throw new JOSENotSupported(`Content Encryption Algorithm ${enc} is not supported either by JOSE or your javascript runtime`); + } + if (cek instanceof Uint8Array) { + const actual = cek.byteLength << 3; + if (actual !== expected) { + throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); + } + return; + } + if (isKeyObject(cek) && cek.type === 'secret') { + const actual = cek.symmetricKeySize << 3; + if (actual !== expected) { + throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`); + } + return; + } + throw new TypeError('Invalid Content Encryption Key type'); +}; +export default checkCekLength; diff --git a/dist/node/esm/runtime/check_modulus_length.js b/dist/node/esm/runtime/check_modulus_length.js new file mode 100644 index 0000000000..690f809602 --- /dev/null +++ b/dist/node/esm/runtime/check_modulus_length.js @@ -0,0 +1,48 @@ +export const weakMap = new WeakMap(); +const getLength = (buf, index) => { + let len = buf.readUInt8(1); + if ((len & 0x80) === 0) { + if (index === 0) { + return len; + } + return getLength(buf.subarray(2 + len), index - 1); + } + const num = len & 0x7f; + len = 0; + for (let i = 0; i < num; i++) { + len <<= 8; + const j = buf.readUInt8(2 + i); + len |= j; + } + if (index === 0) { + return len; + } + return getLength(buf.subarray(2 + len), index - 1); +}; +const getLengthOfSeqIndex = (sequence, index) => { + const len = sequence.readUInt8(1); + if ((len & 0x80) === 0) { + return getLength(sequence.subarray(2), index); + } + const num = len & 0x7f; + return getLength(sequence.subarray(2 + num), index); +}; +const getModulusLength = (key) => { + var _a, _b; + if (weakMap.has(key)) { + return weakMap.get(key); + } + const modulusLength = (_b = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.modulusLength) !== null && _b !== void 0 ? _b : (getLengthOfSeqIndex(key.export({ format: 'der', type: 'pkcs1' }), key.type === 'private' ? 1 : 0) - + 1) << + 3; + weakMap.set(key, modulusLength); + return modulusLength; +}; +export const setModulusLength = (keyObject, modulusLength) => { + weakMap.set(keyObject, modulusLength); +}; +export default (key, alg) => { + if (getModulusLength(key) < 2048) { + throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); + } +}; diff --git a/dist/node/esm/runtime/ciphers.js b/dist/node/esm/runtime/ciphers.js new file mode 100644 index 0000000000..daded1d503 --- /dev/null +++ b/dist/node/esm/runtime/ciphers.js @@ -0,0 +1,6 @@ +import { getCiphers } from 'crypto'; +let ciphers; +export default (algorithm) => { + ciphers || (ciphers = new Set(getCiphers())); + return ciphers.has(algorithm); +}; diff --git a/dist/node/esm/runtime/decrypt.js b/dist/node/esm/runtime/decrypt.js new file mode 100644 index 0000000000..8a611d174b --- /dev/null +++ b/dist/node/esm/runtime/decrypt.js @@ -0,0 +1,95 @@ +import { createDecipheriv, KeyObject } from 'crypto'; +import checkIvLength from '../lib/check_iv_length.js'; +import checkCekLength from './check_cek_length.js'; +import { concat } from '../lib/buffer_utils.js'; +import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js'; +import timingSafeEqual from './timing_safe_equal.js'; +import cbcTag from './cbc_tag.js'; +import { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import supported from './ciphers.js'; +import { types } from './is_key_like.js'; +function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + if (isKeyObject(cek)) { + cek = cek.export(); + } + const encKey = cek.subarray(keySize >> 3); + const macKey = cek.subarray(0, keySize >> 3); + const macSize = parseInt(enc.slice(-3), 10); + const algorithm = `aes-${keySize}-cbc`; + if (!supported(algorithm)) { + throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + const expectedTag = cbcTag(aad, iv, ciphertext, macSize, macKey, keySize); + let macCheckPassed; + try { + macCheckPassed = timingSafeEqual(tag, expectedTag); + } + catch { + } + if (!macCheckPassed) { + throw new JWEDecryptionFailed(); + } + let plaintext; + try { + const decipher = createDecipheriv(algorithm, encKey, iv); + plaintext = concat(decipher.update(ciphertext), decipher.final()); + } + catch { + } + if (!plaintext) { + throw new JWEDecryptionFailed(); + } + return plaintext; +} +function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + const algorithm = `aes-${keySize}-gcm`; + if (!supported(algorithm)) { + throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + try { + const decipher = createDecipheriv(algorithm, cek, iv, { authTagLength: 16 }); + decipher.setAuthTag(tag); + if (aad.byteLength) { + decipher.setAAD(aad, { plaintextLength: ciphertext.length }); + } + const plaintext = decipher.update(ciphertext); + decipher.final(); + return plaintext; + } + catch { + throw new JWEDecryptionFailed(); + } +} +const decrypt = (enc, cek, ciphertext, iv, tag, aad) => { + let key; + if (isCryptoKey(cek)) { + checkEncCryptoKey(cek, enc, 'decrypt'); + key = KeyObject.from(cek); + } + else if (cek instanceof Uint8Array || isKeyObject(cek)) { + key = cek; + } + else { + throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); + } + checkCekLength(enc, key); + checkIvLength(enc, iv); + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return cbcDecrypt(enc, key, ciphertext, iv, tag, aad); + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + return gcmDecrypt(enc, key, ciphertext, iv, tag, aad); + default: + throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); + } +}; +export default decrypt; diff --git a/dist/node/esm/runtime/digest.js b/dist/node/esm/runtime/digest.js new file mode 100644 index 0000000000..0facde6c29 --- /dev/null +++ b/dist/node/esm/runtime/digest.js @@ -0,0 +1,3 @@ +import { createHash } from 'crypto'; +const digest = (algorithm, data) => createHash(algorithm).update(data).digest(); +export default digest; diff --git a/dist/node/esm/runtime/dsa_digest.js b/dist/node/esm/runtime/dsa_digest.js new file mode 100644 index 0000000000..ce7215bd67 --- /dev/null +++ b/dist/node/esm/runtime/dsa_digest.js @@ -0,0 +1,22 @@ +import { JOSENotSupported } from '../util/errors.js'; +export default function dsaDigest(alg) { + switch (alg) { + case 'PS256': + case 'RS256': + case 'ES256': + case 'ES256K': + return 'sha256'; + case 'PS384': + case 'RS384': + case 'ES384': + return 'sha384'; + case 'PS512': + case 'RS512': + case 'ES512': + return 'sha512'; + case 'EdDSA': + return undefined; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} diff --git a/dist/node/esm/runtime/ecdhes.js b/dist/node/esm/runtime/ecdhes.js new file mode 100644 index 0000000000..d3faef4a05 --- /dev/null +++ b/dist/node/esm/runtime/ecdhes.js @@ -0,0 +1,64 @@ +import { diffieHellman, generateKeyPair as generateKeyPairCb, KeyObject } from 'crypto'; +import { promisify } from 'util'; +import getNamedCurve from './get_named_curve.js'; +import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.js'; +import { JOSENotSupported } from '../util/errors.js'; +import { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +const generateKeyPair = promisify(generateKeyPairCb); +export async function deriveKey(publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { + let publicKey; + if (isCryptoKey(publicKee)) { + checkEncCryptoKey(publicKee, 'ECDH'); + publicKey = KeyObject.from(publicKee); + } + else if (isKeyObject(publicKee)) { + publicKey = publicKee; + } + else { + throw new TypeError(invalidKeyInput(publicKee, ...types)); + } + let privateKey; + if (isCryptoKey(privateKee)) { + checkEncCryptoKey(privateKee, 'ECDH', 'deriveBits'); + privateKey = KeyObject.from(privateKee); + } + else if (isKeyObject(privateKee)) { + privateKey = privateKee; + } + else { + throw new TypeError(invalidKeyInput(privateKee, ...types)); + } + const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); + const sharedSecret = diffieHellman({ privateKey, publicKey }); + return concatKdf(sharedSecret, keyLength, value); +} +export async function generateEpk(kee) { + let key; + if (isCryptoKey(kee)) { + key = KeyObject.from(kee); + } + else if (isKeyObject(kee)) { + key = kee; + } + else { + throw new TypeError(invalidKeyInput(kee, ...types)); + } + switch (key.asymmetricKeyType) { + case 'x25519': + return generateKeyPair('x25519'); + case 'x448': { + return generateKeyPair('x448'); + } + case 'ec': { + const namedCurve = getNamedCurve(key); + return generateKeyPair('ec', { namedCurve }); + } + default: + throw new JOSENotSupported('Invalid or unsupported EPK'); + } +} +export const ecdhAllowed = (key) => ['P-256', 'P-384', 'P-521', 'X25519', 'X448'].includes(getNamedCurve(key)); diff --git a/dist/node/esm/runtime/encrypt.js b/dist/node/esm/runtime/encrypt.js new file mode 100644 index 0000000000..8dfb87b10c --- /dev/null +++ b/dist/node/esm/runtime/encrypt.js @@ -0,0 +1,72 @@ +import { createCipheriv, KeyObject } from 'crypto'; +import checkIvLength from '../lib/check_iv_length.js'; +import checkCekLength from './check_cek_length.js'; +import { concat } from '../lib/buffer_utils.js'; +import cbcTag from './cbc_tag.js'; +import { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { JOSENotSupported } from '../util/errors.js'; +import supported from './ciphers.js'; +import { types } from './is_key_like.js'; +function cbcEncrypt(enc, plaintext, cek, iv, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + if (isKeyObject(cek)) { + cek = cek.export(); + } + const encKey = cek.subarray(keySize >> 3); + const macKey = cek.subarray(0, keySize >> 3); + const algorithm = `aes-${keySize}-cbc`; + if (!supported(algorithm)) { + throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + const cipher = createCipheriv(algorithm, encKey, iv); + const ciphertext = concat(cipher.update(plaintext), cipher.final()); + const macSize = parseInt(enc.slice(-3), 10); + const tag = cbcTag(aad, iv, ciphertext, macSize, macKey, keySize); + return { ciphertext, tag }; +} +function gcmEncrypt(enc, plaintext, cek, iv, aad) { + const keySize = parseInt(enc.slice(1, 4), 10); + const algorithm = `aes-${keySize}-gcm`; + if (!supported(algorithm)) { + throw new JOSENotSupported(`alg ${enc} is not supported by your javascript runtime`); + } + const cipher = createCipheriv(algorithm, cek, iv, { authTagLength: 16 }); + if (aad.byteLength) { + cipher.setAAD(aad, { plaintextLength: plaintext.length }); + } + const ciphertext = cipher.update(plaintext); + cipher.final(); + const tag = cipher.getAuthTag(); + return { ciphertext, tag }; +} +const encrypt = (enc, plaintext, cek, iv, aad) => { + let key; + if (isCryptoKey(cek)) { + checkEncCryptoKey(cek, enc, 'encrypt'); + key = KeyObject.from(cek); + } + else if (cek instanceof Uint8Array || isKeyObject(cek)) { + key = cek; + } + else { + throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); + } + checkCekLength(enc, key); + checkIvLength(enc, iv); + switch (enc) { + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + return cbcEncrypt(enc, plaintext, key, iv, aad); + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + return gcmEncrypt(enc, plaintext, key, iv, aad); + default: + throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); + } +}; +export default encrypt; diff --git a/dist/node/esm/runtime/env.js b/dist/node/esm/runtime/env.js new file mode 100644 index 0000000000..f55de30dc1 --- /dev/null +++ b/dist/node/esm/runtime/env.js @@ -0,0 +1,3 @@ +export function isCloudflareWorkers() { + return false; +} diff --git a/dist/node/esm/runtime/fetch_jwks.js b/dist/node/esm/runtime/fetch_jwks.js new file mode 100644 index 0000000000..5853424ec1 --- /dev/null +++ b/dist/node/esm/runtime/fetch_jwks.js @@ -0,0 +1,43 @@ +import * as http from 'http'; +import * as https from 'https'; +import { once } from 'events'; +import { JOSEError, JWKSTimeout } from '../util/errors.js'; +import { concat, decoder } from '../lib/buffer_utils.js'; +const fetchJwks = async (url, timeout, options) => { + let get; + switch (url.protocol) { + case 'https:': + get = https.get; + break; + case 'http:': + get = http.get; + break; + default: + throw new TypeError('Unsupported URL protocol.'); + } + const { agent, headers } = options; + const req = get(url.href, { + agent, + timeout, + headers, + }); + const [response] = (await Promise.race([once(req, 'response'), once(req, 'timeout')])); + if (!response) { + req.destroy(); + throw new JWKSTimeout(); + } + if (response.statusCode !== 200) { + throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response'); + } + const parts = []; + for await (const part of response) { + parts.push(part); + } + try { + return JSON.parse(decoder.decode(concat(...parts))); + } + catch { + throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON'); + } +}; +export default fetchJwks; diff --git a/dist/node/esm/runtime/flags.js b/dist/node/esm/runtime/flags.js new file mode 100644 index 0000000000..390299593f --- /dev/null +++ b/dist/node/esm/runtime/flags.js @@ -0,0 +1,5 @@ +const [major, minor] = process.versions.node.split('.').map((str) => parseInt(str, 10)); +export const oneShotCallback = major >= 16 || (major === 15 && minor >= 13); +export const rsaPssParams = !('electron' in process.versions) && (major >= 17 || (major === 16 && minor >= 9)); +export const jwkExport = major >= 16 || (major === 15 && minor >= 9); +export const jwkImport = major >= 16 || (major === 15 && minor >= 12); diff --git a/dist/node/esm/runtime/generate.js b/dist/node/esm/runtime/generate.js new file mode 100644 index 0000000000..64f76962f1 --- /dev/null +++ b/dist/node/esm/runtime/generate.js @@ -0,0 +1,100 @@ +import { createSecretKey, generateKeyPair as generateKeyPairCb } from 'crypto'; +import { promisify } from 'util'; +import random from './random.js'; +import { setModulusLength } from './check_modulus_length.js'; +import { JOSENotSupported } from '../util/errors.js'; +const generate = promisify(generateKeyPairCb); +export async function generateSecret(alg, options) { + let length; + switch (alg) { + case 'HS256': + case 'HS384': + case 'HS512': + case 'A128CBC-HS256': + case 'A192CBC-HS384': + case 'A256CBC-HS512': + length = parseInt(alg.slice(-3), 10); + break; + case 'A128KW': + case 'A192KW': + case 'A256KW': + case 'A128GCMKW': + case 'A192GCMKW': + case 'A256GCMKW': + case 'A128GCM': + case 'A192GCM': + case 'A256GCM': + length = parseInt(alg.slice(1, 4), 10); + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + return createSecretKey(random(new Uint8Array(length >> 3))); +} +export async function generateKeyPair(alg, options) { + var _a, _b; + switch (alg) { + case 'RS256': + case 'RS384': + case 'RS512': + case 'PS256': + case 'PS384': + case 'PS512': + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + case 'RSA1_5': { + const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048; + if (typeof modulusLength !== 'number' || modulusLength < 2048) { + throw new JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used'); + } + const keypair = await generate('rsa', { + modulusLength, + publicExponent: 0x10001, + }); + setModulusLength(keypair.privateKey, modulusLength); + setModulusLength(keypair.publicKey, modulusLength); + return keypair; + } + case 'ES256': + return generate('ec', { namedCurve: 'P-256' }); + case 'ES256K': + return generate('ec', { namedCurve: 'secp256k1' }); + case 'ES384': + return generate('ec', { namedCurve: 'P-384' }); + case 'ES512': + return generate('ec', { namedCurve: 'P-521' }); + case 'EdDSA': { + switch (options === null || options === void 0 ? void 0 : options.crv) { + case undefined: + case 'Ed25519': + return generate('ed25519'); + case 'Ed448': + return generate('ed448'); + default: + throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are Ed25519 and Ed448'); + } + } + case 'ECDH-ES': + case 'ECDH-ES+A128KW': + case 'ECDH-ES+A192KW': + case 'ECDH-ES+A256KW': + const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256'; + switch (crv) { + case undefined: + case 'P-256': + case 'P-384': + case 'P-521': + return generate('ec', { namedCurve: crv }); + case 'X25519': + return generate('x25519'); + case 'X448': + return generate('x448'); + default: + throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448'); + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } +} diff --git a/dist/node/esm/runtime/get_named_curve.js b/dist/node/esm/runtime/get_named_curve.js new file mode 100644 index 0000000000..e453a6660e --- /dev/null +++ b/dist/node/esm/runtime/get_named_curve.js @@ -0,0 +1,91 @@ +import { Buffer } from 'buffer'; +import { createPublicKey, KeyObject } from 'crypto'; +import { JOSENotSupported } from '../util/errors.js'; +import { isCryptoKey } from './webcrypto.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +const p256 = Buffer.from([42, 134, 72, 206, 61, 3, 1, 7]); +const p384 = Buffer.from([43, 129, 4, 0, 34]); +const p521 = Buffer.from([43, 129, 4, 0, 35]); +const secp256k1 = Buffer.from([43, 129, 4, 0, 10]); +export const weakMap = new WeakMap(); +const namedCurveToJOSE = (namedCurve) => { + switch (namedCurve) { + case 'prime256v1': + return 'P-256'; + case 'secp384r1': + return 'P-384'; + case 'secp521r1': + return 'P-521'; + case 'secp256k1': + return 'secp256k1'; + default: + throw new JOSENotSupported('Unsupported key curve for this operation'); + } +}; +const getNamedCurve = (kee, raw) => { + var _a; + let key; + if (isCryptoKey(kee)) { + key = KeyObject.from(kee); + } + else if (isKeyObject(kee)) { + key = kee; + } + else { + throw new TypeError(invalidKeyInput(kee, ...types)); + } + if (key.type === 'secret') { + throw new TypeError('only "private" or "public" type keys can be used for this operation'); + } + switch (key.asymmetricKeyType) { + case 'ed25519': + case 'ed448': + return `Ed${key.asymmetricKeyType.slice(2)}`; + case 'x25519': + case 'x448': + return `X${key.asymmetricKeyType.slice(1)}`; + case 'ec': { + if (weakMap.has(key)) { + return weakMap.get(key); + } + let namedCurve = (_a = key.asymmetricKeyDetails) === null || _a === void 0 ? void 0 : _a.namedCurve; + if (!namedCurve && key.type === 'private') { + namedCurve = getNamedCurve(createPublicKey(key), true); + } + else if (!namedCurve) { + const buf = key.export({ format: 'der', type: 'spki' }); + const i = buf[1] < 128 ? 14 : 15; + const len = buf[i]; + const curveOid = buf.slice(i + 1, i + 1 + len); + if (curveOid.equals(p256)) { + namedCurve = 'prime256v1'; + } + else if (curveOid.equals(p384)) { + namedCurve = 'secp384r1'; + } + else if (curveOid.equals(p521)) { + namedCurve = 'secp521r1'; + } + else if (curveOid.equals(secp256k1)) { + namedCurve = 'secp256k1'; + } + else { + throw new JOSENotSupported('Unsupported key curve for this operation'); + } + } + if (raw) + return namedCurve; + const curve = namedCurveToJOSE(namedCurve); + weakMap.set(key, curve); + return curve; + } + default: + throw new TypeError('Invalid asymmetric key type for this operation'); + } +}; +export function setCurve(keyObject, curve) { + weakMap.set(keyObject, curve); +} +export default getNamedCurve; diff --git a/dist/node/esm/runtime/get_sign_verify_key.js b/dist/node/esm/runtime/get_sign_verify_key.js new file mode 100644 index 0000000000..46aa2b4551 --- /dev/null +++ b/dist/node/esm/runtime/get_sign_verify_key.js @@ -0,0 +1,21 @@ +import { KeyObject, createSecretKey } from 'crypto'; +import { isCryptoKey } from './webcrypto.js'; +import { checkSigCryptoKey } from '../lib/crypto_key.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +export default function getSignVerifyKey(alg, key, usage) { + if (key instanceof Uint8Array) { + if (!alg.startsWith('HS')) { + throw new TypeError(invalidKeyInput(key, ...types)); + } + return createSecretKey(key); + } + if (key instanceof KeyObject) { + return key; + } + if (isCryptoKey(key)) { + checkSigCryptoKey(key, alg, usage); + return KeyObject.from(key); + } + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); +} diff --git a/dist/node/esm/runtime/hmac_digest.js b/dist/node/esm/runtime/hmac_digest.js new file mode 100644 index 0000000000..29d55c3e9c --- /dev/null +++ b/dist/node/esm/runtime/hmac_digest.js @@ -0,0 +1,13 @@ +import { JOSENotSupported } from '../util/errors.js'; +export default function hmacDigest(alg) { + switch (alg) { + case 'HS256': + return 'sha256'; + case 'HS384': + return 'sha384'; + case 'HS512': + return 'sha512'; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} diff --git a/dist/node/esm/runtime/is_key_like.js b/dist/node/esm/runtime/is_key_like.js new file mode 100644 index 0000000000..af0d0a0725 --- /dev/null +++ b/dist/node/esm/runtime/is_key_like.js @@ -0,0 +1,8 @@ +import webcrypto, { isCryptoKey } from './webcrypto.js'; +import isKeyObject from './is_key_object.js'; +export default (key) => isKeyObject(key) || isCryptoKey(key); +const types = ['KeyObject']; +if (globalThis.CryptoKey || (webcrypto === null || webcrypto === void 0 ? void 0 : webcrypto.CryptoKey)) { + types.push('CryptoKey'); +} +export { types }; diff --git a/dist/node/esm/runtime/is_key_object.js b/dist/node/esm/runtime/is_key_object.js new file mode 100644 index 0000000000..3a28cd80eb --- /dev/null +++ b/dist/node/esm/runtime/is_key_object.js @@ -0,0 +1,5 @@ +import { KeyObject } from 'crypto'; +import * as util from 'util'; +export default util.types.isKeyObject + ? (obj) => util.types.isKeyObject(obj) + : (obj) => obj != null && obj instanceof KeyObject; diff --git a/dist/node/esm/runtime/jwk_to_key.js b/dist/node/esm/runtime/jwk_to_key.js new file mode 100644 index 0000000000..8cb31d6bf9 --- /dev/null +++ b/dist/node/esm/runtime/jwk_to_key.js @@ -0,0 +1,116 @@ +import { Buffer } from 'buffer'; +import { createPrivateKey, createPublicKey, createSecretKey } from 'crypto'; +import { decode as base64url } from './base64url.js'; +import { JOSENotSupported } from '../util/errors.js'; +import { setCurve } from './get_named_curve.js'; +import { setModulusLength } from './check_modulus_length.js'; +import Asn1SequenceEncoder from './asn1_sequence_encoder.js'; +import { jwkImport } from './flags.js'; +const parse = (jwk) => { + if (jwkImport && jwk.kty !== 'oct') { + return jwk.d + ? createPrivateKey({ format: 'jwk', key: jwk }) + : createPublicKey({ format: 'jwk', key: jwk }); + } + switch (jwk.kty) { + case 'oct': { + return createSecretKey(base64url(jwk.k)); + } + case 'RSA': { + const enc = new Asn1SequenceEncoder(); + const isPrivate = jwk.d !== undefined; + const modulus = Buffer.from(jwk.n, 'base64'); + const exponent = Buffer.from(jwk.e, 'base64'); + if (isPrivate) { + enc.zero(); + enc.unsignedInteger(modulus); + enc.unsignedInteger(exponent); + enc.unsignedInteger(Buffer.from(jwk.d, 'base64')); + enc.unsignedInteger(Buffer.from(jwk.p, 'base64')); + enc.unsignedInteger(Buffer.from(jwk.q, 'base64')); + enc.unsignedInteger(Buffer.from(jwk.dp, 'base64')); + enc.unsignedInteger(Buffer.from(jwk.dq, 'base64')); + enc.unsignedInteger(Buffer.from(jwk.qi, 'base64')); + } + else { + enc.unsignedInteger(modulus); + enc.unsignedInteger(exponent); + } + const der = enc.end(); + const createInput = { + key: der, + format: 'der', + type: 'pkcs1', + }; + const keyObject = isPrivate ? createPrivateKey(createInput) : createPublicKey(createInput); + setModulusLength(keyObject, modulus.length << 3); + return keyObject; + } + case 'EC': { + const enc = new Asn1SequenceEncoder(); + const isPrivate = jwk.d !== undefined; + const pub = Buffer.concat([ + Buffer.alloc(1, 4), + Buffer.from(jwk.x, 'base64'), + Buffer.from(jwk.y, 'base64'), + ]); + if (isPrivate) { + enc.zero(); + const enc$1 = new Asn1SequenceEncoder(); + enc$1.oidFor('ecPublicKey'); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + const enc$2 = new Asn1SequenceEncoder(); + enc$2.one(); + enc$2.octStr(Buffer.from(jwk.d, 'base64')); + const enc$3 = new Asn1SequenceEncoder(); + enc$3.bitStr(pub); + const f2 = enc$3.end(Buffer.from([0xa1])); + enc$2.add(f2); + const f = enc$2.end(); + const enc$4 = new Asn1SequenceEncoder(); + enc$4.add(f); + const f3 = enc$4.end(Buffer.from([0x04])); + enc.add(f3); + const der = enc.end(); + const keyObject = createPrivateKey({ key: der, format: 'der', type: 'pkcs8' }); + setCurve(keyObject, jwk.crv); + return keyObject; + } + const enc$1 = new Asn1SequenceEncoder(); + enc$1.oidFor('ecPublicKey'); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + enc.bitStr(pub); + const der = enc.end(); + const keyObject = createPublicKey({ key: der, format: 'der', type: 'spki' }); + setCurve(keyObject, jwk.crv); + return keyObject; + } + case 'OKP': { + const enc = new Asn1SequenceEncoder(); + const isPrivate = jwk.d !== undefined; + if (isPrivate) { + enc.zero(); + const enc$1 = new Asn1SequenceEncoder(); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + const enc$2 = new Asn1SequenceEncoder(); + enc$2.octStr(Buffer.from(jwk.d, 'base64')); + const f = enc$2.end(Buffer.from([0x04])); + enc.add(f); + const der = enc.end(); + return createPrivateKey({ key: der, format: 'der', type: 'pkcs8' }); + } + const enc$1 = new Asn1SequenceEncoder(); + enc$1.oidFor(jwk.crv); + enc.add(enc$1.end()); + enc.bitStr(Buffer.from(jwk.x, 'base64')); + const der = enc.end(); + return createPublicKey({ key: der, format: 'der', type: 'spki' }); + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); + } +}; +export default parse; diff --git a/dist/node/esm/runtime/key_to_jwk.js b/dist/node/esm/runtime/key_to_jwk.js new file mode 100644 index 0000000000..755564cbb3 --- /dev/null +++ b/dist/node/esm/runtime/key_to_jwk.js @@ -0,0 +1,158 @@ +import { KeyObject, createPublicKey } from 'crypto'; +import { encode as base64url } from './base64url.js'; +import Asn1SequenceDecoder from './asn1_sequence_decoder.js'; +import { JOSENotSupported } from '../util/errors.js'; +import getNamedCurve from './get_named_curve.js'; +import { isCryptoKey } from './webcrypto.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +import { jwkExport } from './flags.js'; +const keyToJWK = (key) => { + let keyObject; + if (isCryptoKey(key)) { + if (!key.extractable) { + throw new TypeError('CryptoKey is not extractable'); + } + keyObject = KeyObject.from(key); + } + else if (isKeyObject(key)) { + keyObject = key; + } + else if (key instanceof Uint8Array) { + return { + kty: 'oct', + k: base64url(key), + }; + } + else { + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); + } + if (jwkExport) { + if (keyObject.type !== 'secret' && + !['rsa', 'ec', 'ed25519', 'x25519', 'ed448', 'x448'].includes(keyObject.asymmetricKeyType)) { + throw new JOSENotSupported('Unsupported key asymmetricKeyType'); + } + return keyObject.export({ format: 'jwk' }); + } + switch (keyObject.type) { + case 'secret': + return { + kty: 'oct', + k: base64url(keyObject.export()), + }; + case 'private': + case 'public': { + switch (keyObject.asymmetricKeyType) { + case 'rsa': { + const der = keyObject.export({ format: 'der', type: 'pkcs1' }); + const dec = new Asn1SequenceDecoder(der); + if (keyObject.type === 'private') { + dec.unsignedInteger(); + } + const n = base64url(dec.unsignedInteger()); + const e = base64url(dec.unsignedInteger()); + let jwk; + if (keyObject.type === 'private') { + jwk = { + d: base64url(dec.unsignedInteger()), + p: base64url(dec.unsignedInteger()), + q: base64url(dec.unsignedInteger()), + dp: base64url(dec.unsignedInteger()), + dq: base64url(dec.unsignedInteger()), + qi: base64url(dec.unsignedInteger()), + }; + } + dec.end(); + return { kty: 'RSA', n, e, ...jwk }; + } + case 'ec': { + const crv = getNamedCurve(keyObject); + let len; + let offset; + let correction; + switch (crv) { + case 'secp256k1': + len = 64; + offset = 31 + 2; + correction = -1; + break; + case 'P-256': + len = 64; + offset = 34 + 2; + correction = -1; + break; + case 'P-384': + len = 96; + offset = 33 + 2; + correction = -3; + break; + case 'P-521': + len = 132; + offset = 33 + 2; + correction = -3; + break; + default: + throw new JOSENotSupported('Unsupported curve'); + } + if (keyObject.type === 'public') { + const der = keyObject.export({ type: 'spki', format: 'der' }); + return { + kty: 'EC', + crv, + x: base64url(der.subarray(-len, -len / 2)), + y: base64url(der.subarray(-len / 2)), + }; + } + const der = keyObject.export({ type: 'pkcs8', format: 'der' }); + if (der.length < 100) { + offset += correction; + } + return { + ...keyToJWK(createPublicKey(keyObject)), + d: base64url(der.subarray(offset, offset + len / 2)), + }; + } + case 'ed25519': + case 'x25519': { + const crv = getNamedCurve(keyObject); + if (keyObject.type === 'public') { + const der = keyObject.export({ type: 'spki', format: 'der' }); + return { + kty: 'OKP', + crv, + x: base64url(der.subarray(-32)), + }; + } + const der = keyObject.export({ type: 'pkcs8', format: 'der' }); + return { + ...keyToJWK(createPublicKey(keyObject)), + d: base64url(der.subarray(-32)), + }; + } + case 'ed448': + case 'x448': { + const crv = getNamedCurve(keyObject); + if (keyObject.type === 'public') { + const der = keyObject.export({ type: 'spki', format: 'der' }); + return { + kty: 'OKP', + crv, + x: base64url(der.subarray(crv === 'Ed448' ? -57 : -56)), + }; + } + const der = keyObject.export({ type: 'pkcs8', format: 'der' }); + return { + ...keyToJWK(createPublicKey(keyObject)), + d: base64url(der.subarray(crv === 'Ed448' ? -57 : -56)), + }; + } + default: + throw new JOSENotSupported('Unsupported key asymmetricKeyType'); + } + } + default: + throw new JOSENotSupported('Unsupported key type'); + } +}; +export default keyToJWK; diff --git a/dist/node/esm/runtime/node_key.js b/dist/node/esm/runtime/node_key.js new file mode 100644 index 0000000000..3535dd8d67 --- /dev/null +++ b/dist/node/esm/runtime/node_key.js @@ -0,0 +1,75 @@ +import { constants } from 'crypto'; +import getNamedCurve from './get_named_curve.js'; +import { JOSENotSupported } from '../util/errors.js'; +import checkModulusLength from './check_modulus_length.js'; +import { rsaPssParams } from './flags.js'; +const PSS = { + padding: constants.RSA_PKCS1_PSS_PADDING, + saltLength: constants.RSA_PSS_SALTLEN_DIGEST, +}; +const ecCurveAlgMap = new Map([ + ['ES256', 'P-256'], + ['ES256K', 'secp256k1'], + ['ES384', 'P-384'], + ['ES512', 'P-521'], +]); +export default function keyForCrypto(alg, key) { + switch (alg) { + case 'EdDSA': + if (!['ed25519', 'ed448'].includes(key.asymmetricKeyType)) { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ed25519 or ed448'); + } + return key; + case 'RS256': + case 'RS384': + case 'RS512': + if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); + } + checkModulusLength(key, alg); + return key; + case rsaPssParams && 'PS256': + case rsaPssParams && 'PS384': + case rsaPssParams && 'PS512': + if (key.asymmetricKeyType === 'rsa-pss') { + const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails; + const length = parseInt(alg.slice(-3), 10); + if (hashAlgorithm !== undefined && + (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm)) { + throw new TypeError(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${alg}`); + } + if (saltLength !== undefined && saltLength > length >> 3) { + throw new TypeError(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of "alg" ${alg}`); + } + } + else if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa or rsa-pss'); + } + checkModulusLength(key, alg); + return { key, ...PSS }; + case !rsaPssParams && 'PS256': + case !rsaPssParams && 'PS384': + case !rsaPssParams && 'PS512': + if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); + } + checkModulusLength(key, alg); + return { key, ...PSS }; + case 'ES256': + case 'ES256K': + case 'ES384': + case 'ES512': { + if (key.asymmetricKeyType !== 'ec') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ec'); + } + const actual = getNamedCurve(key); + const expected = ecCurveAlgMap.get(alg); + if (actual !== expected) { + throw new TypeError(`Invalid key curve for the algorithm, its curve must be ${expected}, got ${actual}`); + } + return { dsaEncoding: 'ieee-p1363', key }; + } + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } +} diff --git a/dist/node/esm/runtime/pbes2kw.js b/dist/node/esm/runtime/pbes2kw.js new file mode 100644 index 0000000000..63122e04ef --- /dev/null +++ b/dist/node/esm/runtime/pbes2kw.js @@ -0,0 +1,43 @@ +import { promisify } from 'util'; +import { KeyObject, pbkdf2 as pbkdf2cb } from 'crypto'; +import random from './random.js'; +import { p2s as concatSalt } from '../lib/buffer_utils.js'; +import { encode as base64url } from './base64url.js'; +import { wrap, unwrap } from './aeskw.js'; +import checkP2s from '../lib/check_p2s.js'; +import { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +const pbkdf2 = promisify(pbkdf2cb); +function getPassword(key, alg) { + if (isKeyObject(key)) { + return key.export(); + } + if (key instanceof Uint8Array) { + return key; + } + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey'); + return KeyObject.from(key).export(); + } + throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array')); +} +export const encrypt = async (alg, key, cek, p2c = 2048, p2s = random(new Uint8Array(16))) => { + checkP2s(p2s); + const salt = concatSalt(alg, p2s); + const keylen = parseInt(alg.slice(13, 16), 10) >> 3; + const password = getPassword(key, alg); + const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); + const encryptedKey = await wrap(alg.slice(-6), derivedKey, cek); + return { encryptedKey, p2c, p2s: base64url(p2s) }; +}; +export const decrypt = async (alg, key, encryptedKey, p2c, p2s) => { + checkP2s(p2s); + const salt = concatSalt(alg, p2s); + const keylen = parseInt(alg.slice(13, 16), 10) >> 3; + const password = getPassword(key, alg); + const derivedKey = await pbkdf2(password, salt, p2c, keylen, `sha${alg.slice(8, 11)}`); + return unwrap(alg.slice(-6), derivedKey, encryptedKey); +}; diff --git a/dist/node/esm/runtime/random.js b/dist/node/esm/runtime/random.js new file mode 100644 index 0000000000..80478ea946 --- /dev/null +++ b/dist/node/esm/runtime/random.js @@ -0,0 +1 @@ +export { randomFillSync as default } from 'crypto'; diff --git a/dist/node/esm/runtime/rsaes.js b/dist/node/esm/runtime/rsaes.js new file mode 100644 index 0000000000..3556fe3436 --- /dev/null +++ b/dist/node/esm/runtime/rsaes.js @@ -0,0 +1,64 @@ +import { KeyObject, publicEncrypt, constants, privateDecrypt } from 'crypto'; +import checkModulusLength from './check_modulus_length.js'; +import { isCryptoKey } from './webcrypto.js'; +import { checkEncCryptoKey } from '../lib/crypto_key.js'; +import isKeyObject from './is_key_object.js'; +import invalidKeyInput from '../lib/invalid_key_input.js'; +import { types } from './is_key_like.js'; +const checkKey = (key, alg) => { + if (key.asymmetricKeyType !== 'rsa') { + throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa'); + } + checkModulusLength(key, alg); +}; +const resolvePadding = (alg) => { + switch (alg) { + case 'RSA-OAEP': + case 'RSA-OAEP-256': + case 'RSA-OAEP-384': + case 'RSA-OAEP-512': + return constants.RSA_PKCS1_OAEP_PADDING; + case 'RSA1_5': + return constants.RSA_PKCS1_PADDING; + default: + return undefined; + } +}; +const resolveOaepHash = (alg) => { + switch (alg) { + case 'RSA-OAEP': + return 'sha1'; + case 'RSA-OAEP-256': + return 'sha256'; + case 'RSA-OAEP-384': + return 'sha384'; + case 'RSA-OAEP-512': + return 'sha512'; + default: + return undefined; + } +}; +function ensureKeyObject(key, alg, ...usages) { + if (isKeyObject(key)) { + return key; + } + if (isCryptoKey(key)) { + checkEncCryptoKey(key, alg, ...usages); + return KeyObject.from(key); + } + throw new TypeError(invalidKeyInput(key, ...types)); +} +export const encrypt = (alg, key, cek) => { + const padding = resolvePadding(alg); + const oaepHash = resolveOaepHash(alg); + const keyObject = ensureKeyObject(key, alg, 'wrapKey', 'encrypt'); + checkKey(keyObject, alg); + return publicEncrypt({ key: keyObject, oaepHash, padding }, cek); +}; +export const decrypt = (alg, key, encryptedKey) => { + const padding = resolvePadding(alg); + const oaepHash = resolveOaepHash(alg); + const keyObject = ensureKeyObject(key, alg, 'unwrapKey', 'decrypt'); + checkKey(keyObject, alg); + return privateDecrypt({ key: keyObject, oaepHash, padding }, encryptedKey); +}; diff --git a/dist/node/esm/runtime/sign.js b/dist/node/esm/runtime/sign.js new file mode 100644 index 0000000000..8902d4151c --- /dev/null +++ b/dist/node/esm/runtime/sign.js @@ -0,0 +1,23 @@ +import * as crypto from 'crypto'; +import { promisify } from 'util'; +import nodeDigest from './dsa_digest.js'; +import hmacDigest from './hmac_digest.js'; +import nodeKey from './node_key.js'; +import getSignKey from './get_sign_verify_key.js'; +let oneShotSign; +if (crypto.sign.length > 3) { + oneShotSign = promisify(crypto.sign); +} +else { + oneShotSign = crypto.sign; +} +const sign = async (alg, key, data) => { + const keyObject = getSignKey(alg, key, 'sign'); + if (alg.startsWith('HS')) { + const hmac = crypto.createHmac(hmacDigest(alg), keyObject); + hmac.update(data); + return hmac.digest(); + } + return oneShotSign(nodeDigest(alg), data, nodeKey(alg, keyObject)); +}; +export default sign; diff --git a/dist/node/esm/runtime/timing_safe_equal.js b/dist/node/esm/runtime/timing_safe_equal.js new file mode 100644 index 0000000000..901ae38bdd --- /dev/null +++ b/dist/node/esm/runtime/timing_safe_equal.js @@ -0,0 +1,3 @@ +import { timingSafeEqual as impl } from 'crypto'; +const timingSafeEqual = impl; +export default timingSafeEqual; diff --git a/dist/node/esm/runtime/verify.js b/dist/node/esm/runtime/verify.js new file mode 100644 index 0000000000..e514e1c452 --- /dev/null +++ b/dist/node/esm/runtime/verify.js @@ -0,0 +1,36 @@ +import * as crypto from 'crypto'; +import { promisify } from 'util'; +import nodeDigest from './dsa_digest.js'; +import nodeKey from './node_key.js'; +import sign from './sign.js'; +import getVerifyKey from './get_sign_verify_key.js'; +import { oneShotCallback } from './flags.js'; +let oneShotVerify; +if (crypto.verify.length > 4 && oneShotCallback) { + oneShotVerify = promisify(crypto.verify); +} +else { + oneShotVerify = crypto.verify; +} +const verify = async (alg, key, signature, data) => { + const keyObject = getVerifyKey(alg, key, 'verify'); + if (alg.startsWith('HS')) { + const expected = await sign(alg, keyObject, data); + const actual = signature; + try { + return crypto.timingSafeEqual(actual, expected); + } + catch { + return false; + } + } + const algorithm = nodeDigest(alg); + const keyInput = nodeKey(alg, keyObject); + try { + return await oneShotVerify(algorithm, data, keyInput, signature); + } + catch { + return false; + } +}; +export default verify; diff --git a/dist/node/esm/runtime/webcrypto.js b/dist/node/esm/runtime/webcrypto.js new file mode 100644 index 0000000000..a2fdb2a7a1 --- /dev/null +++ b/dist/node/esm/runtime/webcrypto.js @@ -0,0 +1,8 @@ +import * as crypto from 'crypto'; +import * as util from 'util'; +const webcrypto = crypto.webcrypto; +export default webcrypto; +export const isCryptoKey = util.types.isCryptoKey + ? (key) => util.types.isCryptoKey(key) + : + (key) => false; diff --git a/dist/node/esm/runtime/zlib.js b/dist/node/esm/runtime/zlib.js new file mode 100644 index 0000000000..8bb72cbf18 --- /dev/null +++ b/dist/node/esm/runtime/zlib.js @@ -0,0 +1,6 @@ +import { promisify } from 'util'; +import { inflateRaw as inflateRawCb, deflateRaw as deflateRawCb } from 'zlib'; +const inflateRaw = promisify(inflateRawCb); +const deflateRaw = promisify(deflateRawCb); +export const inflate = (input) => inflateRaw(input); +export const deflate = (input) => deflateRaw(input); diff --git a/dist/node/esm/util/base64url.js b/dist/node/esm/util/base64url.js new file mode 100644 index 0000000000..88ce7556d6 --- /dev/null +++ b/dist/node/esm/util/base64url.js @@ -0,0 +1,3 @@ +import * as base64url from '../runtime/base64url.js'; +export const encode = base64url.encode; +export const decode = base64url.decode; diff --git a/dist/node/esm/util/decode_jwt.js b/dist/node/esm/util/decode_jwt.js new file mode 100644 index 0000000000..0b824ed580 --- /dev/null +++ b/dist/node/esm/util/decode_jwt.js @@ -0,0 +1,32 @@ +import { decode as base64url } from './base64url.js'; +import { decoder } from '../lib/buffer_utils.js'; +import isObject from '../lib/is_object.js'; +import { JWTInvalid } from './errors.js'; +export function decodeJwt(jwt) { + if (typeof jwt !== 'string') + throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string'); + const { 1: payload, length } = jwt.split('.'); + if (length === 5) + throw new JWTInvalid('Only JWTs using Compact JWS serialization can be decoded'); + if (length !== 3) + throw new JWTInvalid('Invalid JWT'); + if (!payload) + throw new JWTInvalid('JWTs must contain a payload'); + let decoded; + try { + decoded = base64url(payload); + } + catch { + throw new JWTInvalid('Failed to parse the base64url encoded payload'); + } + let result; + try { + result = JSON.parse(decoder.decode(decoded)); + } + catch { + throw new JWTInvalid('Failed to parse the decoded payload as JSON'); + } + if (!isObject(result)) + throw new JWTInvalid('Invalid JWT Claims Set'); + return result; +} diff --git a/dist/node/esm/util/decode_protected_header.js b/dist/node/esm/util/decode_protected_header.js new file mode 100644 index 0000000000..04be31d8f2 --- /dev/null +++ b/dist/node/esm/util/decode_protected_header.js @@ -0,0 +1,34 @@ +import { decode as base64url } from './base64url.js'; +import { decoder } from '../lib/buffer_utils.js'; +import isObject from '../lib/is_object.js'; +export function decodeProtectedHeader(token) { + let protectedB64u; + if (typeof token === 'string') { + const parts = token.split('.'); + if (parts.length === 3 || parts.length === 5) { + ; + [protectedB64u] = parts; + } + } + else if (typeof token === 'object' && token) { + if ('protected' in token) { + protectedB64u = token.protected; + } + else { + throw new TypeError('Token does not contain a Protected Header'); + } + } + try { + if (typeof protectedB64u !== 'string' || !protectedB64u) { + throw new Error(); + } + const result = JSON.parse(decoder.decode(base64url(protectedB64u))); + if (!isObject(result)) { + throw new Error(); + } + return result; + } + catch { + throw new TypeError('Invalid Token or Protected Header formatting'); + } +} diff --git a/dist/node/esm/util/errors.js b/dist/node/esm/util/errors.js new file mode 100644 index 0000000000..13a36f58fa --- /dev/null +++ b/dist/node/esm/util/errors.js @@ -0,0 +1,148 @@ +export class JOSEError extends Error { + static get code() { + return 'ERR_JOSE_GENERIC'; + } + constructor(message) { + var _a; + super(message); + this.code = 'ERR_JOSE_GENERIC'; + this.name = this.constructor.name; + (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor); + } +} +export class JWTClaimValidationFailed extends JOSEError { + static get code() { + return 'ERR_JWT_CLAIM_VALIDATION_FAILED'; + } + constructor(message, claim = 'unspecified', reason = 'unspecified') { + super(message); + this.code = 'ERR_JWT_CLAIM_VALIDATION_FAILED'; + this.claim = claim; + this.reason = reason; + } +} +export class JWTExpired extends JOSEError { + static get code() { + return 'ERR_JWT_EXPIRED'; + } + constructor(message, claim = 'unspecified', reason = 'unspecified') { + super(message); + this.code = 'ERR_JWT_EXPIRED'; + this.claim = claim; + this.reason = reason; + } +} +export class JOSEAlgNotAllowed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JOSE_ALG_NOT_ALLOWED'; + } + static get code() { + return 'ERR_JOSE_ALG_NOT_ALLOWED'; + } +} +export class JOSENotSupported extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JOSE_NOT_SUPPORTED'; + } + static get code() { + return 'ERR_JOSE_NOT_SUPPORTED'; + } +} +export class JWEDecryptionFailed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWE_DECRYPTION_FAILED'; + this.message = 'decryption operation failed'; + } + static get code() { + return 'ERR_JWE_DECRYPTION_FAILED'; + } +} +export class JWEInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWE_INVALID'; + } + static get code() { + return 'ERR_JWE_INVALID'; + } +} +export class JWSInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWS_INVALID'; + } + static get code() { + return 'ERR_JWS_INVALID'; + } +} +export class JWTInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWT_INVALID'; + } + static get code() { + return 'ERR_JWT_INVALID'; + } +} +export class JWKInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWK_INVALID'; + } + static get code() { + return 'ERR_JWK_INVALID'; + } +} +export class JWKSInvalid extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_INVALID'; + } + static get code() { + return 'ERR_JWKS_INVALID'; + } +} +export class JWKSNoMatchingKey extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_NO_MATCHING_KEY'; + this.message = 'no applicable key found in the JSON Web Key Set'; + } + static get code() { + return 'ERR_JWKS_NO_MATCHING_KEY'; + } +} +export class JWKSMultipleMatchingKeys extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; + this.message = 'multiple matching keys found in the JSON Web Key Set'; + } + static get code() { + return 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; + } +} +Symbol.asyncIterator; +export class JWKSTimeout extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWKS_TIMEOUT'; + this.message = 'request timed out'; + } + static get code() { + return 'ERR_JWKS_TIMEOUT'; + } +} +export class JWSSignatureVerificationFailed extends JOSEError { + constructor() { + super(...arguments); + this.code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; + this.message = 'signature verification failed'; + } + static get code() { + return 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; + } +} diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts new file mode 100644 index 0000000000..6ce928e73a --- /dev/null +++ b/dist/types/index.d.ts @@ -0,0 +1,47 @@ +export { compactDecrypt } from './jwe/compact/decrypt'; +export type { CompactDecryptGetKey } from './jwe/compact/decrypt'; +export { flattenedDecrypt } from './jwe/flattened/decrypt'; +export type { FlattenedDecryptGetKey } from './jwe/flattened/decrypt'; +export { generalDecrypt } from './jwe/general/decrypt'; +export type { GeneralDecryptGetKey } from './jwe/general/decrypt'; +export { GeneralEncrypt } from './jwe/general/encrypt'; +export type { Recipient } from './jwe/general/encrypt'; +export { compactVerify } from './jws/compact/verify'; +export type { CompactVerifyGetKey } from './jws/compact/verify'; +export { flattenedVerify } from './jws/flattened/verify'; +export type { FlattenedVerifyGetKey } from './jws/flattened/verify'; +export { generalVerify } from './jws/general/verify'; +export type { GeneralVerifyGetKey } from './jws/general/verify'; +export { jwtVerify } from './jwt/verify'; +export type { JWTVerifyOptions, JWTVerifyGetKey } from './jwt/verify'; +export { jwtDecrypt } from './jwt/decrypt'; +export type { JWTDecryptOptions, JWTDecryptGetKey } from './jwt/decrypt'; +export type { ProduceJWT } from './jwt/produce'; +export { CompactEncrypt } from './jwe/compact/encrypt'; +export { FlattenedEncrypt } from './jwe/flattened/encrypt'; +export { CompactSign } from './jws/compact/sign'; +export { FlattenedSign } from './jws/flattened/sign'; +export { GeneralSign } from './jws/general/sign'; +export type { Signature } from './jws/general/sign'; +export { SignJWT } from './jwt/sign'; +export { EncryptJWT } from './jwt/encrypt'; +export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint'; +export { EmbeddedJWK } from './jwk/embedded'; +export { createLocalJWKSet } from './jwks/local'; +export { createRemoteJWKSet } from './jwks/remote'; +export type { RemoteJWKSetOptions } from './jwks/remote'; +export { UnsecuredJWT } from './jwt/unsecured'; +export type { UnsecuredResult } from './jwt/unsecured'; +export { exportPKCS8, exportSPKI, exportJWK } from './key/export'; +export { importSPKI, importPKCS8, importX509, importJWK } from './key/import'; +export type { PEMImportOptions } from './key/import'; +export { decodeProtectedHeader } from './util/decode_protected_header'; +export { decodeJwt } from './util/decode_jwt'; +export type { ProtectedHeaderParameters } from './util/decode_protected_header'; +export * as errors from './util/errors'; +export { generateKeyPair } from './key/generate_key_pair'; +export type { GenerateKeyPairResult, GenerateKeyPairOptions } from './key/generate_key_pair'; +export { generateSecret } from './key/generate_secret'; +export type { GenerateSecretOptions } from './key/generate_secret'; +export * as base64url from './util/base64url'; +export type { KeyLike, JWK, FlattenedJWSInput, GeneralJWSInput, FlattenedJWS, GeneralJWS, JoseHeaderParameters, JWSHeaderParameters, JWEKeyManagementHeaderParameters, FlattenedJWE, GeneralJWE, JWEHeaderParameters, CritOption, DeflateOption, DecryptOptions, EncryptOptions, JWTClaimVerificationOptions, VerifyOptions, SignOptions, JWTPayload, DeflateFunction, InflateFunction, FlattenedDecryptResult, GeneralDecryptResult, CompactDecryptResult, FlattenedVerifyResult, GeneralVerifyResult, CompactVerifyResult, JWTVerifyResult, JWTDecryptResult, ResolvedKey, CompactJWEHeaderParameters, CompactJWSHeaderParameters, JWTHeaderParameters, JSONWebKeySet, } from './types'; diff --git a/dist/types/jwe/compact/decrypt.d.ts b/dist/types/jwe/compact/decrypt.d.ts new file mode 100644 index 0000000000..0a37a97656 --- /dev/null +++ b/dist/types/jwe/compact/decrypt.d.ts @@ -0,0 +1,33 @@ +import type { KeyLike, DecryptOptions, CompactJWEHeaderParameters, GetKeyFunction, FlattenedJWE, CompactDecryptResult, ResolvedKey } from '../../types'; +/** + * Interface for Compact JWE Decryption dynamic key resolution. No token components have been + * verified at the time of this function call. + */ +export interface CompactDecryptGetKey extends GetKeyFunction { +} +/** + * Decrypts a Compact JWE. + * + * @example Usage + * + * ```js + * const jwe = + * 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.nyQ19eq9ogh9wA7fFtnI2oouzy5_8b5DeLkoRMfi2yijgfTs2zEnayCEofz_qhnL-nwszabd9qUeHv0-IwvhhJJS7GUJOU3ikiIe42qcIAFme1A_Fo9CTxw4XTOy-I5qanl8So91u6hwfyN1VxAqVLsSE7_23EC-gfGEg_5znew9PyXXsOIE-K_HH7IQowRrlZ1X_bM_Liu53RzDpLDvRz59mp3S8L56YqpM8FexFGTGpEaoTcEIst375qncYt3-79IVR7gZN1RWsWgjPatfvVbnh74PglQcATSf3UUhaW0OAKn6q7r3PDx6DIKQ35bgHQg5QopuN00eIfLQL2trGw.W3grIVj5HVuAb76X.6PcuDe5D6ttWFYyv0oqqdDXfI2R8wBg1F2Q80UUA_Gv8eEimNWfxIWdLxrjzgQGSvIhxmFKuLM0.a93_Ug3uZHuczj70Zavx8Q' + * + * const { plaintext, protectedHeader } = await jose.compactDecrypt(jwe, privateKey) + * + * console.log(protectedHeader) + * console.log(new TextDecoder().decode(plaintext)) + * ``` + * + * @param jwe Compact JWE. + * @param key Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export declare function compactDecrypt(jwe: string | Uint8Array, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise; +/** + * @param jwe Compact JWE. + * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export declare function compactDecrypt(jwe: string | Uint8Array, getKey: CompactDecryptGetKey, options?: DecryptOptions): Promise; diff --git a/dist/types/jwe/compact/encrypt.d.ts b/dist/types/jwe/compact/encrypt.d.ts new file mode 100644 index 0000000000..0f48815a78 --- /dev/null +++ b/dist/types/jwe/compact/encrypt.d.ts @@ -0,0 +1,60 @@ +import type { KeyLike, JWEKeyManagementHeaderParameters, CompactJWEHeaderParameters, EncryptOptions } from '../../types'; +/** + * The CompactEncrypt class is a utility for creating Compact JWE strings. + * + * @example Usage + * + * ```js + * const jwe = await new jose.CompactEncrypt( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) + * .encrypt(publicKey) + * + * console.log(jwe) + * ``` + */ +export declare class CompactEncrypt { + private _flattened; + /** @param plaintext Binary representation of the plaintext to encrypt. */ + constructor(plaintext: Uint8Array); + /** + * Sets a content encryption key to use, by default a random suitable one is generated for the JWE + * enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param cek JWE Content Encryption Key. + */ + setContentEncryptionKey(cek: Uint8Array): this; + /** + * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable + * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param iv JWE Initialization Vector. + */ + setInitializationVector(iv: Uint8Array): this; + /** + * Sets the JWE Protected Header on the CompactEncrypt object. + * + * @param protectedHeader JWE Protected Header object. + */ + setProtectedHeader(protectedHeader: CompactJWEHeaderParameters): this; + /** + * Sets the JWE Key Management parameters to be used when encrypting the Content Encryption Key. + * You do not need to invoke this method, it is only really intended for test and vector + * validation purposes. + * + * @param parameters JWE Key Management parameters. + */ + setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this; + /** + * Encrypts and resolves the value of the Compact JWE string. + * + * @param key Public Key or Secret to encrypt the JWE with. + * @param options JWE Encryption options. + */ + encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise; +} diff --git a/dist/types/jwe/flattened/decrypt.d.ts b/dist/types/jwe/flattened/decrypt.d.ts new file mode 100644 index 0000000000..016ca62bbc --- /dev/null +++ b/dist/types/jwe/flattened/decrypt.d.ts @@ -0,0 +1,43 @@ +import type { FlattenedDecryptResult, KeyLike, FlattenedJWE, JWEHeaderParameters, DecryptOptions, GetKeyFunction, ResolvedKey } from '../../types'; +/** + * Interface for Flattened JWE Decryption dynamic key resolution. No token components have been + * verified at the time of this function call. + */ +export interface FlattenedDecryptGetKey extends GetKeyFunction { +} +/** + * Decrypts a Flattened JWE. + * + * @example Usage + * + * ```js + * const jwe = { + * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', + * iv: '8Fy7A_IuoX5VXG9s', + * tag: 'W76IYV6arGRuDSaSyWrQNg', + * encrypted_key: + * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', + * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', + * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', + * } + * + * const { plaintext, protectedHeader, additionalAuthenticatedData } = + * await jose.flattenedDecrypt(jwe, privateKey) + * + * console.log(protectedHeader) + * const decoder = new TextDecoder() + * console.log(decoder.decode(plaintext)) + * console.log(decoder.decode(additionalAuthenticatedData)) + * ``` + * + * @param jwe Flattened JWE. + * @param key Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export declare function flattenedDecrypt(jwe: FlattenedJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise; +/** + * @param jwe Flattened JWE. + * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export declare function flattenedDecrypt(jwe: FlattenedJWE, getKey: FlattenedDecryptGetKey, options?: DecryptOptions): Promise; diff --git a/dist/types/jwe/flattened/encrypt.d.ts b/dist/types/jwe/flattened/encrypt.d.ts new file mode 100644 index 0000000000..d5d02fdfbb --- /dev/null +++ b/dist/types/jwe/flattened/encrypt.d.ts @@ -0,0 +1,89 @@ +import type { KeyLike, FlattenedJWE, JWEHeaderParameters, JWEKeyManagementHeaderParameters, EncryptOptions } from '../../types'; +/** @private */ +export declare const unprotected: unique symbol; +/** + * The FlattenedEncrypt class is a utility for creating Flattened JWE objects. + * + * @example Usage + * + * ```js + * const jwe = await new jose.FlattenedEncrypt( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) + * .setAdditionalAuthenticatedData(encoder.encode('The Fellowship of the Ring')) + * .encrypt(publicKey) + * + * console.log(jwe) + * ``` + */ +export declare class FlattenedEncrypt { + private _plaintext; + private _protectedHeader; + private _sharedUnprotectedHeader; + private _unprotectedHeader; + private _aad; + private _cek; + private _iv; + private _keyManagementParameters; + /** @param plaintext Binary representation of the plaintext to encrypt. */ + constructor(plaintext: Uint8Array); + /** + * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is + * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or + * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed + * and missing. + * + * @param parameters JWE Key Management parameters. + */ + setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this; + /** + * Sets the JWE Protected Header on the FlattenedEncrypt object. + * + * @param protectedHeader JWE Protected Header. + */ + setProtectedHeader(protectedHeader: JWEHeaderParameters): this; + /** + * Sets the JWE Shared Unprotected Header on the FlattenedEncrypt object. + * + * @param sharedUnprotectedHeader JWE Shared Unprotected Header. + */ + setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters): this; + /** + * Sets the JWE Per-Recipient Unprotected Header on the FlattenedEncrypt object. + * + * @param unprotectedHeader JWE Per-Recipient Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters): this; + /** + * Sets the Additional Authenticated Data on the FlattenedEncrypt object. + * + * @param aad Additional Authenticated Data. + */ + setAdditionalAuthenticatedData(aad: Uint8Array): this; + /** + * Sets a content encryption key to use, by default a random suitable one is generated for the JWE + * enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param cek JWE Content Encryption Key. + */ + setContentEncryptionKey(cek: Uint8Array): this; + /** + * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable + * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param iv JWE Initialization Vector. + */ + setInitializationVector(iv: Uint8Array): this; + /** + * Encrypts and resolves the value of the Flattened JWE object. + * + * @param key Public Key or Secret to encrypt the JWE with. + * @param options JWE Encryption options. + */ + encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise; +} diff --git a/dist/types/jwe/general/decrypt.d.ts b/dist/types/jwe/general/decrypt.d.ts new file mode 100644 index 0000000000..d6efd0ff51 --- /dev/null +++ b/dist/types/jwe/general/decrypt.d.ts @@ -0,0 +1,47 @@ +import type { KeyLike, DecryptOptions, JWEHeaderParameters, GetKeyFunction, FlattenedJWE, GeneralJWE, GeneralDecryptResult, ResolvedKey } from '../../types'; +/** + * Interface for General JWE Decryption dynamic key resolution. No token components have been + * verified at the time of this function call. + */ +export interface GeneralDecryptGetKey extends GetKeyFunction { +} +/** + * Decrypts a General JWE. + * + * @example Usage + * + * ```js + * const jwe = { + * ciphertext: '9EzjFISUyoG-ifC2mSihfP0DPC80yeyrxhTzKt1C_VJBkxeBG0MI4Te61Pk45RAGubUvBpU9jm4', + * iv: '8Fy7A_IuoX5VXG9s', + * tag: 'W76IYV6arGRuDSaSyWrQNg', + * aad: 'VGhlIEZlbGxvd3NoaXAgb2YgdGhlIFJpbmc', + * protected: 'eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0', + * recipients: [ + * { + * encrypted_key: + * 'Z6eD4UK_yFb5ZoKvKkGAdqywEG_m0e4IYo0x8Vf30LAMJcsc-_zSgIeiF82teZyYi2YYduHKoqImk7MRnoPZOlEs0Q5BNK1OgBmSOhCE8DFyqh9Zh48TCTP6lmBQ52naqoUJFMtHzu-0LwZH26hxos0GP3Dt19O379MJB837TdKKa87skq0zHaVLAquRHOBF77GI54Bc7O49d8aOrSu1VEFGMThlW2caspPRiTSePDMDPq7_WGk50izRhB3Asl9wmP9wEeaTrkJKRnQj5ips1SAZ1hDBsqEQKKukxP1HtdcopHV5_qgwU8Hjm5EwSLMluMQuiE6hwlkXGOujZLVizA', + * }, + * ], + * } + * + * const { plaintext, protectedHeader, additionalAuthenticatedData } = + * await jose.generalDecrypt(jwe, privateKey) + * + * console.log(protectedHeader) + * const decoder = new TextDecoder() + * console.log(decoder.decode(plaintext)) + * console.log(decoder.decode(additionalAuthenticatedData)) + * ``` + * + * @param jwe General JWE. + * @param key Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export declare function generalDecrypt(jwe: GeneralJWE, key: KeyLike | Uint8Array, options?: DecryptOptions): Promise; +/** + * @param jwe General JWE. + * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. + * @param options JWE Decryption options. + */ +export declare function generalDecrypt(jwe: GeneralJWE, getKey: GeneralDecryptGetKey, options?: DecryptOptions): Promise; diff --git a/dist/types/jwe/general/encrypt.d.ts b/dist/types/jwe/general/encrypt.d.ts new file mode 100644 index 0000000000..70dee92e94 --- /dev/null +++ b/dist/types/jwe/general/encrypt.d.ts @@ -0,0 +1,74 @@ +import type { KeyLike, GeneralJWE, JWEHeaderParameters, CritOption, DeflateOption } from '../../types'; +export interface Recipient { + /** + * Sets the JWE Per-Recipient Unprotected Header on the Recipient object. + * + * @param unprotectedHeader JWE Per-Recipient Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWEHeaderParameters): Recipient; + /** A shorthand for calling addRecipient() on the enclosing GeneralEncrypt instance */ + addRecipient(...args: Parameters): Recipient; + /** A shorthand for calling encrypt() on the enclosing GeneralEncrypt instance */ + encrypt(...args: Parameters): Promise; + /** Returns the enclosing GeneralEncrypt */ + done(): GeneralEncrypt; +} +/** + * The GeneralEncrypt class is a utility for creating General JWE objects. + * + * @example Usage + * + * ```js + * const jwe = await new jose.GeneralEncrypt( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ enc: 'A256GCM' }) + * .addRecipient(ecPublicKey) + * .setUnprotectedHeader({ alg: 'ECDH-ES+A256KW' }) + * .addRecipient(rsaPublicKey) + * .setUnprotectedHeader({ alg: 'RSA-OAEP-384' }) + * .encrypt() + * + * console.log(jwe) + * ``` + */ +export declare class GeneralEncrypt { + private _plaintext; + private _recipients; + private _protectedHeader; + private _unprotectedHeader; + private _aad; + /** @param plaintext Binary representation of the plaintext to encrypt. */ + constructor(plaintext: Uint8Array); + /** + * Adds an additional recipient for the General JWE object. + * + * @param key Public Key or Secret to encrypt the Content Encryption Key for the recipient with. + * @param options JWE Encryption options. + */ + addRecipient(key: KeyLike | Uint8Array, options?: CritOption): Recipient; + /** + * Sets the JWE Protected Header on the GeneralEncrypt object. + * + * @param protectedHeader JWE Protected Header object. + */ + setProtectedHeader(protectedHeader: JWEHeaderParameters): this; + /** + * Sets the JWE Shared Unprotected Header on the GeneralEncrypt object. + * + * @param sharedUnprotectedHeader JWE Shared Unprotected Header object. + */ + setSharedUnprotectedHeader(sharedUnprotectedHeader: JWEHeaderParameters): this; + /** + * Sets the Additional Authenticated Data on the GeneralEncrypt object. + * + * @param aad Additional Authenticated Data. + */ + setAdditionalAuthenticatedData(aad: Uint8Array): this; + /** + * Encrypts and resolves the value of the General JWE object. + * + * @param options JWE Encryption options. + */ + encrypt(options?: DeflateOption): Promise; +} diff --git a/dist/types/jwk/embedded.d.ts b/dist/types/jwk/embedded.d.ts new file mode 100644 index 0000000000..d5756b3d18 --- /dev/null +++ b/dist/types/jwk/embedded.d.ts @@ -0,0 +1,23 @@ +import type { KeyLike, FlattenedJWSInput, JWSHeaderParameters } from '../types'; +/** + * EmbeddedJWK is an implementation of a GetKeyFunction intended to be used with the JWS/JWT verify + * operations whenever you need to opt-in to verify signatures with a public key embedded in the + * token's "jwk" (JSON Web Key) Header Parameter. It is recommended to combine this with the verify + * function's `algorithms` option to define accepted JWS "alg" (Algorithm) Header Parameter values. + * + * @example Usage + * + * ```js + * const jwt = + * 'eyJqd2siOnsiY3J2IjoiUC0yNTYiLCJ4IjoiVU05ZzVuS25aWFlvdldBbE03NmNMejl2VG96UmpfX0NIVV9kT2wtZ09vRSIsInkiOiJkczhhZVF3MWwyY0RDQTdiQ2tPTnZ3REtwWEFidFhqdnFDbGVZSDhXc19VIiwia3R5IjoiRUMifSwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSIsImlhdCI6MTYwNDU4MDc5NH0.60boak3_dErnW47ZPty1C0nrjeVq86EN_eK0GOq6K8w2OA0thKoBxFK4j-NuU9yZ_A9UKGxPT_G87DladBaV9g' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, jose.EmbeddedJWK, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + */ +export declare function EmbeddedJWK(protectedHeader: JWSHeaderParameters, token: FlattenedJWSInput): Promise; diff --git a/dist/types/jwk/thumbprint.d.ts b/dist/types/jwk/thumbprint.d.ts new file mode 100644 index 0000000000..5122dcc3db --- /dev/null +++ b/dist/types/jwk/thumbprint.d.ts @@ -0,0 +1,47 @@ +import type { JWK } from '../types'; +/** + * Calculates a base64url-encoded JSON Web Key (JWK) Thumbprint + * + * @example Usage + * + * ```js + * const thumbprint = await jose.calculateJwkThumbprint({ + * kty: 'EC', + * crv: 'P-256', + * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', + * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', + * }) + * + * console.log(thumbprint) + * // 'w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' + * ``` + * + * @param jwk JSON Web Key. + * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is + * "sha256". + * @see [RFC7638](https://www.rfc-editor.org/rfc/rfc7638) + */ +export declare function calculateJwkThumbprint(jwk: JWK, digestAlgorithm?: 'sha256' | 'sha384' | 'sha512'): Promise; +/** + * Calculates a JSON Web Key (JWK) Thumbprint URI + * + * @example Usage + * + * ```js + * const thumbprintUri = await jose.calculateJwkThumbprintUri({ + * kty: 'EC', + * crv: 'P-256', + * x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo', + * y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww', + * }) + * + * console.log(thumbprint) + * // 'urn:ietf:params:oauth:jwk-thumbprint:sha-256:w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8' + * ``` + * + * @param jwk JSON Web Key. + * @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is + * "sha256". + * @see [RFC9278](https://www.rfc-editor.org/rfc/rfc9278) + */ +export declare function calculateJwkThumbprintUri(jwk: JWK, digestAlgorithm?: 'sha256' | 'sha384' | 'sha512'): Promise; diff --git a/dist/types/jwks/local.d.ts b/dist/types/jwks/local.d.ts new file mode 100644 index 0000000000..79c722c2dd --- /dev/null +++ b/dist/types/jwks/local.d.ts @@ -0,0 +1,85 @@ +import type { KeyLike, JWSHeaderParameters, JSONWebKeySet, FlattenedJWSInput } from '../types'; +/** @private */ +export declare function isJWKSLike(jwks: unknown): jwks is JSONWebKeySet; +/** @private */ +export declare class LocalJWKSet { + protected _jwks?: JSONWebKeySet; + private _cached; + constructor(jwks: unknown); + getKey(protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise; +} +/** + * Returns a function that resolves to a key object from a locally stored, or otherwise available, + * JSON Web Key Set. + * + * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), + * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if + * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key + * Operations) Parameters (if they are present on the JWK). + * + * Only a single public key must match the selection process. As shown in the example below when + * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt + * verification in an iterative manner. + * + * @example Usage + * + * ```js + * const JWKS = jose.createLocalJWKSet({ + * keys: [ + * { + * kty: 'RSA', + * e: 'AQAB', + * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', + * alg: 'PS256', + * }, + * { + * crv: 'P-256', + * kty: 'EC', + * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', + * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', + * alg: 'ES256', + * }, + * ], + * }) + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Opting-in to multiple JWKS matches using `createLocalJWKSet` + * + * ```js + * const options = { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * } + * const { payload, protectedHeader } = await jose + * .jwtVerify(jwt, JWKS, options) + * .catch(async (error) => { + * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { + * for await (const publicKey of error) { + * try { + * return await jose.jwtVerify(jwt, publicKey, options) + * } catch (innerError) { + * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { + * continue + * } + * throw innerError + * } + * } + * throw new jose.errors.JWSSignatureVerificationFailed() + * } + * + * throw error + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwks JSON Web Key Set formatted object. + */ +export declare function createLocalJWKSet(jwks: JSONWebKeySet): (protectedHeader?: JWSHeaderParameters | undefined, token?: FlattenedJWSInput | undefined) => Promise; diff --git a/dist/types/jwks/remote.d.ts b/dist/types/jwks/remote.d.ts new file mode 100644 index 0000000000..a948dd9f91 --- /dev/null +++ b/dist/types/jwks/remote.d.ts @@ -0,0 +1,92 @@ +import type { KeyLike, JWSHeaderParameters, FlattenedJWSInput } from '../types'; +/** Options for the remote JSON Web Key Set. */ +export interface RemoteJWKSetOptions { + /** + * Timeout (in milliseconds) for the HTTP request. When reached the request will be aborted and + * the verification will fail. Default is 5000 (5 seconds). + */ + timeoutDuration?: number; + /** + * Duration (in milliseconds) for which no more HTTP requests will be triggered after a previous + * successful fetch. Default is 30000 (30 seconds). + */ + cooldownDuration?: number; + /** + * Maximum time (in milliseconds) between successful HTTP requests. Default is 600000 (10 + * minutes). + */ + cacheMaxAge?: number | typeof Infinity; + /** + * An instance of [http.Agent](https://nodejs.org/api/http.html#class-httpagent) or + * [https.Agent](https://nodejs.org/api/https.html#class-httpsagent) to pass to the + * [http.get](https://nodejs.org/api/http.html#httpgetoptions-callback) or + * [https.get](https://nodejs.org/api/https.html#httpsgetoptions-callback) method's options. Use + * when behind an http(s) proxy. This is a Node.js runtime specific option, it is ignored when + * used outside of Node.js runtime. + */ + agent?: any; + /** Optional headers to be sent with the HTTP request. */ + headers?: Record; +} +/** + * Returns a function that resolves to a key object downloaded from a remote endpoint returning a + * JSON Web Key Set, that is, for example, an OAuth 2.0 or OIDC jwks_uri. The JSON Web Key Set is + * fetched when no key matches the selection process but only as frequently as the + * `cooldownDuration` option allows to prevent abuse. + * + * It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type), + * then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if + * there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key + * Operations) Parameters (if they are present on the JWK). + * + * Only a single public key must match the selection process. As shown in the example below when + * multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt + * verification in an iterative manner. + * + * @example Usage + * + * ```js + * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Opting-in to multiple JWKS matches using `createRemoteJWKSet` + * + * ```js + * const options = { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * } + * const { payload, protectedHeader } = await jose + * .jwtVerify(jwt, JWKS, options) + * .catch(async (error) => { + * if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { + * for await (const publicKey of error) { + * try { + * return await jose.jwtVerify(jwt, publicKey, options) + * } catch (innerError) { + * if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { + * continue + * } + * throw innerError + * } + * } + * throw new jose.errors.JWSSignatureVerificationFailed() + * } + * + * throw error + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param url URL to fetch the JSON Web Key Set from. + * @param options Options for the remote JSON Web Key Set. + */ +export declare function createRemoteJWKSet(url: URL, options?: RemoteJWKSetOptions): (protectedHeader?: JWSHeaderParameters | undefined, token?: FlattenedJWSInput | undefined) => Promise; diff --git a/dist/types/jws/compact/sign.d.ts b/dist/types/jws/compact/sign.d.ts new file mode 100644 index 0000000000..1edb1790d7 --- /dev/null +++ b/dist/types/jws/compact/sign.d.ts @@ -0,0 +1,34 @@ +import type { CompactJWSHeaderParameters, KeyLike, SignOptions } from '../../types'; +/** + * The CompactSign class is a utility for creating Compact JWS strings. + * + * @example Usage + * + * ```js + * const jws = await new jose.CompactSign( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'ES256' }) + * .sign(privateKey) + * + * console.log(jws) + * ``` + */ +export declare class CompactSign { + private _flattened; + /** @param payload Binary representation of the payload to sign. */ + constructor(payload: Uint8Array); + /** + * Sets the JWS Protected Header on the Sign object. + * + * @param protectedHeader JWS Protected Header. + */ + setProtectedHeader(protectedHeader: CompactJWSHeaderParameters): this; + /** + * Signs and resolves the value of the Compact JWS string. + * + * @param key Private Key or Secret to sign the JWS with. + * @param options JWS Sign options. + */ + sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise; +} diff --git a/dist/types/jws/compact/verify.d.ts b/dist/types/jws/compact/verify.d.ts new file mode 100644 index 0000000000..e164c10447 --- /dev/null +++ b/dist/types/jws/compact/verify.d.ts @@ -0,0 +1,37 @@ +import type { CompactVerifyResult, FlattenedJWSInput, GetKeyFunction, CompactJWSHeaderParameters, KeyLike, VerifyOptions, ResolvedKey } from '../../types'; +/** + * Interface for Compact JWS Verification dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface CompactVerifyGetKey extends GetKeyFunction { +} +/** + * Verifies the signature and format of and afterwards decodes the Compact JWS. + * + * @example Usage + * + * ```js + * const jws = + * 'eyJhbGciOiJFUzI1NiJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4.kkAs_gPPxWMI3rHuVlxHaTPfDWDoqdI8jSvuSmqV-8IHIWXg9mcAeC9ggV-45ZHRbiRJ3obUIFo1rHphPA5URg' + * + * const { payload, protectedHeader } = await jose.compactVerify(jws, publicKey) + * + * console.log(protectedHeader) + * console.log(new TextDecoder().decode(payload)) + * ``` + * + * @param jws Compact JWS. + * @param key Key to verify the JWS with. + * @param options JWS Verify options. + */ +export declare function compactVerify(jws: string | Uint8Array, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise; +/** + * @param jws Compact JWS. + * @param getKey Function resolving a key to verify the JWS with. + * @param options JWS Verify options. + */ +export declare function compactVerify(jws: string | Uint8Array, getKey: CompactVerifyGetKey, options?: VerifyOptions): Promise; diff --git a/dist/types/jws/flattened/sign.d.ts b/dist/types/jws/flattened/sign.d.ts new file mode 100644 index 0000000000..b719e7e1ef --- /dev/null +++ b/dist/types/jws/flattened/sign.d.ts @@ -0,0 +1,42 @@ +import type { KeyLike, FlattenedJWS, JWSHeaderParameters, SignOptions } from '../../types'; +/** + * The FlattenedSign class is a utility for creating Flattened JWS objects. + * + * @example Usage + * + * ```js + * const jws = await new jose.FlattenedSign( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .setProtectedHeader({ alg: 'ES256' }) + * .sign(privateKey) + * + * console.log(jws) + * ``` + */ +export declare class FlattenedSign { + private _payload; + private _protectedHeader; + private _unprotectedHeader; + /** @param payload Binary representation of the payload to sign. */ + constructor(payload: Uint8Array); + /** + * Sets the JWS Protected Header on the FlattenedSign object. + * + * @param protectedHeader JWS Protected Header. + */ + setProtectedHeader(protectedHeader: JWSHeaderParameters): this; + /** + * Sets the JWS Unprotected Header on the FlattenedSign object. + * + * @param unprotectedHeader JWS Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters): this; + /** + * Signs and resolves the value of the Flattened JWS object. + * + * @param key Private Key or Secret to sign the JWS with. + * @param options JWS Sign options. + */ + sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise; +} diff --git a/dist/types/jws/flattened/verify.d.ts b/dist/types/jws/flattened/verify.d.ts new file mode 100644 index 0000000000..b4b7d65d64 --- /dev/null +++ b/dist/types/jws/flattened/verify.d.ts @@ -0,0 +1,42 @@ +import type { FlattenedVerifyResult, KeyLike, FlattenedJWSInput, JWSHeaderParameters, VerifyOptions, GetKeyFunction, ResolvedKey } from '../../types'; +/** + * Interface for Flattened JWS Verification dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface FlattenedVerifyGetKey extends GetKeyFunction { +} +/** + * Verifies the signature and format of and afterwards decodes the Flattened JWS. + * + * @example Usage + * + * ```js + * const decoder = new TextDecoder() + * const jws = { + * signature: + * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', + * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', + * protected: 'eyJhbGciOiJFUzI1NiJ9', + * } + * + * const { payload, protectedHeader } = await jose.flattenedVerify(jws, publicKey) + * + * console.log(protectedHeader) + * console.log(decoder.decode(payload)) + * ``` + * + * @param jws Flattened JWS. + * @param key Key to verify the JWS with. + * @param options JWS Verify options. + */ +export declare function flattenedVerify(jws: FlattenedJWSInput, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise; +/** + * @param jws Flattened JWS. + * @param getKey Function resolving a key to verify the JWS with. + * @param options JWS Verify options. + */ +export declare function flattenedVerify(jws: FlattenedJWSInput, getKey: FlattenedVerifyGetKey, options?: VerifyOptions): Promise; diff --git a/dist/types/jws/general/sign.d.ts b/dist/types/jws/general/sign.d.ts new file mode 100644 index 0000000000..59a765cfef --- /dev/null +++ b/dist/types/jws/general/sign.d.ts @@ -0,0 +1,54 @@ +import type { KeyLike, GeneralJWS, JWSHeaderParameters, SignOptions } from '../../types'; +export interface Signature { + /** + * Sets the JWS Protected Header on the Signature object. + * + * @param protectedHeader JWS Protected Header. + */ + setProtectedHeader(protectedHeader: JWSHeaderParameters): Signature; + /** + * Sets the JWS Unprotected Header on the Signature object. + * + * @param unprotectedHeader JWS Unprotected Header. + */ + setUnprotectedHeader(unprotectedHeader: JWSHeaderParameters): Signature; + /** A shorthand for calling addSignature() on the enclosing GeneralSign instance */ + addSignature(...args: Parameters): Signature; + /** A shorthand for calling encrypt() on the enclosing GeneralSign instance */ + sign(...args: Parameters): Promise; + /** Returns the enclosing GeneralSign */ + done(): GeneralSign; +} +/** + * The GeneralSign class is a utility for creating General JWS objects. + * + * @example Usage + * + * ```js + * const jws = await new jose.GeneralSign( + * new TextEncoder().encode('It’s a dangerous business, Frodo, going out your door.'), + * ) + * .addSignature(ecPrivateKey) + * .setProtectedHeader({ alg: 'ES256' }) + * .addSignature(rsaPrivateKey) + * .setProtectedHeader({ alg: 'PS256' }) + * .sign() + * + * console.log(jws) + * ``` + */ +export declare class GeneralSign { + private _payload; + private _signatures; + /** @param payload Binary representation of the payload to sign. */ + constructor(payload: Uint8Array); + /** + * Adds an additional signature for the General JWS object. + * + * @param key Private Key or Secret to sign the individual JWS signature with. + * @param options JWS Sign options. + */ + addSignature(key: KeyLike | Uint8Array, options?: SignOptions): Signature; + /** Signs and resolves the value of the General JWS object. */ + sign(): Promise; +} diff --git a/dist/types/jws/general/verify.d.ts b/dist/types/jws/general/verify.d.ts new file mode 100644 index 0000000000..3795656add --- /dev/null +++ b/dist/types/jws/general/verify.d.ts @@ -0,0 +1,45 @@ +import type { GeneralJWSInput, GeneralVerifyResult, FlattenedJWSInput, GetKeyFunction, JWSHeaderParameters, KeyLike, VerifyOptions, ResolvedKey } from '../../types'; +/** + * Interface for General JWS Verification dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface GeneralVerifyGetKey extends GetKeyFunction { +} +/** + * Verifies the signature and format of and afterwards decodes the General JWS. + * + * @example Usage + * + * ```js + * const jws = { + * payload: 'SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4', + * signatures: [ + * { + * signature: + * 'FVVOXwj6kD3DqdfD9yYqfT2W9jv-Nop4kOehp_DeDGNB5dQNSPRvntBY6xH3uxlCxE8na9d_kyhYOcanpDJ0EA', + * protected: 'eyJhbGciOiJFUzI1NiJ9', + * }, + * ], + * } + * + * const { payload, protectedHeader } = await jose.generalVerify(jws, publicKey) + * + * console.log(protectedHeader) + * console.log(new TextDecoder().decode(payload)) + * ``` + * + * @param jws General JWS. + * @param key Key to verify the JWS with. + * @param options JWS Verify options. + */ +export declare function generalVerify(jws: GeneralJWSInput, key: KeyLike | Uint8Array, options?: VerifyOptions): Promise; +/** + * @param jws General JWS. + * @param getKey Function resolving a key to verify the JWS with. + * @param options JWS Verify options. + */ +export declare function generalVerify(jws: GeneralJWSInput, getKey: GeneralVerifyGetKey, options?: VerifyOptions): Promise; diff --git a/dist/types/jwt/decrypt.d.ts b/dist/types/jwt/decrypt.d.ts new file mode 100644 index 0000000000..f1d5d4c44e --- /dev/null +++ b/dist/types/jwt/decrypt.d.ts @@ -0,0 +1,41 @@ +import type { KeyLike, DecryptOptions, JWTClaimVerificationOptions, GetKeyFunction, CompactJWEHeaderParameters, FlattenedJWE, JWTDecryptResult, ResolvedKey } from '../types'; +/** Combination of JWE Decryption options and JWT Claims Set verification options. */ +export interface JWTDecryptOptions extends DecryptOptions, JWTClaimVerificationOptions { +} +/** + * Interface for JWT Decryption dynamic key resolution. No token components have been verified at + * the time of this function call. + */ +export interface JWTDecryptGetKey extends GetKeyFunction { +} +/** + * Verifies the JWT format (to be a JWE Compact format), decrypts the ciphertext, validates the JWT + * Claims Set. + * + * @example Usage + * + * ```js + * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') + * const jwt = + * 'eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..MB66qstZBPxAXKdsjet_lA.WHbtJTl4taHp7otOHLq3hBvv0yNPsPEKHYInmCPdDDeyV1kU-f-tGEiU4FxlSqkqAT2hVs8_wMNiQFAzPU1PUgIqWCPsBrPP3TtxYsrtwagpn4SvCsUsx0Mhw9ZhliAO8CLmCBQkqr_T9AcYsz5uZw.7nX9m7BGUu_u1p1qFHzyIg' + * + * const { payload, protectedHeader } = await jose.jwtDecrypt(jwt, secret, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwt JSON Web Token value (encoded as JWE). + * @param key Private Key or Secret to decrypt and verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export declare function jwtDecrypt(jwt: string | Uint8Array, key: KeyLike | Uint8Array, options?: JWTDecryptOptions): Promise; +/** + * @param jwt JSON Web Token value (encoded as JWE). + * @param getKey Function resolving Private Key or Secret to decrypt and verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export declare function jwtDecrypt(jwt: string | Uint8Array, getKey: JWTDecryptGetKey, options?: JWTDecryptOptions): Promise; diff --git a/dist/types/jwt/encrypt.d.ts b/dist/types/jwt/encrypt.d.ts new file mode 100644 index 0000000000..d25808a8a8 --- /dev/null +++ b/dist/types/jwt/encrypt.d.ts @@ -0,0 +1,85 @@ +import type { EncryptOptions, CompactJWEHeaderParameters, JWEKeyManagementHeaderParameters, KeyLike } from '../types'; +import { ProduceJWT } from './produce'; +/** + * The EncryptJWT class is a utility for creating Compact JWE formatted JWT strings. + * + * @example Usage + * + * ```js + * const secret = jose.base64url.decode('zH4NRP1HMALxxCFnRZABFA7GOJtzU_gIj02alfL1lvI') + * const jwt = await new jose.EncryptJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg: 'dir', enc: 'A128CBC-HS256' }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .encrypt(secret) + * + * console.log(jwt) + * ``` + */ +export declare class EncryptJWT extends ProduceJWT { + private _cek; + private _iv; + private _keyManagementParameters; + private _protectedHeader; + private _replicateIssuerAsHeader; + private _replicateSubjectAsHeader; + private _replicateAudienceAsHeader; + /** + * Sets the JWE Protected Header on the EncryptJWT object. + * + * @param protectedHeader JWE Protected Header. Must contain an "alg" (JWE Algorithm) and "enc" + * (JWE Encryption Algorithm) properties. + */ + setProtectedHeader(protectedHeader: CompactJWEHeaderParameters): this; + /** + * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is + * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or + * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed + * and missing. + * + * @param parameters JWE Key Management parameters. + */ + setKeyManagementParameters(parameters: JWEKeyManagementHeaderParameters): this; + /** + * Sets a content encryption key to use, by default a random suitable one is generated for the JWE + * enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param cek JWE Content Encryption Key. + */ + setContentEncryptionKey(cek: Uint8Array): this; + /** + * Sets the JWE Initialization Vector to use for content encryption, by default a random suitable + * one is generated for the JWE enc" (Encryption Algorithm) Header Parameter. + * + * @deprecated You should not use this method. It is only really intended for test and vector + * validation purposes. + * @param iv JWE Initialization Vector. + */ + setInitializationVector(iv: Uint8Array): this; + /** + * Replicates the "iss" (Issuer) Claim as a JWE Protected Header Parameter as per + * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). + */ + replicateIssuerAsHeader(): this; + /** + * Replicates the "sub" (Subject) Claim as a JWE Protected Header Parameter as per + * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). + */ + replicateSubjectAsHeader(): this; + /** + * Replicates the "aud" (Audience) Claim as a JWE Protected Header Parameter as per + * [RFC7519#section-5.3](https://www.rfc-editor.org/rfc/rfc7519#section-5.3). + */ + replicateAudienceAsHeader(): this; + /** + * Encrypts and returns the JWT. + * + * @param key Public Key or Secret to encrypt the JWT with. + * @param options JWE Encryption options. + */ + encrypt(key: KeyLike | Uint8Array, options?: EncryptOptions): Promise; +} diff --git a/dist/types/jwt/produce.d.ts b/dist/types/jwt/produce.d.ts new file mode 100644 index 0000000000..5563a062e5 --- /dev/null +++ b/dist/types/jwt/produce.d.ts @@ -0,0 +1,54 @@ +import type { JWTPayload } from '../types'; +/** Generic class for JWT producing. */ +export declare class ProduceJWT { + protected _payload: JWTPayload; + /** @param payload The JWT Claims Set object. */ + constructor(payload: JWTPayload); + /** + * Set "iss" (Issuer) Claim. + * + * @param issuer "Issuer" Claim value to set on the JWT Claims Set. + */ + setIssuer(issuer: string): this; + /** + * Set "sub" (Subject) Claim. + * + * @param subject "sub" (Subject) Claim value to set on the JWT Claims Set. + */ + setSubject(subject: string): this; + /** + * Set "aud" (Audience) Claim. + * + * @param audience "aud" (Audience) Claim value to set on the JWT Claims Set. + */ + setAudience(audience: string | string[]): this; + /** + * Set "jti" (JWT ID) Claim. + * + * @param jwtId "jti" (JWT ID) Claim value to set on the JWT Claims Set. + */ + setJti(jwtId: string): this; + /** + * Set "nbf" (Not Before) Claim. + * + * @param input "nbf" (Not Before) Claim value to set on the JWT Claims Set. When number is passed + * that is used as a value, when string is passed it is resolved to a time span and added to the + * current timestamp. + */ + setNotBefore(input: number | string): this; + /** + * Set "exp" (Expiration Time) Claim. + * + * @param input "exp" (Expiration Time) Claim value to set on the JWT Claims Set. When number is + * passed that is used as a value, when string is passed it is resolved to a time span and added + * to the current timestamp. + */ + setExpirationTime(input: number | string): this; + /** + * Set "iat" (Issued At) Claim. + * + * @param input "iat" (Issued At) Claim value to set on the JWT Claims Set. Default is current + * timestamp. + */ + setIssuedAt(input?: number): this; +} diff --git a/dist/types/jwt/sign.d.ts b/dist/types/jwt/sign.d.ts new file mode 100644 index 0000000000..976ee16754 --- /dev/null +++ b/dist/types/jwt/sign.d.ts @@ -0,0 +1,113 @@ +import type { JWTHeaderParameters, KeyLike, SignOptions } from '../types'; +import { ProduceJWT } from './produce'; +/** + * The SignJWT class is a utility for creating Compact JWS formatted JWT strings. + * + * @example Usage with a symmetric secret + * + * ```js + * const secret = new TextEncoder().encode( + * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', + * ) + * const alg = 'HS256' + * + * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .sign(secret) + * + * console.log(jwt) + * ``` + * + * @example Usage with a private PKCS#8 encoded RSA key + * + * ```js + * const alg = 'RS256' + * const pkcs8 = `-----BEGIN PRIVATE KEY----- + * MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCFg4UrY5xtulv + * /NXKmL1J4qI1SopAfTNMo3X7p+kJO7plqUYjzaztcre1qfh0m33Sm1Q8oPbO/GpP + * MU1/HgcceytgJ/b4UwufVVMl9BrMDYG8moDBylbVupFQS3Ly1L9i/iFG9Z9A9xzY + * Zzf799A45bnvNXL6s2glzvjiRvfQ2NDF0anTcnZLcYtC7ugq1IMM+ihAcPfw8Qw2 + * chN/SmP4qAM+PKaQwagmU7doqmmyN9u38AfoYZ1GCFhEs5TBBT6H6h9YdHeVtiIq + * 1c+fl03biSIfLrV7dUBD39gBmXBcL/30Ya3D82mCEUC4zg/UkOfQOmkmV3Lc8YUL + * QZ8EJkBLAgMBAAECggEAVuVE/KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34ls + * VOPK0XDegZkhAybMZHjRhp+gwVxX5ChC+J3cUpOBH5FNxElgW6HizD2Jcq6t6LoL + * YgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG/qJV1K00/Ly1G1QKoBffEs + * +v4fAMJrCbUdCz1qWto+PU+HLMEo+krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq/ + * aAP4a1SXmo+j0cvRU4W5Fj0RVwNesIpetX2ZFz4p/JmB5sWFEj/fC7h5z2lq+6Bm + * e2T3BHtXkIxoBW0/pYVnASC8P2puO5FnVxDmWuHDYQKBgQDTuuBd3+0tSFVEX+DU + * 5qpFmHm5nyGItZRJTS+71yg5pBxq1KqNCUjAtbxR0q//fwauakh+BwRVCPOrqsUG + * jBSb3NYE70Srp6elqxgkE54PwQx4Mr6exJPnseM9U4K+hULllf5yjM9edreJE1nV + * NVgFjeyafQhrHKwgr7PERJ/ikwKBgQDqqsT1M+EJLmI1HtCspOG6cu7q3gf/wKRh + * E8tu84i3YyBnI8uJkKy92RNVI5fvpBARe3tjSdM25rr2rcrcmF/5g6Q9ImxZPGCt + * 86eOgO9ErNtbc4TEgybsP319UE4O41aKeNiBTAZKoYCxv/dMqG0j4avmWzd+foHq + * gSNUvR2maQKBgQCYeqOsV2B6VPY7KIVFLd0AA9/dwvEmgAYLiA/RShDI+hwQ/5jX + * uxDu37KAhqeC65sHLrmIMUt4Zdr+DRyZK3aIDNEAesPMjw/X6lCXYp1ZISD2yyym + * MFGH8X8CIkstI9Faf9vf6PJKSFrC1/HA7wq17VCwrUzLvrljTMW8meM/CwKBgCpo + * 2leGHLFQFKeM/iF1WuYbR1pi7gcmhY6VyTowARFDdOOu8GXYI5/bz0afvCGvAMho + * DJCREv7lC/zww6zCTPYG+HOj+PjXlJFba3ixjIxYwPvyEJiDK1Ge18sB7Fl8dHNq + * C5ayaqCqN1voWYUdGzxU2IA1E/5kVo5O8FesJeOhAoGBAImJbZFf+D5kA32Xxhac + * 59lLWBCsocvvbd1cvDMNlRywAAyhsCb1SuX4nEAK9mrSBdfmoF2Nm3eilfsOds0f + * K5mX069IKG82CMqh3Mzptd7e7lyb9lsoGO0BAtjho3cWtha/UZ70vfaMzGuZ6JmQ + * ak6k+8+UFd93M4z0Qo74OhXB + * -----END PRIVATE KEY-----` + * const privateKey = await jose.importPKCS8(pkcs8, alg) + * + * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .sign(privateKey) + * + * console.log(jwt) + * ``` + * + * @example Usage with a private JWK encoded RSA key + * + * ```js + * const alg = 'RS256' + * const jwk = { + * kty: 'RSA', + * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', + * e: 'AQAB', + * d: 'VuVE_KEP6323WjpbBdAIv7HGahGrgGANvbxZsIhm34lsVOPK0XDegZkhAybMZHjRhp-gwVxX5ChC-J3cUpOBH5FNxElgW6HizD2Jcq6t6LoLYgPSrfEHm71iHg8JsgrqfUnGYFzMJmv88C6WdCtpgG_qJV1K00_Ly1G1QKoBffEs-v4fAMJrCbUdCz1qWto-PU-HLMEo-krfEpGgcmtZeRlDADh8cETMQlgQfQX2VWq_aAP4a1SXmo-j0cvRU4W5Fj0RVwNesIpetX2ZFz4p_JmB5sWFEj_fC7h5z2lq-6Bme2T3BHtXkIxoBW0_pYVnASC8P2puO5FnVxDmWuHDYQ', + * p: '07rgXd_tLUhVRF_g1OaqRZh5uZ8hiLWUSU0vu9coOaQcatSqjQlIwLW8UdKv_38GrmpIfgcEVQjzq6rFBowUm9zWBO9Eq6enpasYJBOeD8EMeDK-nsST57HjPVOCvoVC5ZX-cozPXna3iRNZ1TVYBY3smn0IaxysIK-zxESf4pM', + * q: '6qrE9TPhCS5iNR7QrKThunLu6t4H_8CkYRPLbvOIt2MgZyPLiZCsvdkTVSOX76QQEXt7Y0nTNua69q3K3Jhf-YOkPSJsWTxgrfOnjoDvRKzbW3OExIMm7D99fVBODuNWinjYgUwGSqGAsb_3TKhtI-Gr5ls3fn6B6oEjVL0dpmk', + * dp: 'mHqjrFdgelT2OyiFRS3dAAPf3cLxJoAGC4gP0UoQyPocEP-Y17sQ7t-ygIanguubBy65iDFLeGXa_g0cmSt2iAzRAHrDzI8P1-pQl2KdWSEg9ssspjBRh_F_AiJLLSPRWn_b3-jySkhawtfxwO8Kte1QsK1My765Y0zFvJnjPws', + * dq: 'KmjaV4YcsVAUp4z-IXVa5htHWmLuByaFjpXJOjABEUN0467wZdgjn9vPRp-8Ia8AyGgMkJES_uUL_PDDrMJM9gb4c6P4-NeUkVtreLGMjFjA-_IQmIMrUZ7XywHsWXx0c2oLlrJqoKo3W-hZhR0bPFTYgDUT_mRWjk7wV6wl46E', + * qi: 'iYltkV_4PmQDfZfGFpzn2UtYEKyhy-9t3Vy8Mw2VHLAADKGwJvVK5ficQAr2atIF1-agXY2bd6KV-w52zR8rmZfTr0gobzYIyqHczOm13t7uXJv2WygY7QEC2OGjdxa2Fr9RnvS99ozMa5nomZBqTqT7z5QV33czjPRCjvg6FcE', + * } + * const privateKey = await jose.importJWK(jwk, alg) + * + * const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) + * .setProtectedHeader({ alg }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .sign(privateKey) + * + * console.log(jwt) + * ``` + */ +export declare class SignJWT extends ProduceJWT { + private _protectedHeader; + /** + * Sets the JWS Protected Header on the SignJWT object. + * + * @param protectedHeader JWS Protected Header. Must contain an "alg" (JWS Algorithm) property. + */ + setProtectedHeader(protectedHeader: JWTHeaderParameters): this; + /** + * Signs and returns the JWT. + * + * @param key Private Key or Secret to sign the JWT with. + * @param options JWT Sign options. + */ + sign(key: KeyLike | Uint8Array, options?: SignOptions): Promise; +} diff --git a/dist/types/jwt/unsecured.d.ts b/dist/types/jwt/unsecured.d.ts new file mode 100644 index 0000000000..767ea18461 --- /dev/null +++ b/dist/types/jwt/unsecured.d.ts @@ -0,0 +1,44 @@ +import type { JWSHeaderParameters, JWTClaimVerificationOptions, JWTPayload } from '../types'; +import { ProduceJWT } from './produce'; +export interface UnsecuredResult { + payload: JWTPayload; + header: JWSHeaderParameters; +} +/** + * The UnsecuredJWT class is a utility for dealing with `{ "alg": "none" }` Unsecured JWTs. + * + * @example Encoding + * + * ```js + * const unsecuredJwt = new jose.UnsecuredJWT({ 'urn:example:claim': true }) + * .setIssuedAt() + * .setIssuer('urn:example:issuer') + * .setAudience('urn:example:audience') + * .setExpirationTime('2h') + * .encode() + * + * console.log(unsecuredJwt) + * ``` + * + * @example Decoding + * + * ```js + * const payload = jose.UnsecuredJWT.decode(jwt, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(payload) + * ``` + */ +export declare class UnsecuredJWT extends ProduceJWT { + /** Encodes the Unsecured JWT. */ + encode(): string; + /** + * Decodes an unsecured JWT. + * + * @param jwt Unsecured JWT to decode the payload of. + * @param options JWT Claims Set validation options. + */ + static decode(jwt: string, options?: JWTClaimVerificationOptions): UnsecuredResult; +} diff --git a/dist/types/jwt/verify.d.ts b/dist/types/jwt/verify.d.ts new file mode 100644 index 0000000000..50b0cbafd3 --- /dev/null +++ b/dist/types/jwt/verify.d.ts @@ -0,0 +1,108 @@ +import type { KeyLike, VerifyOptions, JWTClaimVerificationOptions, JWTHeaderParameters, GetKeyFunction, FlattenedJWSInput, JWTVerifyResult, ResolvedKey } from '../types'; +/** Combination of JWS Verification options and JWT Claims Set verification options. */ +export interface JWTVerifyOptions extends VerifyOptions, JWTClaimVerificationOptions { +} +/** + * Interface for JWT Verification dynamic key resolution. No token components have been verified at + * the time of this function call. + * + * See + * [createRemoteJWKSet](../functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwkset) + * to verify using a remote JSON Web Key Set. + */ +export interface JWTVerifyGetKey extends GetKeyFunction { +} +/** + * Verifies the JWT format (to be a JWS Compact format), verifies the JWS signature, validates the + * JWT Claims Set. + * + * @example Usage with a symmetric secret + * + * ```js + * const secret = new TextEncoder().encode( + * 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2', + * ) + * const jwt = + * 'eyJhbGciOiJIUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2MjMxLCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.C4iSlLfAUMBq--wnC6VqD9gEOhwpRZpoRarE0m7KEnI' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, secret, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Usage with a public SPKI encoded RSA key + * + * ```js + * const alg = 'RS256' + * const spki = `-----BEGIN PUBLIC KEY----- + * MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwhYOFK2Ocbbpb/zVypi9 + * SeKiNUqKQH0zTKN1+6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4H + * HHsrYCf2+FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS/Yv4hRvWfQPcc2Gc3+/fQ + * OOW57zVy+rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj + * +KgDPjymkMGoJlO3aKppsjfbt/AH6GGdRghYRLOUwQU+h+ofWHR3lbYiKtXPn5dN + * 24kiHy61e3VAQ9/YAZlwXC/99GGtw/NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZA + * SwIDAQAB + * -----END PUBLIC KEY-----` + * const publicKey = await jose.importSPKI(spki, alg) + * const jwt = + * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @example Usage with a public JWK encoded RSA key + * + * ```js + * const alg = 'RS256' + * const jwk = { + * kty: 'RSA', + * n: 'whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw', + * e: 'AQAB', + * } + * const publicKey = await jose.importJWK(jwk, alg) + * const jwt = + * 'eyJhbGciOiJSUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6dHJ1ZSwiaWF0IjoxNjY5MDU2NDg4LCJpc3MiOiJ1cm46ZXhhbXBsZTppc3N1ZXIiLCJhdWQiOiJ1cm46ZXhhbXBsZTphdWRpZW5jZSJ9.gXrPZ3yM_60dMXGE69dusbpzYASNA-XIOwsb5D5xYnSxyj6_D6OR_uR_1vqhUm4AxZxcrH1_-XJAve9HCw8az_QzHcN-nETt-v6stCsYrn6Bv1YOc-mSJRZ8ll57KVqLbCIbjKwerNX5r2_Qg2TwmJzQdRs-AQDhy-s_DlJd8ql6wR4n-kDZpar-pwIvz4fFIN0Fj57SXpAbLrV6Eo4Byzl0xFD8qEYEpBwjrMMfxCZXTlAVhAq6KCoGlDTwWuExps342-0UErEtyIqDnDGcrfNWiUsoo8j-29IpKd-w9-C388u-ChCxoHz--H8WmMSZzx3zTXsZ5lXLZ9IKfanDKg' + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, publicKey, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwt JSON Web Token value (encoded as JWS). + * @param key Key to verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export declare function jwtVerify(jwt: string | Uint8Array, key: KeyLike | Uint8Array, options?: JWTVerifyOptions): Promise; +/** + * @example Usage with a public JSON Web Key Set hosted on a remote URL + * + * ```js + * const JWKS = jose.createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')) + * + * const { payload, protectedHeader } = await jose.jwtVerify(jwt, JWKS, { + * issuer: 'urn:example:issuer', + * audience: 'urn:example:audience', + * }) + * console.log(protectedHeader) + * console.log(payload) + * ``` + * + * @param jwt JSON Web Token value (encoded as JWS). + * @param getKey Function resolving a key to verify the JWT with. + * @param options JWT Decryption and JWT Claims Set validation options. + */ +export declare function jwtVerify(jwt: string | Uint8Array, getKey: JWTVerifyGetKey, options?: JWTVerifyOptions): Promise; diff --git a/dist/types/key/export.d.ts b/dist/types/key/export.d.ts new file mode 100644 index 0000000000..5d745e446f --- /dev/null +++ b/dist/types/key/export.d.ts @@ -0,0 +1,47 @@ +import type { JWK, KeyLike } from '../types'; +/** + * Exports a runtime-specific public key representation (KeyObject or CryptoKey) to a PEM-encoded + * SPKI string format. + * + * @example Usage + * + * ```js + * const spkiPem = await jose.exportSPKI(publicKey) + * + * console.log(spkiPem) + * ``` + * + * @param key Key representation to transform to a PEM-encoded SPKI string format. + */ +export declare function exportSPKI(key: KeyLike): Promise; +/** + * Exports a runtime-specific private key representation (KeyObject or CryptoKey) to a PEM-encoded + * PKCS8 string format. + * + * @example Usage + * + * ```js + * const pkcs8Pem = await jose.exportPKCS8(privateKey) + * + * console.log(pkcs8Pem) + * ``` + * + * @param key Key representation to transform to a PEM-encoded PKCS8 string format. + */ +export declare function exportPKCS8(key: KeyLike): Promise; +/** + * Exports a runtime-specific key representation (KeyLike) to a JWK. + * + * @example Usage + * + * ```js + * const privateJwk = await jose.exportJWK(privateKey) + * const publicJwk = await jose.exportJWK(publicKey) + * + * console.log(privateJwk) + * console.log(publicJwk) + * ``` + * + * @param key Key representation to export as JWK. + */ +export declare function exportJWK(key: KeyLike | Uint8Array): Promise; diff --git a/dist/types/key/generate_key_pair.d.ts b/dist/types/key/generate_key_pair.d.ts new file mode 100644 index 0000000000..13b87f27a0 --- /dev/null +++ b/dist/types/key/generate_key_pair.d.ts @@ -0,0 +1,44 @@ +import type { KeyLike } from '../types'; +export interface GenerateKeyPairResult { + /** The generated Private Key. */ + privateKey: KeyLike; + /** Public Key corresponding to the generated Private Key. */ + publicKey: KeyLike; +} +export interface GenerateKeyPairOptions { + /** + * The EC "crv" (Curve) or OKP "crv" (Subtype of Key Pair) value to generate. The curve must be + * both supported on the runtime as well as applicable for the given JWA algorithm identifier. + */ + crv?: string; + /** + * A hint for RSA algorithms to generate an RSA key of a given `modulusLength` (Key size in bits). + * JOSE requires 2048 bits or larger. Default is 2048. + */ + modulusLength?: number; + /** + * (Only effective in Web Crypto API runtimes) The value to use as + * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) + * `extractable` argument. Default is false. + */ + extractable?: boolean; +} +/** + * Generates a private and a public key for a given JWA algorithm identifier. This can only generate + * asymmetric key pairs. For symmetric secrets use the `generateSecret` function. + * + * Note: Under Web Crypto API runtime the `privateKey` is generated with `extractable` set to + * `false` by default. + * + * @example Usage + * + * ```js + * const { publicKey, privateKey } = await jose.generateKeyPair('PS256') + * console.log(publicKey) + * console.log(privateKey) + * ``` + * + * @param alg JWA Algorithm Identifier to be used with the generated key pair. + * @param options Additional options passed down to the key pair generation. + */ +export declare function generateKeyPair(alg: string, options?: GenerateKeyPairOptions): Promise; diff --git a/dist/types/key/generate_secret.d.ts b/dist/types/key/generate_secret.d.ts new file mode 100644 index 0000000000..31898091c9 --- /dev/null +++ b/dist/types/key/generate_secret.d.ts @@ -0,0 +1,26 @@ +import type { KeyLike } from '../types'; +export interface GenerateSecretOptions { + /** + * (Only effective in Web Crypto API runtimes) The value to use as + * [SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) + * `extractable` argument. Default is false. + */ + extractable?: boolean; +} +/** + * Generates a symmetric secret key for a given JWA algorithm identifier. + * + * Note: Under Web Crypto API runtime the secret key is generated with `extractable` set to `false` + * by default. + * + * @example Usage + * + * ```js + * const secret = await jose.generateSecret('HS256') + * console.log(secret) + * ``` + * + * @param alg JWA Algorithm Identifier to be used with the generated secret. + * @param options Additional options passed down to the secret generation. + */ +export declare function generateSecret(alg: string, options?: GenerateSecretOptions): Promise; diff --git a/dist/types/key/import.d.ts b/dist/types/key/import.d.ts new file mode 100644 index 0000000000..8bb9c25197 --- /dev/null +++ b/dist/types/key/import.d.ts @@ -0,0 +1,119 @@ +import type { JWK, KeyLike } from '../types'; +export interface PEMImportOptions { + /** + * (Only effective in Web Crypto API runtimes) The value to use as + * [SubtleCrypto.importKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) + * `extractable` argument. Default is false. + */ + extractable?: boolean; +} +/** + * Imports a PEM-encoded SPKI string as a runtime-specific public key representation (KeyObject or + * CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to learn + * about key to algorithm requirements and mapping. + * + * @example Usage + * + * ```js + * const algorithm = 'ES256' + * const spki = `-----BEGIN PUBLIC KEY----- + * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM + * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== + * -----END PUBLIC KEY-----` + * const ecPublicKey = await jose.importSPKI(spki, algorithm) + * ``` + * + * @param pem PEM-encoded SPKI string + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key, its presence is only enforced in Web Crypto API runtimes. + */ +export declare function importSPKI(spki: string, alg: string, options?: PEMImportOptions): Promise; +/** + * Imports the SPKI from an X.509 string certificate as a runtime-specific public key representation + * (KeyObject or CryptoKey). See [Algorithm Key + * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm + * requirements and mapping. + * + * @example Usage + * + * ```js + * const algorithm = 'ES256' + * const x509 = `-----BEGIN CERTIFICATE----- + * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np + * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw + * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN + * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI + * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 + * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA + * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh + * v+A1QWZMuTWqYt+uh/YSRNDn + * -----END CERTIFICATE-----` + * const ecPublicKey = await jose.importX509(x509, algorithm) + * ``` + * + * @param pem X.509 certificate string + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key, its presence is only enforced in Web Crypto API runtimes. + */ +export declare function importX509(x509: string, alg: string, options?: PEMImportOptions): Promise; +/** + * Imports a PEM-encoded PKCS#8 string as a runtime-specific private key representation (KeyObject + * or CryptoKey). See [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) to + * learn about key to algorithm requirements and mapping. Encrypted keys are not supported. + * + * @example Usage + * + * ```js + * const algorithm = 'ES256' + * const pkcs8 = `-----BEGIN PRIVATE KEY----- + * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN + * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg + * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa + * -----END PRIVATE KEY-----` + * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) + * ``` + * + * @param pem PEM-encoded PKCS#8 string + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key, its presence is only enforced in Web Crypto API runtimes. + */ +export declare function importPKCS8(pkcs8: string, alg: string, options?: PEMImportOptions): Promise; +/** + * Imports a JWK to a runtime-specific key representation (KeyLike). Either JWK "alg" (Algorithm) + * Parameter must be present or the optional "alg" argument. When running on a runtime using [Web + * Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) the jwk parameters "use", "key_ops", and + * "ext" are also used in the resulting `CryptoKey`. See [Algorithm Key + * Requirements](https://github.com/panva/jose/issues/210) to learn about key to algorithm + * requirements and mapping. + * + * @example Usage + * + * ```js + * const ecPublicKey = await jose.importJWK( + * { + * crv: 'P-256', + * kty: 'EC', + * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', + * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', + * }, + * 'ES256', + * ) + * + * const rsaPublicKey = await jose.importJWK( + * { + * kty: 'RSA', + * e: 'AQAB', + * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', + * }, + * 'PS256', + * ) + * ``` + * + * @param jwk JSON Web Key. + * @param alg (Only effective in Web Crypto API runtimes) JSON Web Algorithm identifier to be used + * with the imported key. Default is the "alg" property on the JWK, its presence is only enforced + * in Web Crypto API runtimes. + * @param octAsKeyObject Forces a symmetric key to be imported to a KeyObject or CryptoKey. Default + * is true unless JWK "ext" (Extractable) is true. + */ +export declare function importJWK(jwk: JWK, alg?: string, octAsKeyObject?: boolean): Promise; diff --git a/dist/types/types.d.ts b/dist/types/types.d.ts new file mode 100644 index 0000000000..3310685b47 --- /dev/null +++ b/dist/types/types.d.ts @@ -0,0 +1,628 @@ +/** + * KeyLike are runtime-specific classes representing asymmetric keys or symmetric secrets. These are + * instances of [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) and + * additionally [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) in Node.js runtime. + * [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) + * instances are also accepted as symmetric secret representation only. + * + * [Key Import Functions](../modules/key_import.md#readme) can be used to import PEM, or JWK + * formatted asymmetric keys and certificates to these runtime-specific representations. + * + * In Node.js the [Buffer](https://nodejs.org/api/buffer.html#buffer) class is a subclass of + * Uint8Array and so Buffer can be provided for symmetric secrets as well. + * + * [KeyObject](https://nodejs.org/api/crypto.html#class-keyobject) is a representation of a + * key/secret available in the Node.js runtime. In addition to the import functions of this library + * you may use the runtime APIs + * [crypto.createPublicKey](https://nodejs.org/api/crypto.html#cryptocreatepublickeykey), + * [crypto.createPrivateKey](https://nodejs.org/api/crypto.html#cryptocreateprivatekeykey), and + * [crypto.createSecretKey](https://nodejs.org/api/crypto.html#cryptocreatesecretkeykey-encoding) to + * obtain a KeyObject from your existing key material. + * + * [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) is a representation of a + * key/secret available in the Browser and Web-interoperable runtimes. In addition to the import + * functions of this library you may use the + * [SubtleCrypto.importKey](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey) + * API to obtain a CryptoKey from your existing key material. + * + * @example Import a PEM-encoded SPKI Public Key + * + * ```js + * const algorithm = 'ES256' + * const spki = `-----BEGIN PUBLIC KEY----- + * MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlHHWfLk0gLBbsLTcuCrbCqoHqmM + * YJepMC+Q+Dd6RBmBiA41evUsNMwLeN+PNFqib+xwi9JkJ8qhZkq8Y/IzGg== + * -----END PUBLIC KEY-----` + * const ecPublicKey = await jose.importSPKI(spki, algorithm) + * ``` + * + * @example Import SPKI from an X.509 Certificate + * + * ```js + * const algorithm = 'ES256' + * const x509 = `-----BEGIN CERTIFICATE----- + * MIIBXjCCAQSgAwIBAgIGAXvykuMKMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK3Np + * QXBNOXpBdk1VaXhXVWVGaGtjZXg1NjJRRzFyQUhXaV96UlFQTVpQaG8wHhcNMjEw + * OTE3MDcwNTE3WhcNMjIwNzE0MDcwNTE3WjA2MTQwMgYDVQQDDCtzaUFwTTl6QXZN + * VWl4V1VlRmhrY2V4NTYyUUcxckFIV2lfelJRUE1aUGhvMFkwEwYHKoZIzj0CAQYI + * KoZIzj0DAQcDQgAE8PbPvCv5D5xBFHEZlBp/q5OEUymq7RIgWIi7tkl9aGSpYE35 + * UH+kBKDnphJO3odpPZ5gvgKs2nwRWcrDnUjYLDAKBggqhkjOPQQDAgNIADBFAiEA + * 1yyMTRe66MhEXID9+uVub7woMkNYd0LhSHwKSPMUUTkCIFQGsfm1ecXOpeGOufAh + * v+A1QWZMuTWqYt+uh/YSRNDn + * -----END CERTIFICATE-----` + * const ecPublicKey = await jose.importX509(x509, algorithm) + * ``` + * + * @example Import a PEM-encoded PKCS8 Private Key + * + * ```js + * const algorithm = 'ES256' + * const pkcs8 = `-----BEGIN PRIVATE KEY----- + * MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiyvo0X+VQ0yIrOaN + * nlrnUclopnvuuMfoc8HHly3505OhRANCAAQWUcdZ8uTSAsFuwtNy4KtsKqgeqYxg + * l6kwL5D4N3pEGYGIDjV69Sw0zAt43480WqJv7HCL0mQnyqFmSrxj8jMa + * -----END PRIVATE KEY-----` + * const ecPrivateKey = await jose.importPKCS8(pkcs8, algorithm) + * ``` + * + * @example Import a JSON Web Key (JWK) + * + * ```js + * const ecPublicKey = await jose.importJWK( + * { + * crv: 'P-256', + * kty: 'EC', + * x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw', + * y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo', + * }, + * 'ES256', + * ) + * + * const rsaPublicKey = await jose.importJWK( + * { + * kty: 'RSA', + * e: 'AQAB', + * n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ', + * }, + * 'PS256', + * ) + * ``` + */ +export type KeyLike = { type: string } + +/** + * JSON Web Key ([JWK](https://www.rfc-editor.org/rfc/rfc7517)). "RSA", "EC", "OKP", and "oct" key + * types are supported. + */ +export interface JWK { + /** JWK "alg" (Algorithm) Parameter. */ + alg?: string + crv?: string + d?: string + dp?: string + dq?: string + e?: string + /** JWK "ext" (Extractable) Parameter. */ + ext?: boolean + k?: string + /** JWK "key_ops" (Key Operations) Parameter. */ + key_ops?: string[] + /** JWK "kid" (Key ID) Parameter. */ + kid?: string + /** JWK "kty" (Key Type) Parameter. */ + kty?: string + n?: string + oth?: Array<{ + d?: string + r?: string + t?: string + }> + p?: string + q?: string + qi?: string + /** JWK "use" (Public Key Use) Parameter. */ + use?: string + x?: string + y?: string + /** JWK "x5c" (X.509 Certificate Chain) Parameter. */ + x5c?: string[] + /** JWK "x5t" (X.509 Certificate SHA-1 Thumbprint) Parameter. */ + x5t?: string + /** "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Parameter. */ + 'x5t#S256'?: string + /** JWK "x5u" (X.509 URL) Parameter. */ + x5u?: string + + [propName: string]: unknown +} + +/** + * Generic Interface for consuming operations dynamic key resolution. No token components have been + * verified at the time of this function call. + * + * If you cannot match a key suitable for the token, throw an error instead. + * + * @param protectedHeader JWE or JWS Protected Header. + * @param token The consumed JWE or JWS token. + */ +export interface GetKeyFunction { + (protectedHeader: T, token: T2): Promise | KeyLike | Uint8Array +} + +/** + * Flattened JWS definition for verify function inputs, allows payload as Uint8Array for detached + * signature validation. + */ +export interface FlattenedJWSInput { + /** + * The "header" member MUST be present and contain the value JWS Unprotected Header when the JWS + * Unprotected Header value is non- empty; otherwise, it MUST be absent. This value is represented + * as an unencoded JSON object, rather than as a string. These Header Parameter values are not + * integrity protected. + */ + header?: JWSHeaderParameters + + /** + * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 + * "b64": false is used the value passed may also be a Uint8Array. + */ + payload: string | Uint8Array + + /** + * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWS Protected + * Header)) when the JWS Protected Header value is non-empty; otherwise, it MUST be absent. These + * Header Parameter values are integrity protected. + */ + protected?: string + + /** The "signature" member MUST be present and contain the value BASE64URL(JWS Signature). */ + signature: string +} + +/** + * General JWS definition for verify function inputs, allows payload as Uint8Array for detached + * signature validation. + */ +export interface GeneralJWSInput { + /** + * The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When RFC7797 + * "b64": false is used the value passed may also be a Uint8Array. + */ + payload: string | Uint8Array + + /** + * The "signatures" member value MUST be an array of JSON objects. Each object represents a + * signature or MAC over the JWS Payload and the JWS Protected Header. + */ + signatures: Omit[] +} + +/** + * Flattened JWS definition. Payload is returned as an empty string when JWS Unencoded Payload + * Option [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. + */ +export interface FlattenedJWS extends Partial { + payload: string + signature: string +} + +/** + * General JWS definition. Payload is returned as an empty string when JWS Unencoded Payload Option + * [RFC7797](https://www.rfc-editor.org/rfc/rfc7797) is used. + */ +export interface GeneralJWS { + payload: string + signatures: Omit[] +} + +export interface JoseHeaderParameters { + /** "kid" (Key ID) Header Parameter. */ + kid?: string + + /** "x5t" (X.509 Certificate SHA-1 Thumbprint) Header Parameter. */ + x5t?: string + + /** "x5c" (X.509 Certificate Chain) Header Parameter. */ + x5c?: string[] + + /** "x5u" (X.509 URL) Header Parameter. */ + x5u?: string + + /** "jku" (JWK Set URL) Header Parameter. */ + jku?: string + + /** "jwk" (JSON Web Key) Header Parameter. */ + jwk?: Pick + + /** "typ" (Type) Header Parameter. */ + typ?: string + + /** "cty" (Content Type) Header Parameter. */ + cty?: string +} + +/** Recognized JWS Header Parameters, any other Header Members may also be present. */ +export interface JWSHeaderParameters extends JoseHeaderParameters { + /** JWS "alg" (Algorithm) Header Parameter. */ + alg?: string + + /** + * This JWS Extension Header Parameter modifies the JWS Payload representation and the JWS Signing + * Input computation as per [RFC7797](https://www.rfc-editor.org/rfc/rfc7797). + */ + b64?: boolean + + /** JWS "crit" (Critical) Header Parameter. */ + crit?: string[] + + /** Any other JWS Header member. */ + [propName: string]: unknown +} + +/** Recognized JWE Key Management-related Header Parameters. */ +export interface JWEKeyManagementHeaderParameters { + apu?: Uint8Array + apv?: Uint8Array + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + p2c?: number + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + p2s?: Uint8Array + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + iv?: Uint8Array + /** + * @deprecated You should not use this parameter. It is only really intended for test and vector + * validation purposes. + */ + epk?: KeyLike +} + +/** Flattened JWE definition. */ +export interface FlattenedJWE { + /** + * The "aad" member MUST be present and contain the value BASE64URL(JWE AAD)) when the JWE AAD + * value is non-empty; otherwise, it MUST be absent. A JWE AAD value can be included to supply a + * base64url-encoded value to be integrity protected but not encrypted. + */ + aad?: string + + /** The "ciphertext" member MUST be present and contain the value BASE64URL(JWE Ciphertext). */ + ciphertext: string + + /** + * The "encrypted_key" member MUST be present and contain the value BASE64URL(JWE Encrypted Key) + * when the JWE Encrypted Key value is non-empty; otherwise, it MUST be absent. + */ + encrypted_key?: string + + /** + * The "header" member MUST be present and contain the value JWE Per- Recipient Unprotected Header + * when the JWE Per-Recipient Unprotected Header value is non-empty; otherwise, it MUST be absent. + * This value is represented as an unencoded JSON object, rather than as a string. These Header + * Parameter values are not integrity protected. + */ + header?: JWEHeaderParameters + + /** + * The "iv" member MUST be present and contain the value BASE64URL(JWE Initialization Vector) when + * the JWE Initialization Vector value is non-empty; otherwise, it MUST be absent. + */ + iv: string + + /** + * The "protected" member MUST be present and contain the value BASE64URL(UTF8(JWE Protected + * Header)) when the JWE Protected Header value is non-empty; otherwise, it MUST be absent. These + * Header Parameter values are integrity protected. + */ + protected?: string + + /** + * The "tag" member MUST be present and contain the value BASE64URL(JWE Authentication Tag) when + * the JWE Authentication Tag value is non-empty; otherwise, it MUST be absent. + */ + tag: string + + /** + * The "unprotected" member MUST be present and contain the value JWE Shared Unprotected Header + * when the JWE Shared Unprotected Header value is non-empty; otherwise, it MUST be absent. This + * value is represented as an unencoded JSON object, rather than as a string. These Header + * Parameter values are not integrity protected. + */ + unprotected?: JWEHeaderParameters +} + +export interface GeneralJWE extends Omit { + recipients: Pick[] +} + +/** Recognized JWE Header Parameters, any other Header members may also be present. */ +export interface JWEHeaderParameters extends JoseHeaderParameters { + /** JWE "alg" (Algorithm) Header Parameter. */ + alg?: string + + /** JWE "enc" (Encryption Algorithm) Header Parameter. */ + enc?: string + + /** JWE "crit" (Critical) Header Parameter. */ + crit?: string[] + + /** JWE "zip" (Compression Algorithm) Header Parameter. */ + zip?: string + + /** Any other JWE Header member. */ + [propName: string]: unknown +} + +/** Shared Interface with a "crit" property for all sign, verify, encrypt and decrypt operations. */ +export interface CritOption { + /** + * An object with keys representing recognized "crit" (Critical) Header Parameter names. The value + * for those is either `true` or `false`. `true` when the Header Parameter MUST be integrity + * protected, `false` when it's irrelevant. + * + * This makes the "Extension Header Parameter "..." is not recognized" error go away. + * + * Use this when a given JWS/JWT/JWE profile requires the use of proprietary non-registered "crit" + * (Critical) Header Parameters. This will only make sure the Header Parameter is syntactically + * correct when provided and that it is optionally integrity protected. It will not process the + * Header Parameter in any way or reject the operation if it is missing. You MUST still verify the + * Header Parameter was present and process it according to the profile's validation steps after + * the operation succeeds. + * + * The JWS extension Header Parameter `b64` is always recognized and processed properly. No other + * registered Header Parameters that need this kind of default built-in treatment are currently + * available. + */ + crit?: { + [propName: string]: boolean + } +} + +/** JWE Decryption options. */ +export interface DecryptOptions extends CritOption { + /** A list of accepted JWE "alg" (Algorithm) Header Parameter values. */ + keyManagementAlgorithms?: string[] + + /** + * A list of accepted JWE "enc" (Encryption Algorithm) Header Parameter values. By default all + * "enc" (Encryption Algorithm) values applicable for the used key/secret are allowed. + */ + contentEncryptionAlgorithms?: string[] + + /** + * In a browser runtime you have to provide an implementation for Inflate Raw when you expect JWEs + * with compressed plaintext. + */ + inflateRaw?: InflateFunction + + /** + * (PBES2 Key Management Algorithms only) Maximum allowed "p2c" (PBES2 Count) Header Parameter + * value. The PBKDF2 iteration count defines the algorithm's computational expense. By default + * this value is set to 10000. + */ + maxPBES2Count?: number +} + +/** JWE Deflate option. */ +export interface DeflateOption { + /** + * In a browser runtime you have to provide an implementation for Deflate Raw when you will be + * producing JWEs with compressed plaintext. + */ + deflateRaw?: DeflateFunction +} + +/** JWE Encryption options. */ +export interface EncryptOptions extends CritOption, DeflateOption {} + +/** JWT Claims Set verification options. */ +export interface JWTClaimVerificationOptions { + /** Expected JWT "aud" (Audience) Claim value(s). */ + audience?: string | string[] + + /** + * Expected clock tolerance + * + * - In seconds when number (e.g. 5) + * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). + */ + clockTolerance?: string | number + + /** Expected JWT "iss" (Issuer) Claim value(s). */ + issuer?: string | string[] + + /** + * Maximum time elapsed (in seconds) from the JWT "iat" (Issued At) Claim value. + * + * - In seconds when number (e.g. 5) + * - Parsed as seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). + */ + maxTokenAge?: string | number + + /** Expected JWT "sub" (Subject) Claim value. */ + subject?: string + + /** Expected JWT "typ" (Type) Header Parameter value. */ + typ?: string + + /** Date to use when comparing NumericDate claims, defaults to `new Date()`. */ + currentDate?: Date +} + +/** JWS Verification options. */ +export interface VerifyOptions extends CritOption { + /** + * A list of accepted JWS "alg" (Algorithm) Header Parameter values. By default all "alg" + * (Algorithm) values applicable for the used key/secret are allowed. Note: "none" is never + * accepted. + */ + algorithms?: string[] +} + +/** JWS Signing options. */ +export interface SignOptions extends CritOption {} + +/** Recognized JWT Claims Set members, any other members may also be present. */ +export interface JWTPayload { + /** + * JWT Issuer + * + * @see [RFC7519#section-4.1.1](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1) + */ + iss?: string + + /** + * JWT Subject + * + * @see [RFC7519#section-4.1.2](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2) + */ + sub?: string + + /** JWT Audience [RFC7519#section-4.1.3](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3). */ + aud?: string | string[] + + /** + * JWT ID + * + * @see [RFC7519#section-4.1.7](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7) + */ + jti?: string + + /** + * JWT Not Before + * + * @see [RFC7519#section-4.1.5](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5) + */ + nbf?: number + + /** + * JWT Expiration Time + * + * @see [RFC7519#section-4.1.4](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4) + */ + exp?: number + + /** + * JWT Issued At + * + * @see [RFC7519#section-4.1.6](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6) + */ + iat?: number + + /** Any other JWT Claim Set member. */ + [propName: string]: unknown +} + +/** + * Deflate Raw implementation, e.g. promisified + * [zlib.deflateRaw](https://nodejs.org/api/zlib.html#zlibdeflaterawbuffer-options-callback). + */ +export interface DeflateFunction { + (input: Uint8Array): Promise +} + +/** + * Inflate Raw implementation, e.g. promisified + * [zlib.inflateRaw](https://nodejs.org/api/zlib.html#zlibinflaterawbuffer-options-callback). + */ +export interface InflateFunction { + (input: Uint8Array): Promise +} + +export interface FlattenedDecryptResult { + /** JWE AAD. */ + additionalAuthenticatedData?: Uint8Array + + /** Plaintext. */ + plaintext: Uint8Array + + /** JWE Protected Header. */ + protectedHeader?: JWEHeaderParameters + + /** JWE Shared Unprotected Header. */ + sharedUnprotectedHeader?: JWEHeaderParameters + + /** JWE Per-Recipient Unprotected Header. */ + unprotectedHeader?: JWEHeaderParameters +} + +export interface GeneralDecryptResult extends FlattenedDecryptResult {} + +export interface CompactDecryptResult { + /** Plaintext. */ + plaintext: Uint8Array + + /** JWE Protected Header. */ + protectedHeader: CompactJWEHeaderParameters +} + +export interface FlattenedVerifyResult { + /** JWS Payload. */ + payload: Uint8Array + + /** JWS Protected Header. */ + protectedHeader?: JWSHeaderParameters + + /** JWS Unprotected Header. */ + unprotectedHeader?: JWSHeaderParameters +} + +export interface GeneralVerifyResult extends FlattenedVerifyResult {} + +export interface CompactVerifyResult { + /** JWS Payload. */ + payload: Uint8Array + + /** JWS Protected Header. */ + protectedHeader: CompactJWSHeaderParameters +} + +export interface JWTVerifyResult { + /** JWT Claims Set. */ + payload: JWTPayload + + /** JWS Protected Header. */ + protectedHeader: JWTHeaderParameters +} + +export interface JWTDecryptResult { + /** JWT Claims Set. */ + payload: JWTPayload + + /** JWE Protected Header. */ + protectedHeader: CompactJWEHeaderParameters +} + +export interface ResolvedKey { + /** Key resolved from the key resolver function. */ + key: KeyLike | Uint8Array +} + +/** Recognized Compact JWS Header Parameters, any other Header Members may also be present. */ +export interface CompactJWSHeaderParameters extends JWSHeaderParameters { + alg: string +} + +/** Recognized Signed JWT Header Parameters, any other Header Members may also be present. */ +export interface JWTHeaderParameters extends CompactJWSHeaderParameters { + b64?: true +} + +/** Recognized Compact JWE Header Parameters, any other Header Members may also be present. */ +export interface CompactJWEHeaderParameters extends JWEHeaderParameters { + alg: string + enc: string +} + +/** JSON Web Key Set */ +export interface JSONWebKeySet { + keys: JWK[] +} diff --git a/dist/types/util/base64url.d.ts b/dist/types/util/base64url.d.ts new file mode 100644 index 0000000000..ec08361d2c --- /dev/null +++ b/dist/types/util/base64url.d.ts @@ -0,0 +1,19 @@ +/** + * Utility function to encode a string or Uint8Array as a base64url string. + * + * @param input Value that will be base64url-encoded. + */ +interface Base64UrlEncode { + (input: Uint8Array | string): string; +} +/** + * Utility function to decode a base64url encoded string. + * + * @param input Value that will be base64url-decoded. + */ +interface Base64UrlDecode { + (input: Uint8Array | string): Uint8Array; +} +export declare const encode: Base64UrlEncode; +export declare const decode: Base64UrlDecode; +export {}; diff --git a/dist/types/util/decode_jwt.d.ts b/dist/types/util/decode_jwt.d.ts new file mode 100644 index 0000000000..151cf733d1 --- /dev/null +++ b/dist/types/util/decode_jwt.d.ts @@ -0,0 +1,17 @@ +import type { JWTPayload } from '../types'; +/** + * Decodes a signed JSON Web Token payload. This does not validate the JWT Claims Set types or + * values. This does not validate the JWS Signature. For a proper Signed JWT Claims Set validation + * and JWS signature verification use `jose.jwtVerify()`. For an encrypted JWT Claims Set validation + * and JWE decryption use `jose.jwtDecrypt()`. + * + * @example Usage + * + * ```js + * const claims = jose.decodeJwt(token) + * console.log(claims) + * ``` + * + * @param jwt JWT token in compact JWS serialization. + */ +export declare function decodeJwt(jwt: string): JWTPayload; diff --git a/dist/types/util/decode_protected_header.d.ts b/dist/types/util/decode_protected_header.d.ts new file mode 100644 index 0000000000..b452f82bfc --- /dev/null +++ b/dist/types/util/decode_protected_header.d.ts @@ -0,0 +1,15 @@ +import type { JWSHeaderParameters, JWEHeaderParameters } from '../types'; +export type ProtectedHeaderParameters = JWSHeaderParameters & JWEHeaderParameters; +/** + * Decodes the Protected Header of a JWE/JWS/JWT token utilizing any JOSE serialization. + * + * @example Usage + * + * ```js + * const protectedHeader = jose.decodeProtectedHeader(token) + * console.log(protectedHeader) + * ``` + * + * @param token JWE/JWS/JWT token in any JOSE serialization. + */ +export declare function decodeProtectedHeader(token: string | object): ProtectedHeaderParameters; diff --git a/dist/types/util/errors.d.ts b/dist/types/util/errors.d.ts new file mode 100644 index 0000000000..3c5ac69778 --- /dev/null +++ b/dist/types/util/errors.d.ts @@ -0,0 +1,99 @@ +import type { KeyLike } from '../types'; +/** A generic Error subclass that all other specific JOSE Error subclasses inherit from. */ +export declare class JOSEError extends Error { + /** A unique error code for the particular error subclass. */ + static get code(): string; + /** A unique error code for the particular error subclass. */ + code: string; + constructor(message?: string); +} +/** An error subclass thrown when a JWT Claim Set member validation fails. */ +export declare class JWTClaimValidationFailed extends JOSEError { + static get code(): 'ERR_JWT_CLAIM_VALIDATION_FAILED'; + code: string; + /** The Claim for which the validation failed. */ + claim: string; + /** Reason code for the validation failure. */ + reason: string; + constructor(message: string, claim?: string, reason?: string); +} +/** An error subclass thrown when a JWT is expired. */ +export declare class JWTExpired extends JOSEError implements JWTClaimValidationFailed { + static get code(): 'ERR_JWT_EXPIRED'; + code: string; + /** The Claim for which the validation failed. */ + claim: string; + /** Reason code for the validation failure. */ + reason: string; + constructor(message: string, claim?: string, reason?: string); +} +/** An error subclass thrown when a JOSE Algorithm is not allowed per developer preference. */ +export declare class JOSEAlgNotAllowed extends JOSEError { + static get code(): 'ERR_JOSE_ALG_NOT_ALLOWED'; + code: string; +} +/** + * An error subclass thrown when a particular feature or algorithm is not supported by this + * implementation or JOSE in general. + */ +export declare class JOSENotSupported extends JOSEError { + static get code(): 'ERR_JOSE_NOT_SUPPORTED'; + code: string; +} +/** An error subclass thrown when a JWE ciphertext decryption fails. */ +export declare class JWEDecryptionFailed extends JOSEError { + static get code(): 'ERR_JWE_DECRYPTION_FAILED'; + code: string; + message: string; +} +/** An error subclass thrown when a JWE is invalid. */ +export declare class JWEInvalid extends JOSEError { + static get code(): 'ERR_JWE_INVALID'; + code: string; +} +/** An error subclass thrown when a JWS is invalid. */ +export declare class JWSInvalid extends JOSEError { + static get code(): 'ERR_JWS_INVALID'; + code: string; +} +/** An error subclass thrown when a JWT is invalid. */ +export declare class JWTInvalid extends JOSEError { + static get code(): 'ERR_JWT_INVALID'; + code: string; +} +/** An error subclass thrown when a JWK is invalid. */ +export declare class JWKInvalid extends JOSEError { + static get code(): 'ERR_JWK_INVALID'; + code: string; +} +/** An error subclass thrown when a JWKS is invalid. */ +export declare class JWKSInvalid extends JOSEError { + static get code(): 'ERR_JWKS_INVALID'; + code: string; +} +/** An error subclass thrown when no keys match from a JWKS. */ +export declare class JWKSNoMatchingKey extends JOSEError { + static get code(): 'ERR_JWKS_NO_MATCHING_KEY'; + code: string; + message: string; +} +/** An error subclass thrown when multiple keys match from a JWKS. */ +export declare class JWKSMultipleMatchingKeys extends JOSEError { + /** @ignore */ + [Symbol.asyncIterator]: () => AsyncIterableIterator; + static get code(): 'ERR_JWKS_MULTIPLE_MATCHING_KEYS'; + code: string; + message: string; +} +/** Timeout was reached when retrieving the JWKS response. */ +export declare class JWKSTimeout extends JOSEError { + static get code(): 'ERR_JWKS_TIMEOUT'; + code: string; + message: string; +} +/** An error subclass thrown when JWS signature verification fails. */ +export declare class JWSSignatureVerificationFailed extends JOSEError { + static get code(): 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'; + code: string; + message: string; +} diff --git a/docs/README.md b/docs/README.md index c015043285..37f907f867 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,7 +18,7 @@ const jose = require('jose') **`example`** Deno import ```js -import * as jose from 'https://deno.land/x/jose@v4.12.1/index.ts' +import * as jose from 'https://deno.land/x/jose@v4.12.2/index.ts' ``` - JSON Web Tokens (JWT) diff --git a/package-lock.json b/package-lock.json index 93f779f682..8f1a533176 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jose", - "version": "4.12.1", + "version": "4.12.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jose", - "version": "4.12.1", + "version": "4.12.2", "license": "MIT", "devDependencies": { "@types/node": "^18.11.9", diff --git a/package.json b/package.json index 36b2369406..7601b5e2ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jose", - "version": "4.12.1", + "version": "4.12.2", "description": "'JSON Web Almost Everything' - JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes", "keywords": [ "browser",