From 585cc31398845b2becb8bc00453b1ae6f32c2629 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Tue, 19 Oct 2021 11:07:53 +0200 Subject: [PATCH 1/4] To be able to verify that keys are of a certain length/size. --- src/cryptojwt/jwk/__init__.py | 5 ++++- src/cryptojwt/jwk/ec.py | 9 +++++++++ src/cryptojwt/jwk/hmac.py | 8 ++++++++ src/cryptojwt/jwk/rsa.py | 9 +++++++++ tests/test_02_jwk.py | 13 ++++++++++--- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/cryptojwt/jwk/__init__.py b/src/cryptojwt/jwk/__init__.py index cfde0316..e22ec836 100644 --- a/src/cryptojwt/jwk/__init__.py +++ b/src/cryptojwt/jwk/__init__.py @@ -178,7 +178,7 @@ def serialize(self, private=False): def get_key(self, private=False, **kwargs): """ - Get a keys useful for signing and/or encrypting information. + Get a key useful for signing and/or encrypting information. :param private: Private key requested. If false return a public key. :return: A key instance. This can be an RSA, EC or other @@ -290,6 +290,9 @@ def appropriate_for(self, usage, **kwargs): def update(self): pass + def key_len(self): + raise NotImplemented() + def pems_to_x5c(cert_chain): """ diff --git a/src/cryptojwt/jwk/ec.py b/src/cryptojwt/jwk/ec.py index d27f5c8e..397c0006 100644 --- a/src/cryptojwt/jwk/ec.py +++ b/src/cryptojwt/jwk/ec.py @@ -1,5 +1,6 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec +from cryptojwt.exception import KeyNotFound from ..exception import DeSerializationNotPossible from ..exception import JWKESTException @@ -254,6 +255,14 @@ def __eq__(self, other): return False + def key_len(self): + if self.priv_key: + return self.priv_key.key_size + elif self.pub_key: + return self.pub_key.key_size + else: + raise KeyNotFound() + def cmp_keys(a, b, key_type): if isinstance(a, key_type): diff --git a/src/cryptojwt/jwk/hmac.py b/src/cryptojwt/jwk/hmac.py index 70da83f2..31448c4d 100644 --- a/src/cryptojwt/jwk/hmac.py +++ b/src/cryptojwt/jwk/hmac.py @@ -1,6 +1,8 @@ import logging import os +from cryptojwt.exception import KeyNotFound + from ..exception import JWKException from ..exception import UnsupportedAlgorithm from ..exception import WrongUsage @@ -149,6 +151,12 @@ def __eq__(self, other): return True + def key_len(self): + if self.key: + return len(self.key) + else: + raise KeyNotFound() + def new_sym_key(use="", bytes=24, kid=""): _key = SYMKey(use=use, kid=kid, key=as_unicode(os.urandom(bytes))) diff --git a/src/cryptojwt/jwk/rsa.py b/src/cryptojwt/jwk/rsa.py index e98cb236..dc9cb43b 100644 --- a/src/cryptojwt/jwk/rsa.py +++ b/src/cryptojwt/jwk/rsa.py @@ -4,6 +4,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa +from cryptojwt.exception import KeyNotFound from ..exception import DeSerializationNotPossible from ..exception import JWKESTException @@ -470,6 +471,14 @@ def __eq__(self, other): else: return cmp_private_numbers(pn1, pn2) + def key_len(self): + if self.priv_key: + return self.priv_key.key_size + elif self.pub_key: + return self.pub_key.key_size + else: + raise KeyNotFound() + def new_rsa_key(key_size=2048, kid="", public_exponent=65537, **kwargs): """ diff --git a/tests/test_02_jwk.py b/tests/test_02_jwk.py index a9307b8b..a3c1397e 100644 --- a/tests/test_02_jwk.py +++ b/tests/test_02_jwk.py @@ -115,6 +115,12 @@ def test_dumps(): assert _eq(list(jwk.keys()), ["kty", "e", "n", "kid"]) +def test_key_size(): + _ckey = import_rsa_key_from_cert_file(CERT) + jwk = jwk_wrap(_ckey) + assert jwk.key_len() == 1024 + + def test_import_rsa_key(): _ckey = import_private_rsa_key_from_file(full_path(KEY)) assert isinstance(_ckey, rsa.RSAPrivateKey) @@ -163,7 +169,7 @@ def test_verify_2(): _key = RSAKey() _key.load_key(import_rsa_key_from_cert_file(CERT)) assert _key.verify() - + assert _key.key_len() == 1024 # default def test_cmp_rsa(): _key1 = RSAKey() @@ -188,12 +194,13 @@ def test_import_export_eckey(): _key = ECKey(**ECKEY) _key.deserialize() assert _eq(list(_key.keys()), ["y", "x", "d", "crv", "kty"]) + assert _key.key_len() == 521 def test_new_ec_key(): ec_key = new_ec_key("P-256") assert isinstance(ec_key, ECKey) - + assert ec_key.key_len() == 256 def test_create_eckey(): ec = new_ec_key("P-256") @@ -622,7 +629,7 @@ def test_mint_new_sym_key(): assert key.use == "sig" assert key.kid == "one" assert len(key.key) == 24 - + assert key.key_len() == 24 def test_dump_load(): _ckey = import_rsa_key_from_cert_file(CERT) From 94ea39a08d0a45afc0eb33036ad7908e082153ff Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Tue, 19 Oct 2021 11:20:16 +0200 Subject: [PATCH 2/4] isort & black --- src/cryptojwt/jwe/__init__.py | 9 +-------- src/cryptojwt/jwe/jwe_ec.py | 7 +------ src/cryptojwt/jwe/rsa.py | 4 +--- src/cryptojwt/jwk/ec.py | 1 + src/cryptojwt/jwk/jwk.py | 4 +--- src/cryptojwt/jwk/rsa.py | 1 + src/cryptojwt/jws/jws.py | 6 +----- src/cryptojwt/jws/pss.py | 6 ++---- src/cryptojwt/key_bundle.py | 4 +--- src/cryptojwt/key_jar.py | 16 +++------------ src/cryptojwt/tools/keyconv.py | 5 +---- tests/test_01_simplejwt.py | 5 +---- tests/test_02_jwk.py | 8 ++++---- tests/test_04_key_issuer.py | 22 ++++----------------- tests/test_04_key_jar.py | 35 +++++++++------------------------ tests/test_06_jws.py | 7 ++----- tests/test_09_jwt.py | 15 +++----------- tests/test_50_argument_alias.py | 5 +---- 18 files changed, 38 insertions(+), 122 deletions(-) diff --git a/src/cryptojwt/jwe/__init__.py b/src/cryptojwt/jwe/__init__.py index ffddcf13..488a5c60 100644 --- a/src/cryptojwt/jwe/__init__.py +++ b/src/cryptojwt/jwe/__init__.py @@ -22,14 +22,7 @@ "ECDH-ES+A192KW", "ECDH-ES+A256KW", ], - "enc": [ - "A128CBC-HS256", - "A192CBC-HS384", - "A256CBC-HS512", - "A128GCM", - "A192GCM", - "A256GCM", - ], + "enc": ["A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512", "A128GCM", "A192GCM", "A256GCM",], } DEPRECATED = { diff --git a/src/cryptojwt/jwe/jwe_ec.py b/src/cryptojwt/jwe/jwe_ec.py index 3321a8e1..911a6ea3 100644 --- a/src/cryptojwt/jwe/jwe_ec.py +++ b/src/cryptojwt/jwe/jwe_ec.py @@ -157,12 +157,7 @@ def dec_setup(self, token, key=None, **kwargs): raise Exception("Unknown key length for algorithm") self.cek = ecdh_derive_key( - key, - epubkey.pub_key, - apu, - apv, - str(self.headers["enc"]).encode(), - dk_len, + key, epubkey.pub_key, apu, apv, str(self.headers["enc"]).encode(), dk_len, ) elif self.headers["alg"] in [ "ECDH-ES+A128KW", diff --git a/src/cryptojwt/jwe/rsa.py b/src/cryptojwt/jwe/rsa.py index 8e7cc4fe..691c3e59 100644 --- a/src/cryptojwt/jwe/rsa.py +++ b/src/cryptojwt/jwe/rsa.py @@ -20,9 +20,7 @@ def encrypt(self, msg, key, sign_padding="pkcs1_padding"): return key.encrypt( msg, _padding( - mgf=padding.MGF1(algorithm=_chosen_hash()), - algorithm=_chosen_hash(), - label=None, + mgf=padding.MGF1(algorithm=_chosen_hash()), algorithm=_chosen_hash(), label=None, ), ) diff --git a/src/cryptojwt/jwk/ec.py b/src/cryptojwt/jwk/ec.py index 397c0006..1884dd71 100644 --- a/src/cryptojwt/jwk/ec.py +++ b/src/cryptojwt/jwk/ec.py @@ -1,5 +1,6 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec + from cryptojwt.exception import KeyNotFound from ..exception import DeSerializationNotPossible diff --git a/src/cryptojwt/jwk/jwk.py b/src/cryptojwt/jwk/jwk.py index c9e32904..86f41c47 100644 --- a/src/cryptojwt/jwk/jwk.py +++ b/src/cryptojwt/jwk/jwk.py @@ -93,9 +93,7 @@ def key_from_jwk_dict(jwk_dict, private=None): else: # Ecdsa public key. ec_pub_numbers = ec.EllipticCurvePublicNumbers( - base64url_to_long(_jwk_dict["x"]), - base64url_to_long(_jwk_dict["y"]), - curve, + base64url_to_long(_jwk_dict["x"]), base64url_to_long(_jwk_dict["y"]), curve, ) _jwk_dict["pub_key"] = ec_pub_numbers.public_key(backends.default_backend()) return ECKey(**_jwk_dict) diff --git a/src/cryptojwt/jwk/rsa.py b/src/cryptojwt/jwk/rsa.py index dc9cb43b..54432431 100644 --- a/src/cryptojwt/jwk/rsa.py +++ b/src/cryptojwt/jwk/rsa.py @@ -4,6 +4,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa + from cryptojwt.exception import KeyNotFound from ..exception import DeSerializationNotPossible diff --git a/src/cryptojwt/jws/jws.py b/src/cryptojwt/jws/jws.py index c9b334ee..b24b0919 100644 --- a/src/cryptojwt/jws/jws.py +++ b/src/cryptojwt/jws/jws.py @@ -321,11 +321,7 @@ def verify_json(self, jws, keys=None, allow_none=False, at_least_one=False): for _sign in _signs: protected_headers = _sign.get("protected", "") token = b".".join( - [ - protected_headers.encode(), - _payload.encode(), - _sign["signature"].encode(), - ] + [protected_headers.encode(), _payload.encode(), _sign["signature"].encode(),] ) unprotected_headers = _sign.get("header", {}) diff --git a/src/cryptojwt/jws/pss.py b/src/cryptojwt/jws/pss.py index a7443ddb..71cbb3d6 100644 --- a/src/cryptojwt/jws/pss.py +++ b/src/cryptojwt/jws/pss.py @@ -38,8 +38,7 @@ def sign(self, msg, key): sig = key.sign( digest, padding.PSS( - mgf=padding.MGF1(self.hash_algorithm()), - salt_length=padding.PSS.MAX_LENGTH, + mgf=padding.MGF1(self.hash_algorithm()), salt_length=padding.PSS.MAX_LENGTH, ), utils.Prehashed(self.hash_algorithm()), ) @@ -60,8 +59,7 @@ def verify(self, msg, signature, key): signature, msg, padding.PSS( - mgf=padding.MGF1(self.hash_algorithm()), - salt_length=padding.PSS.MAX_LENGTH, + mgf=padding.MGF1(self.hash_algorithm()), salt_length=padding.PSS.MAX_LENGTH, ), self.hash_algorithm(), ) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index bfd8150c..e3356d51 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -484,9 +484,7 @@ def do_remote(self): self.time_out = time.time() + self.cache_time else: LOGGER.warning( - "HTTP status %d reading remote JWKS from %s", - _http_resp.status_code, - self.source, + "HTTP status %d reading remote JWKS from %s", _http_resp.status_code, self.source, ) self.ignore_errors_until = time.time() + self.ignore_errors_period raise UpdateFailed(REMOTE_FAILED.format(self.source, _http_resp.status_code)) diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index c9ab1bb9..90b08699 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -690,10 +690,7 @@ def dumps(self, exclude_issuers: Optional[List[str]] = None): return json.dumps(_dict) def load( - self, - info: dict, - init_args: Optional[dict] = None, - load_args: Optional[dict] = None, + self, info: dict, init_args: Optional[dict] = None, load_args: Optional[dict] = None, ): """ @@ -814,11 +811,7 @@ def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id=""): @deprecated_alias(issuer="issuer_id", owner="issuer_id") def init_key_jar( - public_path="", - private_path="", - key_defs="", - issuer_id="", - read_only=True, + public_path="", private_path="", key_defs="", issuer_id="", read_only=True, ): """ A number of cases here: @@ -860,10 +853,7 @@ def init_key_jar( """ _issuer = init_key_issuer( - public_path=public_path, - private_path=private_path, - key_defs=key_defs, - read_only=read_only, + public_path=public_path, private_path=private_path, key_defs=key_defs, read_only=read_only, ) if _issuer is None: diff --git a/src/cryptojwt/tools/keyconv.py b/src/cryptojwt/tools/keyconv.py index a5b27112..5df6b598 100644 --- a/src/cryptojwt/tools/keyconv.py +++ b/src/cryptojwt/tools/keyconv.py @@ -115,10 +115,7 @@ def pem2jwk( def export_jwk( - jwk: JWK, - private: bool = False, - encrypt: bool = False, - passphrase: Optional[str] = None, + jwk: JWK, private: bool = False, encrypt: bool = False, passphrase: Optional[str] = None, ) -> bytes: """Export JWK as PEM/bin""" diff --git a/tests/test_01_simplejwt.py b/tests/test_01_simplejwt.py index 9d94a172..02a944be 100644 --- a/tests/test_01_simplejwt.py +++ b/tests/test_01_simplejwt.py @@ -10,10 +10,7 @@ def _eq(l1, l2): def test_pack_jwt(): _jwt = SimpleJWT(**{"alg": "none", "cty": "jwt"}) jwt = _jwt.pack( - parts=[ - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True}, - "", - ] + parts=[{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True}, "",] ) p = jwt.split(".") diff --git a/tests/test_02_jwk.py b/tests/test_02_jwk.py index a3c1397e..56209de7 100644 --- a/tests/test_02_jwk.py +++ b/tests/test_02_jwk.py @@ -171,6 +171,7 @@ def test_verify_2(): assert _key.verify() assert _key.key_len() == 1024 # default + def test_cmp_rsa(): _key1 = RSAKey() _key1.load_key(import_rsa_key_from_cert_file(CERT)) @@ -202,6 +203,7 @@ def test_new_ec_key(): assert isinstance(ec_key, ECKey) assert ec_key.key_len() == 256 + def test_create_eckey(): ec = new_ec_key("P-256") exp_key = ec.serialize() @@ -631,6 +633,7 @@ def test_mint_new_sym_key(): assert len(key.key) == 24 assert key.key_len() == 24 + def test_dump_load(): _ckey = import_rsa_key_from_cert_file(CERT) _key = jwk_wrap(_ckey, "sig", "kid1") @@ -717,10 +720,7 @@ def test_x5t_calculation(): @pytest.mark.parametrize( "filename,key_type", - [ - ("ec-public.pem", ec.EllipticCurvePublicKey), - ("rsa-public.pem", rsa.RSAPublicKey), - ], + [("ec-public.pem", ec.EllipticCurvePublicKey), ("rsa-public.pem", rsa.RSAPublicKey),], ) def test_import_public_key_from_pem_file(filename, key_type): _file = full_path(filename) diff --git a/tests/test_04_key_issuer.py b/tests/test_04_key_issuer.py index 54d7b0dd..864d026e 100755 --- a/tests/test_04_key_issuer.py +++ b/tests/test_04_key_issuer.py @@ -222,11 +222,7 @@ def test_build_keyissuer_usage(): def test_build_keyissuer_missing(tmpdir): keys = [ - { - "type": "RSA", - "key": os.path.join(tmpdir.dirname, "missing_file"), - "use": ["enc", "sig"], - } + {"type": "RSA", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} ] key_issuer = build_keyissuer(keys) @@ -244,11 +240,7 @@ def test_build_RSA_keyissuer_from_file(tmpdir): def test_build_EC_keyissuer_missing(tmpdir): keys = [ - { - "type": "EC", - "key": os.path.join(tmpdir.dirname, "missing_file"), - "use": ["enc", "sig"], - } + {"type": "EC", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} ] key_issuer = build_keyissuer(keys) @@ -625,10 +617,7 @@ def test_init_key_issuer_update(): # New set of keys, JWKSs with keys and public written to file _keyissuer_1 = init_key_issuer( - private_path=PRIVATE_FILE, - key_defs=KEYSPEC, - public_path=PUBLIC_FILE, - read_only=False, + private_path=PRIVATE_FILE, key_defs=KEYSPEC, public_path=PUBLIC_FILE, read_only=False, ) assert len(_keyissuer_1) == 2 @@ -658,10 +647,7 @@ def test_init_key_issuer_update(): assert len(_keyissuer_3.get("sig", "EC")) == 1 _keyissuer_4 = init_key_issuer( - private_path=PRIVATE_FILE, - key_defs=KEYSPEC_2, - public_path=PUBLIC_FILE, - read_only=False, + private_path=PRIVATE_FILE, key_defs=KEYSPEC_2, public_path=PUBLIC_FILE, read_only=False, ) # Now it should diff --git a/tests/test_04_key_jar.py b/tests/test_04_key_jar.py index f3f79d49..c8ee2ec5 100755 --- a/tests/test_04_key_jar.py +++ b/tests/test_04_key_jar.py @@ -229,11 +229,7 @@ def test_build_keyjar_usage(): def test_build_keyjar_missing(tmpdir): keys = [ - { - "type": "RSA", - "key": os.path.join(tmpdir.dirname, "missing_file"), - "use": ["enc", "sig"], - } + {"type": "RSA", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} ] key_jar = build_keyjar(keys) @@ -251,11 +247,7 @@ def test_build_RSA_keyjar_from_file(tmpdir): def test_build_EC_keyjar_missing(tmpdir): keys = [ - { - "type": "EC", - "key": os.path.join(tmpdir.dirname, "missing_file"), - "use": ["enc", "sig"], - } + {"type": "EC", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} ] key_jar = build_keyjar(keys) @@ -311,8 +303,7 @@ def test_items(self): ), ) ks.add_kb( - "http://www.example.org", - keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert len(ks.items()) == 2 @@ -338,8 +329,7 @@ def test_issuer_extra_slash(self): ), ) ks.add_kb( - "http://www.example.org", - keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("sig", "RSA", "http://www.example.org/") @@ -365,8 +355,7 @@ def test_issuer_missing_slash(self): ), ) ks.add_kb( - "http://www.example.org/", - keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org/", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("sig", "RSA", "http://www.example.org") @@ -392,8 +381,7 @@ def test_get_enc(self): ), ) ks.add_kb( - "http://www.example.org/", - keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org/", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("enc", "oct") @@ -419,8 +407,7 @@ def test_get_enc_not_mine(self): ), ) ks.add_kb( - "http://www.example.org/", - keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org/", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("enc", "oct", "http://www.example.org/") @@ -462,8 +449,7 @@ def test_provider(self): kj = KeyJar() _url = "https://connect-op.herokuapp.com/jwks.json" kj.load_keys( - "https://connect-op.heroku.com", - jwks_uri=_url, + "https://connect-op.heroku.com", jwks_uri=_url, ) iss_keys = kj.get_issuer_keys("https://connect-op.heroku.com") if not iss_keys: @@ -988,10 +974,7 @@ def test_init_key_jar_update(): assert len(_keyjar_3.get_signing_key("EC")) == 1 _keyjar_4 = init_key_jar( - private_path=PRIVATE_FILE, - key_defs=KEYSPEC_2, - public_path=PUBLIC_FILE, - read_only=False, + private_path=PRIVATE_FILE, key_defs=KEYSPEC_2, public_path=PUBLIC_FILE, read_only=False, ) # Now it should diff --git a/tests/test_06_jws.py b/tests/test_06_jws.py index c452e0b5..96b15ac2 100644 --- a/tests/test_06_jws.py +++ b/tests/test_06_jws.py @@ -431,8 +431,7 @@ def test_jws_mm(): @pytest.mark.parametrize( - "ec_func,alg", - [(ec.SECP256R1, "ES256"), (ec.SECP384R1, "ES384"), (ec.SECP521R1, "ES512")], + "ec_func,alg", [(ec.SECP256R1, "ES256"), (ec.SECP384R1, "ES384"), (ec.SECP521R1, "ES512")], ) def test_signer_es(ec_func, alg): payload = "Please take a moment to register today" @@ -707,9 +706,7 @@ def test_sign_json_dont_flatten_if_multiple_signatures(): key = ECKey().load_key(P256()) unprotected_headers = {"foo": "bar"} _jwt = JWS(msg="hello world", alg="ES256").sign_json( - headers=[(None, unprotected_headers), (None, {"abc": "xyz"})], - keys=[key], - flatten=True, + headers=[(None, unprotected_headers), (None, {"abc": "xyz"})], keys=[key], flatten=True, ) assert "signatures" in json.loads(_jwt) diff --git a/tests/test_09_jwt.py b/tests/test_09_jwt.py index d016b211..84a859f5 100755 --- a/tests/test_09_jwt.py +++ b/tests/test_09_jwt.py @@ -25,16 +25,10 @@ def full_path(local_file): # k2 = import_private_rsa_key_from_file(full_path('size2048.key')) kb1 = KeyBundle( - source="file://{}".format(full_path("rsa.key")), - fileformat="der", - keyusage="sig", - kid="1", + source="file://{}".format(full_path("rsa.key")), fileformat="der", keyusage="sig", kid="1", ) kb2 = KeyBundle( - source="file://{}".format(full_path("size2048.key")), - fileformat="der", - keyusage="enc", - kid="2", + source="file://{}".format(full_path("size2048.key")), fileformat="der", keyusage="enc", kid="2", ) ALICE_KEY_JAR = KeyJar() @@ -42,10 +36,7 @@ def full_path(local_file): ALICE_KEY_JAR.add_kb(ALICE, kb2) kb3 = KeyBundle( - source="file://{}".format(full_path("server.key")), - fileformat="der", - keyusage="enc", - kid="3", + source="file://{}".format(full_path("server.key")), fileformat="der", keyusage="enc", kid="3", ) BOB_KEY_JAR = KeyJar() diff --git a/tests/test_50_argument_alias.py b/tests/test_50_argument_alias.py index 8831fb14..799ce52f 100644 --- a/tests/test_50_argument_alias.py +++ b/tests/test_50_argument_alias.py @@ -172,10 +172,7 @@ def test_init_key_jar_update(): assert len(_keyjar_3.get_signing_key("EC")) == 1 _keyjar_4 = init_key_jar( - private_path=PRIVATE_FILE, - key_defs=KEYSPEC_2, - public_path=PUBLIC_FILE, - read_only=False, + private_path=PRIVATE_FILE, key_defs=KEYSPEC_2, public_path=PUBLIC_FILE, read_only=False, ) # Now it should From d7cd0bfc106e7712829449d0a57107d5044560b4 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Tue, 19 Oct 2021 11:22:20 +0200 Subject: [PATCH 3/4] isort & black --- src/cryptojwt/jwe/__init__.py | 9 ++++++++- src/cryptojwt/jwe/jwe_ec.py | 7 ++++++- src/cryptojwt/jwe/rsa.py | 4 +++- src/cryptojwt/jwk/jwk.py | 4 +++- src/cryptojwt/jws/jws.py | 6 +++++- src/cryptojwt/jws/pss.py | 6 ++++-- src/cryptojwt/key_bundle.py | 4 +++- src/cryptojwt/key_jar.py | 16 ++++++++++++--- src/cryptojwt/tools/keyconv.py | 5 ++++- tests/test_01_simplejwt.py | 5 ++++- tests/test_02_jwk.py | 5 ++++- tests/test_04_key_issuer.py | 22 +++++++++++++++++---- tests/test_04_key_jar.py | 35 ++++++++++++++++++++++++--------- tests/test_06_jws.py | 7 +++++-- tests/test_09_jwt.py | 15 +++++++++++--- tests/test_50_argument_alias.py | 5 ++++- 16 files changed, 122 insertions(+), 33 deletions(-) diff --git a/src/cryptojwt/jwe/__init__.py b/src/cryptojwt/jwe/__init__.py index 488a5c60..ffddcf13 100644 --- a/src/cryptojwt/jwe/__init__.py +++ b/src/cryptojwt/jwe/__init__.py @@ -22,7 +22,14 @@ "ECDH-ES+A192KW", "ECDH-ES+A256KW", ], - "enc": ["A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512", "A128GCM", "A192GCM", "A256GCM",], + "enc": [ + "A128CBC-HS256", + "A192CBC-HS384", + "A256CBC-HS512", + "A128GCM", + "A192GCM", + "A256GCM", + ], } DEPRECATED = { diff --git a/src/cryptojwt/jwe/jwe_ec.py b/src/cryptojwt/jwe/jwe_ec.py index 911a6ea3..3321a8e1 100644 --- a/src/cryptojwt/jwe/jwe_ec.py +++ b/src/cryptojwt/jwe/jwe_ec.py @@ -157,7 +157,12 @@ def dec_setup(self, token, key=None, **kwargs): raise Exception("Unknown key length for algorithm") self.cek = ecdh_derive_key( - key, epubkey.pub_key, apu, apv, str(self.headers["enc"]).encode(), dk_len, + key, + epubkey.pub_key, + apu, + apv, + str(self.headers["enc"]).encode(), + dk_len, ) elif self.headers["alg"] in [ "ECDH-ES+A128KW", diff --git a/src/cryptojwt/jwe/rsa.py b/src/cryptojwt/jwe/rsa.py index 691c3e59..8e7cc4fe 100644 --- a/src/cryptojwt/jwe/rsa.py +++ b/src/cryptojwt/jwe/rsa.py @@ -20,7 +20,9 @@ def encrypt(self, msg, key, sign_padding="pkcs1_padding"): return key.encrypt( msg, _padding( - mgf=padding.MGF1(algorithm=_chosen_hash()), algorithm=_chosen_hash(), label=None, + mgf=padding.MGF1(algorithm=_chosen_hash()), + algorithm=_chosen_hash(), + label=None, ), ) diff --git a/src/cryptojwt/jwk/jwk.py b/src/cryptojwt/jwk/jwk.py index 86f41c47..c9e32904 100644 --- a/src/cryptojwt/jwk/jwk.py +++ b/src/cryptojwt/jwk/jwk.py @@ -93,7 +93,9 @@ def key_from_jwk_dict(jwk_dict, private=None): else: # Ecdsa public key. ec_pub_numbers = ec.EllipticCurvePublicNumbers( - base64url_to_long(_jwk_dict["x"]), base64url_to_long(_jwk_dict["y"]), curve, + base64url_to_long(_jwk_dict["x"]), + base64url_to_long(_jwk_dict["y"]), + curve, ) _jwk_dict["pub_key"] = ec_pub_numbers.public_key(backends.default_backend()) return ECKey(**_jwk_dict) diff --git a/src/cryptojwt/jws/jws.py b/src/cryptojwt/jws/jws.py index b24b0919..c9b334ee 100644 --- a/src/cryptojwt/jws/jws.py +++ b/src/cryptojwt/jws/jws.py @@ -321,7 +321,11 @@ def verify_json(self, jws, keys=None, allow_none=False, at_least_one=False): for _sign in _signs: protected_headers = _sign.get("protected", "") token = b".".join( - [protected_headers.encode(), _payload.encode(), _sign["signature"].encode(),] + [ + protected_headers.encode(), + _payload.encode(), + _sign["signature"].encode(), + ] ) unprotected_headers = _sign.get("header", {}) diff --git a/src/cryptojwt/jws/pss.py b/src/cryptojwt/jws/pss.py index 71cbb3d6..a7443ddb 100644 --- a/src/cryptojwt/jws/pss.py +++ b/src/cryptojwt/jws/pss.py @@ -38,7 +38,8 @@ def sign(self, msg, key): sig = key.sign( digest, padding.PSS( - mgf=padding.MGF1(self.hash_algorithm()), salt_length=padding.PSS.MAX_LENGTH, + mgf=padding.MGF1(self.hash_algorithm()), + salt_length=padding.PSS.MAX_LENGTH, ), utils.Prehashed(self.hash_algorithm()), ) @@ -59,7 +60,8 @@ def verify(self, msg, signature, key): signature, msg, padding.PSS( - mgf=padding.MGF1(self.hash_algorithm()), salt_length=padding.PSS.MAX_LENGTH, + mgf=padding.MGF1(self.hash_algorithm()), + salt_length=padding.PSS.MAX_LENGTH, ), self.hash_algorithm(), ) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index e3356d51..bfd8150c 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -484,7 +484,9 @@ def do_remote(self): self.time_out = time.time() + self.cache_time else: LOGGER.warning( - "HTTP status %d reading remote JWKS from %s", _http_resp.status_code, self.source, + "HTTP status %d reading remote JWKS from %s", + _http_resp.status_code, + self.source, ) self.ignore_errors_until = time.time() + self.ignore_errors_period raise UpdateFailed(REMOTE_FAILED.format(self.source, _http_resp.status_code)) diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 90b08699..c9ab1bb9 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -690,7 +690,10 @@ def dumps(self, exclude_issuers: Optional[List[str]] = None): return json.dumps(_dict) def load( - self, info: dict, init_args: Optional[dict] = None, load_args: Optional[dict] = None, + self, + info: dict, + init_args: Optional[dict] = None, + load_args: Optional[dict] = None, ): """ @@ -811,7 +814,11 @@ def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id=""): @deprecated_alias(issuer="issuer_id", owner="issuer_id") def init_key_jar( - public_path="", private_path="", key_defs="", issuer_id="", read_only=True, + public_path="", + private_path="", + key_defs="", + issuer_id="", + read_only=True, ): """ A number of cases here: @@ -853,7 +860,10 @@ def init_key_jar( """ _issuer = init_key_issuer( - public_path=public_path, private_path=private_path, key_defs=key_defs, read_only=read_only, + public_path=public_path, + private_path=private_path, + key_defs=key_defs, + read_only=read_only, ) if _issuer is None: diff --git a/src/cryptojwt/tools/keyconv.py b/src/cryptojwt/tools/keyconv.py index 5df6b598..a5b27112 100644 --- a/src/cryptojwt/tools/keyconv.py +++ b/src/cryptojwt/tools/keyconv.py @@ -115,7 +115,10 @@ def pem2jwk( def export_jwk( - jwk: JWK, private: bool = False, encrypt: bool = False, passphrase: Optional[str] = None, + jwk: JWK, + private: bool = False, + encrypt: bool = False, + passphrase: Optional[str] = None, ) -> bytes: """Export JWK as PEM/bin""" diff --git a/tests/test_01_simplejwt.py b/tests/test_01_simplejwt.py index 02a944be..9d94a172 100644 --- a/tests/test_01_simplejwt.py +++ b/tests/test_01_simplejwt.py @@ -10,7 +10,10 @@ def _eq(l1, l2): def test_pack_jwt(): _jwt = SimpleJWT(**{"alg": "none", "cty": "jwt"}) jwt = _jwt.pack( - parts=[{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True}, "",] + parts=[ + {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True}, + "", + ] ) p = jwt.split(".") diff --git a/tests/test_02_jwk.py b/tests/test_02_jwk.py index 56209de7..0e1b161a 100644 --- a/tests/test_02_jwk.py +++ b/tests/test_02_jwk.py @@ -720,7 +720,10 @@ def test_x5t_calculation(): @pytest.mark.parametrize( "filename,key_type", - [("ec-public.pem", ec.EllipticCurvePublicKey), ("rsa-public.pem", rsa.RSAPublicKey),], + [ + ("ec-public.pem", ec.EllipticCurvePublicKey), + ("rsa-public.pem", rsa.RSAPublicKey), + ], ) def test_import_public_key_from_pem_file(filename, key_type): _file = full_path(filename) diff --git a/tests/test_04_key_issuer.py b/tests/test_04_key_issuer.py index 864d026e..54d7b0dd 100755 --- a/tests/test_04_key_issuer.py +++ b/tests/test_04_key_issuer.py @@ -222,7 +222,11 @@ def test_build_keyissuer_usage(): def test_build_keyissuer_missing(tmpdir): keys = [ - {"type": "RSA", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} + { + "type": "RSA", + "key": os.path.join(tmpdir.dirname, "missing_file"), + "use": ["enc", "sig"], + } ] key_issuer = build_keyissuer(keys) @@ -240,7 +244,11 @@ def test_build_RSA_keyissuer_from_file(tmpdir): def test_build_EC_keyissuer_missing(tmpdir): keys = [ - {"type": "EC", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} + { + "type": "EC", + "key": os.path.join(tmpdir.dirname, "missing_file"), + "use": ["enc", "sig"], + } ] key_issuer = build_keyissuer(keys) @@ -617,7 +625,10 @@ def test_init_key_issuer_update(): # New set of keys, JWKSs with keys and public written to file _keyissuer_1 = init_key_issuer( - private_path=PRIVATE_FILE, key_defs=KEYSPEC, public_path=PUBLIC_FILE, read_only=False, + private_path=PRIVATE_FILE, + key_defs=KEYSPEC, + public_path=PUBLIC_FILE, + read_only=False, ) assert len(_keyissuer_1) == 2 @@ -647,7 +658,10 @@ def test_init_key_issuer_update(): assert len(_keyissuer_3.get("sig", "EC")) == 1 _keyissuer_4 = init_key_issuer( - private_path=PRIVATE_FILE, key_defs=KEYSPEC_2, public_path=PUBLIC_FILE, read_only=False, + private_path=PRIVATE_FILE, + key_defs=KEYSPEC_2, + public_path=PUBLIC_FILE, + read_only=False, ) # Now it should diff --git a/tests/test_04_key_jar.py b/tests/test_04_key_jar.py index c8ee2ec5..f3f79d49 100755 --- a/tests/test_04_key_jar.py +++ b/tests/test_04_key_jar.py @@ -229,7 +229,11 @@ def test_build_keyjar_usage(): def test_build_keyjar_missing(tmpdir): keys = [ - {"type": "RSA", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} + { + "type": "RSA", + "key": os.path.join(tmpdir.dirname, "missing_file"), + "use": ["enc", "sig"], + } ] key_jar = build_keyjar(keys) @@ -247,7 +251,11 @@ def test_build_RSA_keyjar_from_file(tmpdir): def test_build_EC_keyjar_missing(tmpdir): keys = [ - {"type": "EC", "key": os.path.join(tmpdir.dirname, "missing_file"), "use": ["enc", "sig"],} + { + "type": "EC", + "key": os.path.join(tmpdir.dirname, "missing_file"), + "use": ["enc", "sig"], + } ] key_jar = build_keyjar(keys) @@ -303,7 +311,8 @@ def test_items(self): ), ) ks.add_kb( - "http://www.example.org", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org", + keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert len(ks.items()) == 2 @@ -329,7 +338,8 @@ def test_issuer_extra_slash(self): ), ) ks.add_kb( - "http://www.example.org", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org", + keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("sig", "RSA", "http://www.example.org/") @@ -355,7 +365,8 @@ def test_issuer_missing_slash(self): ), ) ks.add_kb( - "http://www.example.org/", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org/", + keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("sig", "RSA", "http://www.example.org") @@ -381,7 +392,8 @@ def test_get_enc(self): ), ) ks.add_kb( - "http://www.example.org/", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org/", + keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("enc", "oct") @@ -407,7 +419,8 @@ def test_get_enc_not_mine(self): ), ) ks.add_kb( - "http://www.example.org/", keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), + "http://www.example.org/", + keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]), ) assert ks.get("enc", "oct", "http://www.example.org/") @@ -449,7 +462,8 @@ def test_provider(self): kj = KeyJar() _url = "https://connect-op.herokuapp.com/jwks.json" kj.load_keys( - "https://connect-op.heroku.com", jwks_uri=_url, + "https://connect-op.heroku.com", + jwks_uri=_url, ) iss_keys = kj.get_issuer_keys("https://connect-op.heroku.com") if not iss_keys: @@ -974,7 +988,10 @@ def test_init_key_jar_update(): assert len(_keyjar_3.get_signing_key("EC")) == 1 _keyjar_4 = init_key_jar( - private_path=PRIVATE_FILE, key_defs=KEYSPEC_2, public_path=PUBLIC_FILE, read_only=False, + private_path=PRIVATE_FILE, + key_defs=KEYSPEC_2, + public_path=PUBLIC_FILE, + read_only=False, ) # Now it should diff --git a/tests/test_06_jws.py b/tests/test_06_jws.py index 96b15ac2..c452e0b5 100644 --- a/tests/test_06_jws.py +++ b/tests/test_06_jws.py @@ -431,7 +431,8 @@ def test_jws_mm(): @pytest.mark.parametrize( - "ec_func,alg", [(ec.SECP256R1, "ES256"), (ec.SECP384R1, "ES384"), (ec.SECP521R1, "ES512")], + "ec_func,alg", + [(ec.SECP256R1, "ES256"), (ec.SECP384R1, "ES384"), (ec.SECP521R1, "ES512")], ) def test_signer_es(ec_func, alg): payload = "Please take a moment to register today" @@ -706,7 +707,9 @@ def test_sign_json_dont_flatten_if_multiple_signatures(): key = ECKey().load_key(P256()) unprotected_headers = {"foo": "bar"} _jwt = JWS(msg="hello world", alg="ES256").sign_json( - headers=[(None, unprotected_headers), (None, {"abc": "xyz"})], keys=[key], flatten=True, + headers=[(None, unprotected_headers), (None, {"abc": "xyz"})], + keys=[key], + flatten=True, ) assert "signatures" in json.loads(_jwt) diff --git a/tests/test_09_jwt.py b/tests/test_09_jwt.py index 84a859f5..d016b211 100755 --- a/tests/test_09_jwt.py +++ b/tests/test_09_jwt.py @@ -25,10 +25,16 @@ def full_path(local_file): # k2 = import_private_rsa_key_from_file(full_path('size2048.key')) kb1 = KeyBundle( - source="file://{}".format(full_path("rsa.key")), fileformat="der", keyusage="sig", kid="1", + source="file://{}".format(full_path("rsa.key")), + fileformat="der", + keyusage="sig", + kid="1", ) kb2 = KeyBundle( - source="file://{}".format(full_path("size2048.key")), fileformat="der", keyusage="enc", kid="2", + source="file://{}".format(full_path("size2048.key")), + fileformat="der", + keyusage="enc", + kid="2", ) ALICE_KEY_JAR = KeyJar() @@ -36,7 +42,10 @@ def full_path(local_file): ALICE_KEY_JAR.add_kb(ALICE, kb2) kb3 = KeyBundle( - source="file://{}".format(full_path("server.key")), fileformat="der", keyusage="enc", kid="3", + source="file://{}".format(full_path("server.key")), + fileformat="der", + keyusage="enc", + kid="3", ) BOB_KEY_JAR = KeyJar() diff --git a/tests/test_50_argument_alias.py b/tests/test_50_argument_alias.py index 799ce52f..8831fb14 100644 --- a/tests/test_50_argument_alias.py +++ b/tests/test_50_argument_alias.py @@ -172,7 +172,10 @@ def test_init_key_jar_update(): assert len(_keyjar_3.get_signing_key("EC")) == 1 _keyjar_4 = init_key_jar( - private_path=PRIVATE_FILE, key_defs=KEYSPEC_2, public_path=PUBLIC_FILE, read_only=False, + private_path=PRIVATE_FILE, + key_defs=KEYSPEC_2, + public_path=PUBLIC_FILE, + read_only=False, ) # Now it should From 5b654f549397bf385d3e8964a9d848e84624c232 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Tue, 19 Oct 2021 11:24:21 +0200 Subject: [PATCH 4/4] Per jschlyter's comments --- src/cryptojwt/jwk/__init__.py | 2 +- src/cryptojwt/jwk/ec.py | 2 +- src/cryptojwt/jwk/hmac.py | 2 +- src/cryptojwt/jwk/rsa.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cryptojwt/jwk/__init__.py b/src/cryptojwt/jwk/__init__.py index e22ec836..ea2aea32 100644 --- a/src/cryptojwt/jwk/__init__.py +++ b/src/cryptojwt/jwk/__init__.py @@ -291,7 +291,7 @@ def update(self): pass def key_len(self): - raise NotImplemented() + raise NotImplemented def pems_to_x5c(cert_chain): diff --git a/src/cryptojwt/jwk/ec.py b/src/cryptojwt/jwk/ec.py index 1884dd71..88134308 100644 --- a/src/cryptojwt/jwk/ec.py +++ b/src/cryptojwt/jwk/ec.py @@ -262,7 +262,7 @@ def key_len(self): elif self.pub_key: return self.pub_key.key_size else: - raise KeyNotFound() + raise KeyNotFound def cmp_keys(a, b, key_type): diff --git a/src/cryptojwt/jwk/hmac.py b/src/cryptojwt/jwk/hmac.py index 31448c4d..f86c366d 100644 --- a/src/cryptojwt/jwk/hmac.py +++ b/src/cryptojwt/jwk/hmac.py @@ -155,7 +155,7 @@ def key_len(self): if self.key: return len(self.key) else: - raise KeyNotFound() + raise KeyNotFound def new_sym_key(use="", bytes=24, kid=""): diff --git a/src/cryptojwt/jwk/rsa.py b/src/cryptojwt/jwk/rsa.py index 54432431..ab24a2bb 100644 --- a/src/cryptojwt/jwk/rsa.py +++ b/src/cryptojwt/jwk/rsa.py @@ -478,7 +478,7 @@ def key_len(self): elif self.pub_key: return self.pub_key.key_size else: - raise KeyNotFound() + raise KeyNotFound def new_rsa_key(key_size=2048, kid="", public_exponent=65537, **kwargs):