def test_creat_jwks_sym(): a = {"kty": "oct", "key": "supersecret", "use": "sig"} kb = KeyBundle([a]) _jwks = kb.jwks() _loc = json.loads(_jwks) assert list(_loc.keys()) == ["keys"] assert set(_loc['keys'][0].keys()) == {'kty', 'use', 'k'}
def key_setup(vault, **kwargs): """ :param vault: Where the keys are kept :return: 2-tuple: result of urlsplit and a dictionary with parameter name as key and url and value """ vault_path = proper_path(vault) if not os.path.exists(vault_path): os.makedirs(vault_path) kb = KeyBundle() for usage in ["sig", "enc"]: if usage in kwargs: if kwargs[usage] is None: continue _args = kwargs[usage] if _args["alg"].upper() == "RSA": try: _key = rsa_load('%s%s' % (vault_path, "pyoidc")) except Exception: devnull = open(os.devnull, 'w') with RedirectStdStreams(stdout=devnull, stderr=devnull): _key = create_and_store_rsa_key_pair( path=vault_path) k = RSAKey(key=_key, use=usage) k.add_kid() kb.append(k) return kb
def test_remove_sym(): a = {"kty": "oct", "key": "supersecret", "use": "sig"} b = {"kty": "oct", "key": "secret", "use": "enc"} kb = KeyBundle([a, b]) assert len(kb) == 2 keys = kb.get('oct') kb.remove(keys[0]) assert len(kb) == 1
def test_with_2_sym_key(): a = {"kty": "oct", "key": "supersecret", "use": "sig"} b = {"kty": "oct", "key": "secret", "use": "enc"} kb = KeyBundle([a, b]) assert len(kb.get("oct")) == 2 assert len(kb) == 2 assert kb.get_key_with_kid('kid') is None assert kb.kids() == []
def test_outdated(): a = {"kty": "oct", "key": "supersecret", "use": "sig"} b = {"kty": "oct", "key": "secret", "use": "enc"} kb = KeyBundle([a, b]) keys = kb.keys() now = time.time() keys[0].inactive_since = now - 60 kb.remove_outdated(30) assert len(kb) == 1
def test_mark_as_inactive(): desc = {"kty": "oct", "key": "supersecret", "use": "sig"} kb = KeyBundle([desc]) assert len(kb.keys()) == 1 for k in kb.keys(): kb.mark_as_inactive(k.kid) desc = {"kty": "oct", "key": "secret", "use": "enc"} kb.do_keys([desc]) assert len(kb.keys()) == 2 assert len(kb.active_keys()) == 1
def ec_init(spec): """ Initiate a keybundle with an elliptic curve key. :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_copy(): kj = KeyJar() kj['A'] = [KeyBundle(JWK0['keys'])] kj['B'] = [KeyBundle(JWK1['keys'])] kj['C'] = [KeyBundle(JWK2['keys'])] kjc = kj.copy() assert set(kjc.owners()) == {'A', 'B', 'C'} assert len(kjc.get('sig', 'oct', 'A')) == 0 assert len(kjc.get('sig', 'rsa', 'A')) == 1 assert len(kjc.get('sig', 'oct', 'B')) == 1 assert len(kjc.get('sig', 'rsa', 'B')) == 1 assert len(kjc.get('sig', 'oct', 'C')) == 0 assert len(kjc.get('sig', 'rsa', 'C')) == 4
def test_construct(self, client): _key = rsa_load(os.path.join(BASE_PATH, "data/keys/rsa.key")) kc_rsa = KeyBundle([{ "key": _key, "kty": "RSA", "use": "ver" }, { "key": _key, "kty": "RSA", "use": "sig" }]) client.client_info.keyjar[""] = kc_rsa client.client_info.provider_info = { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" } client.service['accesstoken'].endpoint = "https://example.com/token" request = AccessTokenRequest() pkj = PrivateKeyJWT() http_args = pkj.construct(request, cli_info=client.client_info, algorithm="RS256", authn_endpoint='token') assert http_args == {} cas = request["client_assertion"] pub_kb = KeyBundle([{ "key": _key.public_key(), "kty": "RSA", "use": "ver" }, { "key": _key.public_key(), "kty": "RSA", "use": "sig" }]) jso = JWT(rec_keys={client.client_id: pub_kb.get('RSA')}).unpack(cas) assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) #assert _jwt.headers == {'alg': 'RS256'} assert jso['aud'] == [ client.client_info.provider_info['token_endpoint'] ]
def test_dump_jwks(): kb1 = rsa_init({ 'use': ['enc', 'sig'], 'size': 1024, 'name': 'rsa', 'path': 'keys' }) a = {"kty": "oct", "key": "supersecret", "use": "sig"} b = {"kty": "oct", "key": "secret", "use": "enc"} kb2 = KeyBundle([a, b]) dump_jwks([kb1, kb2], 'jwks_combo') # Now read it nkb = KeyBundle(source='file://jwks_combo', fileformat='jwks') assert len(nkb) == 2 # both RSA keys assert len(nkb.get('rsa')) == 2
def test_construct_client_assertion(self, client): _key = rsa_load(os.path.join(BASE_PATH, "data/keys/rsa.key")) kc_rsa = KeyBundle([{ "key": _key, "kty": "RSA", "use": "ver" }, { "key": _key, "kty": "RSA", "use": "sig" }]) request = AccessTokenRequest() pkj = PrivateKeyJWT() _ca = assertion_jwt(client.client_id, kc_rsa.get('RSA'), "https://example.com/token", 'RS256') http_args = pkj.construct(request, client_assertion=_ca) assert http_args == {} assert request['client_assertion'] == _ca assert request['client_assertion_type'] == JWT_BEARER
def test_ignore_unknown_types(): kb = KeyBundle({ "kid": "q-H9y8iuh3BIKZBbK6S0mH_isBlJsk" "-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw", "use": "sig", "alg": "EdDSA", "kty": "OKP", "crv": "Ed25519", "x": "FnbcUAXZ4ySvrmdXK1MrDuiqlqTXvGdAaE4RWZjmFIQ" }) assert len(kb) == 0
def test_remove_key_sym(): a = {"kty": "oct", "key": "supersecret", "use": "sig"} b = {"kty": "oct", "key": "secret", "use": "enc"} kb = KeyBundle([a, b]) assert len(kb) == 2 keys = kb.get('oct') kb.remove(keys[0]) assert len(kb) == 1 # This should not work kb.remove_keys_by_type('rsa') # should still be one assert len(kb) == 1
def test_key_export(): kj = KeyJar() url = key_export("http://example.com/keys/", "outbound", "secret", keyjar=kj, sig={ "alg": "rsa", "format": ["x509", "jwks"] }) assert url == "http://example.com/keys/outbound/jwks" # Now a jwks should reside in './keys/outbound/jwks' kb = KeyBundle(source='file://./keys/outbound/jwks') # One key assert len(kb) == 1 # more specifically one RSA key assert len(kb.get('RSA')) == 1 k = kb.get('RSA')[0] # For signing assert k.use == 'sig'
def test_items(self): ks = KeyJar() ks[""] = KeyBundle([{ "kty": "oct", "key": "a1b2c3d4", "use": "sig" }, { "kty": "oct", "key": "a1b2c3d4", "use": "ver" }]) ks["http://www.example.org"] = KeyBundle([{ "kty": "oct", "key": "e5f6g7h8", "use": "sig" }, { "kty": "oct", "key": "e5f6g7h8", "use": "ver" }]) ks["http://www.example.org"].append( keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"])) assert len(ks.items()) == 2
def test_issuer_missing_slash(self): ks = KeyJar() ks[""] = KeyBundle([{ "kty": "oct", "key": "a1b2c3d4", "use": "sig" }, { "kty": "oct", "key": "a1b2c3d4", "use": "ver" }]) ks["http://www.example.org/"] = KeyBundle([{ "kty": "oct", "key": "e5f6g7h8", "use": "sig" }, { "kty": "oct", "key": "e5f6g7h8", "use": "ver" }]) ks["http://www.example.org/"].append( keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"])) assert ks.get('sig', 'RSA', 'http://www.example.org')
def test_get_enc_not_mine(self): ks = KeyJar() ks[""] = KeyBundle([{ "kty": "oct", "key": "a1b2c3d4", "use": "sig" }, { "kty": "oct", "key": "a1b2c3d4", "use": "enc" }]) ks["http://www.example.org/"] = KeyBundle([{ "kty": "oct", "key": "e5f6g7h8", "use": "sig" }, { "kty": "oct", "key": "e5f6g7h8", "use": "ver" }]) ks["http://www.example.org/"].append( keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"])) assert ks.get('enc', 'oct', 'http://www.example.org/')
def test_update(): kc = KeyBundle([{"kty": "oct", "key": "supersecret", "use": "sig"}]) assert len(kc.get("oct")) == 1 assert len(kc.get("rsa")) == 0 assert kc.remote is False assert kc.source is None kc.update() # Nothing should happen assert len(kc.get("oct")) == 1 assert len(kc.get("rsa")) == 0 assert kc.remote is False assert kc.source is None
sys.path.append( os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) __author__ = 'Roland Hedberg' CLIENT_ID = "client_1" IDTOKEN = IdToken(iss="http://oic.example.org/", sub="sub", aud=CLIENT_ID, exp=utc_time_sans_frac() + 300, nonce="N0nce", iat=time.time()) KC_SYM_S = KeyBundle({ "kty": "oct", "key": "abcdefghijklmnop".encode("utf-8"), "use": "sig", "alg": "HS256" }) def query_string_compare(query_str1, query_str2): return parse_qs(query_str1) == parse_qs(query_str2) def _eq(l1, l2): return set(l1) == set(l2) def test_openidschema(): inp = '{"middle_name":null, "updated_at":"20170328081544", "sub":"abc"}' ois = OpenIDSchema().from_json(inp)
from oiccli.oauth2 import Client from oicmsg.key_bundle import KeyBundle from oicmsg.oauth2 import AccessTokenRequest from oicmsg.oauth2 import AccessTokenResponse from oicmsg.oauth2 import AuthorizationRequest from oicmsg.oauth2 import RefreshAccessTokenRequest from oicmsg.oic import IdToken from oicmsg.time_util import utc_time_sans_frac sys.path.insert(0, '.') BASE_PATH = os.path.abspath( os.path.join(os.path.dirname(__file__), "data/keys")) _key = rsa_load(os.path.join(BASE_PATH, "rsa.key")) KC_RSA = KeyBundle({"key": _key, "kty": "RSA", "use": "sig"}) CLIENT_ID = "client_1" IDTOKEN = IdToken(iss="http://oic.example.org/", sub="sub", aud=CLIENT_ID, exp=utc_time_sans_frac() + 86400, nonce="N0nce", iat=time.time()) class TestClient(object): @pytest.fixture(autouse=True) def create_client(self): self.redirect_uri = "http://example.com/redirect" conf = {
def build_keyjar(key_conf, kid_template="", keyjar=None, kidd=None): """ Initiates a new :py:class:`oicmsg.oauth2.Message` instance and populates it with keys according to the key configuration. Configuration of the type :: keys = [ {"type": "RSA", "key": "cp_keys/key.pem", "use": ["enc", "sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, {"type": "EC", "crv": "P-256", "use": ["enc"]} ] :param key_conf: The key configuration :param kid_template: A template by which to build the kids :return: A tuple consisting of a JWKS dictionary, a KeyJar instance and a representation of which kids that can be used for what. Note the JWKS contains private key information !! """ if keyjar is None: keyjar = KeyJar() if kidd is None: kidd = {"sig": {}, "enc": {}} kid = 0 jwks = {"keys": []} for spec in key_conf: typ = spec["type"].upper() if typ == "RSA": if "key" in spec: error_to_catch = (OSError, IOError, DeSerializationNotPossible) try: kb = KeyBundle(source="file://%s" % spec["key"], fileformat="der", keytype=typ, keyusage=spec["use"]) except error_to_catch: kb = _new_rsa_key(spec) except Exception: raise else: kb = rsa_init(spec) elif typ == "EC": kb = ec_init(spec) for k in kb.keys(): if kid_template: k.kid = kid_template % kid kid += 1 else: k.add_kid() kidd[k.use][k.kty] = k.kid jwks["keys"].extend( [k.serialize() for k in kb.keys() if k.kty != 'oct']) keyjar.add_kb("", kb) return jwks, keyjar, kidd
def test_unknown_source(): with pytest.raises(ImportError): kb = KeyBundle(source='foobar')
def test_with_sym_key(): kc = KeyBundle({"kty": "oct", "key": "supersecret", "use": "sig"}) assert len(kc.get("oct")) == 1 assert len(kc.get("rsa")) == 0 assert kc.remote is False assert kc.source is None
def test_no_use(self): kb = KeyBundle(JWK0["keys"]) kj = KeyJar() kj.issuer_keys["abcdefgh"] = [kb] enc_key = kj.get_encrypt_key("RSA", "abcdefgh") assert enc_key != []