def test_cmp_neq_ec(): priv, pub = P256.key_pair() _key1 = ECKey(x=pub[0], y=pub[1], d=priv, crv="P-256") _key2 = ECKey(**ECKEY) try: assert _key1 == _key2 except AssertionError: pass else: assert False
def test_import_export_eckey(): _key = ECKey(**ECKEY) _key.deserialize() _key.serialize() exp_key = _key.to_dict() assert _eq(exp_key.keys(), ["y", "x", "crv", "kty", "d"])
def test_cmp_rsa_ec(): _key1 = RSAKey() _key1.load_key(pem_cert2rsa(CERT)) _key2 = ECKey(**ECKEY) assert _key1 != _key2
def enc_setup(self, msg, auth_data, key=None, **kwargs): encrypted_key = "" # Generate the input parameters try: apu = b64d(kwargs["apu"]) except KeyError: apu = b64d(Random.get_random_bytes(16)) try: apv = b64d(kwargs["apv"]) except KeyError: apv = b64d(Random.get_random_bytes(16)) # Generate an ephemeral key pair curve = NISTEllipticCurve.by_name(key.crv) if "epk" in kwargs: epk = ECKey(key=kwargs["epk"], private=False) eprivk = ECKey(kwargs["epk"], private=True) else: (eprivk, epk) = curve.key_pair() # Derive the KEK and encrypt params = { "apu": b64e(apu), "apv": b64e(apv), #"epk": exportKey(epk, "EC", curve) } cek, iv = self._generate_key_and_iv(self.enc) if self.alg == "ECDH-ES": try: dk_len = KEYLEN[self.enc] except KeyError: raise Exception("Unknown key length for algorithm %s" % self.enc) cek = ecdh_derive_key(curve, eprivk, key, apu, apv, self.enc, dk_len) elif self.alg in [ "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW" ]: _pre, _post = self.alg.split("+") klen = int(_post[1:4]) kek = ecdh_derive_key(curve, eprivk, key, apu, apv, _post, klen) encrypted_key = aes_wrap_key(kek, cek) else: raise Exception("Unsupported algorithm %s" % self.alg) return cek, encrypted_key, iv, params
def test_signer_es384(): payload = "Please take a moment to register today" _key = ECKey().load_key(P384) keys = [_key] _jws = JWS(payload, alg="ES384") _jwt = _jws.sign_compact(keys) _rj = JWS() info = _rj.verify_compact(_jwt, keys) assert info == payload
def test_signer_es256_verbose(): payload = "Please take a moment to register today" _key = ECKey().load_key(P256) keys = [_key] _jws = JWS(payload, alg="ES256") _jwt = _jws.sign_compact(keys) _rj = JWS() info = _rj.verify_compact_verbose(_jwt, keys) assert info['msg'] == payload assert info['key'] == _key
def test_signer_es512(): payload = "Please take a moment to register today" _key = ECKey().load_key(P521) keys = [_key] #keys[0]._keytype = "private" _jws = JWS(payload, alg="ES512") _jwt = _jws.sign_compact(keys) _rj = JWS() info = _rj.verify_compact(_jwt, keys) assert info == payload
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) assert "signatures" in json.loads(_jwt)
def test_verify_json(): key = ECKey().load_key(P256) payload = "hello world" unprotected_headers = {"abc": "xyz"} protected_headers = {"foo": "bar"} _jwt = JWS(msg=payload, alg="ES256").sign_json(headers=[ (protected_headers, unprotected_headers) ], keys=[key]) assert JWS().verify_json(_jwt, keys=[key])
def test_sign_json_dont_include_empty_protected_headers(): key = ECKey().load_key(P256) unprotected_headers = {"foo": "bar"} _jwt = JWS(msg="hello world", alg="ES256").sign_json(headers=[(None, unprotected_headers)], keys=[key]) json_jws = json.loads(_jwt) jws_protected_headers = json.loads( b64d_enc_dec(json_jws["signatures"][0]["protected"])) assert jws_protected_headers == {"alg": "ES256"} jws_unprotected_headers = json_jws["signatures"][0]["header"] assert unprotected_headers == jws_unprotected_headers
def test_cmp_rsa_ec(): _key1 = RSAKey() _key1.load_key(pem_cert2rsa(CERT)) _key2 = ECKey(**ECKEY) try: assert _key1 == _key2 except AssertionError: pass else: assert False
def test_sign_json_dont_include_empty_unprotected_headers(): key = ECKey().load_key(P256) protected_headers = {"foo": "bar"} _jwt = JWS(msg="hello world", alg="ES256").sign_json(headers=[(protected_headers, None)], keys=[key]) json_jws = json.loads(_jwt) assert "header" not in json_jws["signatures"][0] jws_protected_headers = json.loads( b64d_enc_dec(json_jws["signatures"][0]["protected"])) assert set(protected_headers.items()).issubset( set(jws_protected_headers.items()))
def id_token_as_signed_jwt(self, session, loa="2", alg="", code=None, access_token=None, user_info=None, auth_time=0, exp=None, extra_claims=None, **kwargs): kwargs = {} if "rotsig" in self.behavior_type: # Rollover signing keys if alg == "RS256": key = RSAKey(kid="rotated_rsa_{}".format(time.time()), use="sig").load_key(RSA.generate(2048)) else: # alg == "ES256" key = ECKey(kid="rotated_ec_{}".format(time.time()), use="sig").load_key(P256) new_keys = {"keys": [key.serialize(private=True)]} self.events.store("New signing keys", new_keys) self.do_key_rollover(new_keys, "%d") self.events.store("Rotated signing keys", '') if "nokid1jwks" in self.behavior_type: kwargs['keys'] = self.no_kid_keys() # found_key = None # for kb in self.keyjar.key_summary[""]: # issuer_key = list(kb.keys())[0] # if issuer_key.use == "sig" and \ # issuer_key.kty.startswith( # alg[:2]): # issuer_key.kid = None # found_key = key # break # self.keyjar.key_summary[""] = [found_key] if "nokidmuljwks" in self.behavior_type: kwargs['keys'] = self.no_kid_keys() # for key in self.keyjar.key_summary[""]: # for inner_key in list(key.keys()): # inner_key.kid = None _jws = provider.Provider.id_token_as_signed_jwt( self, session, loa=loa, alg=alg, code=code, access_token=access_token, user_info=user_info, auth_time=auth_time, exp=exp, extra_claims=extra_claims, **kwargs) if "idts" in self.behavior_type: # mess with the signature # p = _jws.split(".") p[2] = sort_string(p[2]) _jws = ".".join(p) return _jws
def test_sign_json(): key = ECKey().load_key(P256) payload = "hello world" unprotected_headers = {"abc": "xyz"} protected_headers = {"foo": "bar"} _jwt = JWS(msg=payload, alg="ES256").sign_json(headers=[ (protected_headers, unprotected_headers) ], keys=[key]) jwt = json.loads(_jwt) assert b64d_enc_dec(jwt["payload"]) == payload assert len(jwt["signatures"]) == 1 assert jwt["signatures"][0]["header"] == unprotected_headers assert json.loads(b64d_enc_dec( jwt["signatures"][0]["protected"])) == protected_headers
def ec_init(spec): """ :param spec: Key specifics of the form {"type": "EC", "crv": "P-256", "use": ["sig"]}, :return: A KeyBundle instance """ _key = NISTEllipticCurve.by_name(spec["crv"]) kb = KeyBundle(keytype="EC", keyusage=spec["use"]) for use in spec["use"]: priv, pub = _key.key_pair() ec = ECKey(x=pub[0], y=pub[1], d=priv, crv=spec["crv"]) ec.serialize() ec.use = use kb.append(ec) return kb
def test_sign_json_flattened_syntax(): key = ECKey().load_key(P256) protected_headers = {"foo": "bar"} unprotected_headers = {"abc": "xyz"} payload = "hello world" _jwt = JWS(msg=payload, alg="ES256").sign_json(headers=[ (protected_headers, unprotected_headers) ], keys=[key], flatten=True) json_jws = json.loads(_jwt) assert "signatures" not in json_jws assert b64d_enc_dec(json_jws["payload"]) == payload assert json_jws["header"] == unprotected_headers assert json.loads(b64d_enc_dec(json_jws["protected"])) == protected_headers
def test_signer_protected_headers(): payload = "Please take a moment to register today" _key = ECKey().load_key(P256) keys = [_key] _jws = JWS(payload, alg="ES256") protected = dict(header1=u"header1 is protected", header2="header2 is protected too", a=1) _jwt = _jws.sign_compact(keys, protected=protected) exp_protected = protected.copy() exp_protected['alg'] = 'ES256' enc_header, enc_payload, sig = _jwt.split('.') assert json.loads(b64d(enc_header.encode("utf-8")).decode("utf-8")) == exp_protected assert b64d(enc_payload.encode("utf-8")).decode("utf-8") == payload _rj = JWS() info = _rj.verify_compact(_jwt, keys) assert info == payload
def test_signer_es512(): payload = "Please take a moment to register today" _key = ECKey( crv="P-521", x= "AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk", y= "ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDly79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2", d="AY5pb7A0UFiB3RELSD64fTLOSV_jazdF7fLYyuTw8lOfRhWg6Y6rUrPAxerEzgdRhajnu0ferB0d53vM9mE15j2C" ) _key.deserialize() keys = [_key] #keys[0]._keytype = "private" _jws = JWS(payload, alg="ES512") _jwt = _jws.sign_compact(keys) _rj = JWS() info = _rj.verify_compact(_jwt, keys) assert info == payload
def dec_setup(self, token, key=None, **kwargs): self.headers = token.headers self.iv = token.initialization_vector() self.ctxt = token.ciphertext() self.tag = token.authentication_tag() # Handle EPK / Curve if "epk" not in self.headers or "crv" not in self.headers["epk"]: raise Exception( "Ephemeral Public Key Missing in ECDH-ES Computation") epubkey = ECKey(**self.headers["epk"]) apu = apv = "" if "apu" in self.headers: apu = b64d(self.headers["apu"].encode()) if "apv" in self.headers: apv = b64d(self.headers["apv"].encode()) if self.headers["alg"] == "ECDH-ES": try: dk_len = KEYLEN[self.headers["enc"]] except KeyError: raise Exception("Unknown key length for algorithm") self.cek = ecdh_derive_key(epubkey.curve, key.d, (epubkey.x, epubkey.y), apu, apv, str(self.headers["enc"]).encode(), dk_len) elif self.headers["alg"] in [ "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW" ]: _pre, _post = self.headers['alg'].split("+") klen = int(_post[1:4]) kek = ecdh_derive_key(epubkey.curve, key.d, (epubkey.x, epubkey.y), apu, apv, str(_post).encode(), klen) self.cek = aes_unwrap_key(kek, token.encrypted_key()) else: raise Exception("Unsupported algorithm %s" % self.headers["alg"]) return self.cek
def test_verify_protected_headers(): payload = "Please take a moment to register today" _key = ECKey().load_key(P256) keys = [_key] _jws = JWS(payload, alg="ES256") protected = dict(header1=u"header1 is protected", header2="header2 is protected too", a=1) _jwt = _jws.sign_compact(keys, protected=protected) protectedHeader, enc_payload, sig = _jwt.split(".") data = dict(payload=enc_payload, signatures=[ dict( header=dict(alg=u"ES256", jwk=_key.serialize()), protected=protectedHeader, signature=sig, ) ]) fobj = io.BytesIO(JSONEncoder().encode(data).encode("utf-8")) _jws = JWS() reader = codecs.getreader("utf-8") assert _jws.verify_json(reader(fobj)) == payload
def test_verify_protected_headers(): payload = "Please take a moment to register today" _key = ECKey().load_key(P256) keys = [_key] _jws = JWS(payload, alg="ES256") protected = dict(header1=u"header1 is protected", header2="header2 is protected too", a=1) _jwt = _jws.sign_compact(keys, protected=protected) protectedHeader, enc_payload, sig = _jwt.split(".") data = dict(payload=enc_payload, signatures=[ dict( header=dict(alg=u"ES256", jwk=_key.serialize()), protected=protectedHeader, signature=sig, ) ]) _jws = JWS() assert _jws.verify_json(json.dumps(data)) == payload
def generate_jwks(self, mode): if "rotenc" in self.behavior_type: # Rollover encryption keys rsa_key = RSAKey(kid="rotated_rsa_{}".format(time.time()), use="enc").load_key(RSA.generate(2048)) ec_key = ECKey(kid="rotated_ec_{}".format(time.time()), use="enc").load_key(P256) keys = [ rsa_key.serialize(private=True), ec_key.serialize(private=True) ] new_keys = {"keys": keys} #self.do_key_rollover(new_keys, "%d") signing_keys = [k.to_dict() for k in self.keyjar.get_signing_key()] new_keys["keys"].extend(signing_keys) return json.dumps(new_keys) elif "nokid1jwk" in self.behavior_type: alg = mode["sign_alg"] if not alg: alg = "RS256" keys = [ k.to_dict() for kb in self.keyjar[""] for k in list(kb.keys()) ] for key in keys: if key["use"] == "sig" and key["kty"].startswith(alg[:2]): key.pop("kid", None) jwk = dict(keys=[key]) return json.dumps(jwk) raise Exception( "Did not find sig {} key for nokid1jwk test ".format(alg)) else: # Return all keys keys = [ k.to_dict() for kb in self.keyjar[""] for k in list(kb.keys()) ] jwks = dict(keys=keys) return json.dumps(jwks)
def setUpClass(cls): cls.file_name = full_test_path("test_data/clients.json") with open(full_test_path("test_data/clients.json")) as f: cls.METADATA_FROM_FILE = json.load(f) sym_key = SYMKey(key=TestMDQHandler.SYM_KEY_PHRASE) rsa_key = RSAKey(key=import_rsa_key_from_file( full_test_path("test_data/certs/rsa2048"))) cls.EC_KEY = ECKey().load_key(P256) signing_keys = { "HS256": sym_key, "RS256": rsa_key, "ES256": cls.EC_KEY } cls.SIGNING_ALGS_SUPPORTED = signing_keys.keys() cls.MDQ = MDQHandler(cls.file_name, 36000, signing_keys) cherrypy.config.update({"environment": "test_suite"}) cherrypy.server.socket_host = "0.0.0.0" cherrypy.server.socket_port = cls.SERVER_PORT cherrypy.tree.mount(cls.MDQ, "/", CHERRYPY_CONFIG) cherrypy.engine.start()
def test_cmp_neq_ec(): priv, pub = P256.key_pair() _key1 = ECKey(x=pub[0], y=pub[1], d=priv, crv="P-256") _key2 = ECKey(**ECKEY) assert _key1 != _key2
def test_create_eckey(): priv, pub = P256.key_pair() ec = ECKey(x=pub[0], y=pub[1], d=priv, crv="P-256") exp_key = ec.serialize() assert _eq(list(exp_key.keys()), ["y", "x", "crv", "kty"])
def test_import_export_eckey(): _key = ECKey(**ECKEY) _key.deserialize() assert _eq(list(_key.keys()), ["y", "x", "d", "crv", "kty"])
def test_is_jws_recognize_flattened_json_serialized_jws(): key = ECKey().load_key(P256) jws = JWS(msg="hello world", alg="ES256").sign_json([key], flatten=True) assert JWS().is_jws(jws)
def authorization_endpoint(self, request="", cookie=None, **kwargs): if isinstance(request, dict): _req = request else: _req = {} for key, val in parse_qs(request).items(): if len(val) == 1: _req[key] = val[0] else: _req[key] = val # self.events.store(EV_REQUEST, _req) try: _scope = _req["scope"] except KeyError: return error( error="incorrect_behavior", descr="No scope parameter" ) else: # verify that openid is among the scopes _scopes = _scope.split(" ") if "openid" not in _scopes: return error( error="incorrect_behavior", descr="Scope does not contain 'openid'" ) client_id = _req["client_id"] try: f = response_type_cmp(self.capabilities['response_types_supported'], _req['response_type']) except KeyError: pass else: if f is False: self.events.store( EV_FAULT, 'Wrong response type: {}'.format(_req['response_type'])) return error_response(error="incorrect_behavior", descr="Not supported response_type") _rtypes = _req['response_type'].split(' ') if 'id_token' in _rtypes: try: self._update_client_keys(client_id) except TestError: return error(error="incorrect_behavior", descr="No change in client keys") if isinstance(request, dict): request = urlencode(request) _response = provider.Provider.authorization_endpoint(self, request, cookie, **kwargs) if "rotenc" in self.behavior_type: # Rollover encryption keys rsa_key = RSAKey(kid="rotated_rsa_{}".format(time.time()), use="enc").load_key(RSA.generate(2048)) ec_key = ECKey(kid="rotated_ec_{}".format(time.time()), use="enc").load_key(P256) keys = [rsa_key.serialize(private=True), ec_key.serialize(private=True)] new_keys = {"keys": keys} self.events.store("New encryption keys", new_keys) self.do_key_rollover(new_keys, "%d") self.events.store("Rotated encryption keys", '') logger.info( 'Rotated OP enc keys, new set: {}'.format( key_summary(self.keyjar, ''))) # This is just for logging purposes try: _resp = self.server.http_request(_req["request_uri"]) except KeyError: pass except requests.ConnectionError as err: self.events.store(EV_EXCEPTION, err) err = unwrap_exception(err) return error_response(error="server_error", descr=err) else: if _resp.status_code == 200: self.events.store(EV_REQUEST, "Request from request_uri: {}".format( _resp.text)) return _response
from jwkest.jwk import ECKey from Cryptodome.PublicKey import ECC ecc_key = ECC.generate(curve='P-256') jwk = ECKey(key=ecc_key) jwk.serialize(private=True)
def enc_setup(self, msg, auth_data, key=None, **kwargs): encrypted_key = "" self.msg = msg self.auth_data = auth_data # Generate the input parameters try: apu = b64d(kwargs["apu"]) except KeyError: apu = Random.get_random_bytes(16) try: apv = b64d(kwargs["apv"]) except KeyError: apv = Random.get_random_bytes(16) # Handle Local Key and Ephemeral Public Key if not key: raise Exception("EC Key Required for ECDH-ES JWE Encrpytion Setup") # Generate an ephemeral key pair if none is given curve = NISTEllipticCurve.by_name(key.crv) if "epk" in kwargs: epk = kwargs["epk"] if isinstance(kwargs["epk"], ECKey) else ECKey(kwargs["epk"]) else: raise Exception( "Ephemeral Public Key (EPK) Required for ECDH-ES JWE " "Encryption Setup") params = { "apu": b64e(apu), "apv": b64e(apv), "epk": epk.serialize(False) } cek = iv = None if 'cek' in kwargs and kwargs['cek']: cek = kwargs['cek'] if 'iv' in kwargs and kwargs['iv']: iv = kwargs['iv'] cek, iv = self._generate_key_and_iv(self.enc, cek=cek, iv=iv) if self.alg == "ECDH-ES": try: dk_len = KEYLEN[self.enc] except KeyError: raise Exception( "Unknown key length for algorithm %s" % self.enc) cek = ecdh_derive_key(curve, epk.d, (key.x, key.y), apu, apv, str(self.enc).encode(), dk_len) elif self.alg in ["ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"]: _pre, _post = self.alg.split("+") klen = int(_post[1:4]) kek = ecdh_derive_key(curve, epk.d, (key.x, key.y), apu, apv, str(_post).encode(), klen) encrypted_key = aes_wrap_key(kek, cek) else: raise Exception("Unsupported algorithm %s" % self.alg) return cek, encrypted_key, iv, params, epk