def verify_compact(self, jws, keys=None): _header, _payload, _sig = jws.split(".") self.parse_header(_header) if "alg" in self: if self["alg"] == "none": self.msg = self._decode(_payload) return self.msg if keys: _keys = self._pick_keys(keys) else: _keys = self._pick_keys(self._get_keys()) verifier = SIGNER_ALGS[self["alg"]] for key in _keys: try: verifier.verify(_header + '.' + _payload, b64d(str(_sig)), key.get_key(private=False)) except BadSignature: pass else: self.msg = self._decode(_payload) return self.msg raise BadSignature()
def verify_compact(self, jws, keys=None): _header, _payload, _sig = jws.split(".") self.parse_header(_header) if "alg" in self: if self["alg"] == "none": self.msg = self._decode(_payload) return self.msg _alg = self["alg"] if keys: _keys = self._pick_keys(keys) else: _keys = self._pick_keys(self._get_keys()) verifier = SIGNER_ALGS[self["alg"]] for key in _keys: try: verifier.verify(_header + '.' + _payload, b64d(str(_sig)), key.get_key(alg=_alg, private=False)) except BadSignature: pass else: logger.debug( "Verified message using key with kid=%s" % key.kid) self.msg = self._decode(_payload) return self.msg raise BadSignature()
def verify_compact(self, jws, keys=None): _header, _payload, _sig = jws.split(".") self.parse_header(_header) if "alg" in self: if self["alg"] == "none": self.msg = self._decode(_payload) return self.msg if keys: _keys = self._pick_keys(keys) else: _keys = self._pick_keys(self._get_keys()) verifier = SIGNER_ALGS[self["alg"]] for key in _keys: try: verifier.verify(_header + '.' + _payload, b64d(str(_sig)), key.key) except BadSignature: pass else: self.msg = self._decode(_payload) return self.msg raise BadSignature()
def __init__(self, kty="oct", alg="", use="", kid="", key=None, x5c=None, x5t="", x5u="", k="", mtrl="", **kwargs): Key.__init__(self, kty, alg, use, kid, as_bytes(key), x5c, x5t, x5u, **kwargs) self.k = k if not self.key and self.k: if isinstance(self.k, str): self.k = self.k.encode("utf-8") self.key = b64d(bytes(self.k))
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_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 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_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 from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs): """ Given a signed and/or encrypted JWT, verify its correctness and then create a class instance from the content. :param txt: The JWT :param key: keys that might be used to decrypt and/or verify the signature of the JWT :param verify: Whether the signature should be verified or not :return: A class instance """ if key is None and keyjar is not None: key = keyjar.get_verify_key(owner="") elif key is None: key = {} header = json.loads(b64d(str(txt.split(".")[0]))) try: htype = header["typ"] except KeyError: htype = None jso = None if htype == "JWE" or ("alg" in header and "enc" in header): # encrypted if keyjar: dkeys = keyjar.get_decrypt_key(owner="") else: dkeys = {} txt = jwe.decrypt(txt, dkeys, "private") try: jso = json.loads(txt) except Exception: pass # assume htype == 'JWS' if not jso: try: jso = jwkest.unpack(txt)[1] if isinstance(jso, basestring): jso = json.loads(jso) if verify: if keyjar: for ent in ["iss", "aud", "client_id"]: if ent not in jso: continue if ent == "aud": for _e in jso[ent]: self._add_key(keyjar, _e, key) else: self._add_key(keyjar, jso[ent], key) jws.verify(txt, key) except Exception: raise return self.from_dict(jso)
def decrypt(self, token, key): b64_head, b64_jek, b64_iv, b64_ctxt, b64_tag = token.split(b".") self.parse_header(b64_head) iv = b64d(str(b64_iv)) jek = b64d(str(b64_jek)) # The iv for this function must be 64 bit cek = aes_unwrap_key(key, jek) _ctxt = b64d(str(b64_ctxt)) _tag = b64d(str(b64_tag)) auth_data = b64_head msg = self._decrypt(self["enc"], cek, _ctxt, auth_data, iv, _tag) if "zip" in self and self["zip"] == "DEF": msg = zlib.decompress(msg) return msg
def decrypt(self, token, key): """ Decrypts a JWT :param token: The JWT :param key: A key to use for decrypting :return: The decrypted message """ b64_head, b64_jek, b64_iv, b64_ctxt, b64_tag = token.split(b".") self.parse_header(b64_head) iv = b64d(str(b64_iv)) _decrypt = RSAEncrypter().decrypt jek = b64d(str(b64_jek)) _alg = self["alg"] if _alg == "RSA-OAEP": cek = _decrypt(jek, key, 'pkcs1_oaep_padding') elif _alg == "RSA1_5": cek = _decrypt(jek, key) else: raise NotSupportedAlgorithm(_alg) enc = self["enc"] try: assert enc in SUPPORTED["enc"] except AssertionError: raise NotSupportedAlgorithm(enc) auth_data = b64_head _ctxt = b64d(str(b64_ctxt)) _tag = b64d(str(b64_tag)) msg, flag = self._decrypt(enc, cek, _ctxt, auth_data, iv, _tag) if flag is False: raise DecryptionFailed() if "zip" in self and self["zip"] == "DEF": msg = zlib.decompress(msg) return msg
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 _func(self, conv): for instance, msg in conv.protocol_response: if isinstance(instance, message.OpenIDSchema): header = json.loads(b64d(str(msg.split(".")[0]))) try: assert header["alg"].startswith("RSA") except AssertionError: self._status = self.status break return {}
def parse_header(self, encheader): for attr, val in json.loads(b64d(str(encheader))).items(): if attr == "jwk": self["jwk"] = keyrep(val) else: self[attr] = val if "kid" in self: try: assert isinstance(self["kid"], basestring) except AssertionError: raise HeaderError("kid of wrong value type")
def _func(self, conv): for instance, msg in conv.protocol_response: if isinstance(instance, message.AccessTokenResponse): _dic = json.loads(msg) header = json.loads(b64d(str(_dic["id_token"].split(".")[0]))) try: assert header["alg"].startswith("RSA") except AssertionError: self._status = self.status break return {}
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 decrypt(self, token, key=None, cek=None): if not key and not cek: raise MissingKey("On of key or cek must be specified") b64_head, b64_jek, b64_iv, b64_ctxt, b64_tag = token.split(b".") self.parse_header(b64_head) iv = b64d(str(b64_iv)) if not cek: jek = b64d(str(b64_jek)) # The iv for this function must be 64 bit cek = aes_unwrap_key(key, jek) _ctxt = b64d(str(b64_ctxt)) _tag = b64d(str(b64_tag)) auth_data = b64_head msg = self._decrypt(self["enc"], cek, _ctxt, auth_data, iv, _tag) if "zip" in self and self["zip"] == "DEF": msg = zlib.decompress(msg) return msg
def __init__(self, kty="OCT", alg="", use="", kid="", key=None, x5c=None, x5t="", x5u="", k="", mtrl=""): Key.__init__(self, kty, alg, use, kid, key, x5c, x5t, x5u) self.k = k if not self.key and self.k: self.key = b64d(str(self.k))
def unpack(self, token): """ Unpacks a JWT into its parts and base64 decodes the parts individually :param token: The JWT """ if isinstance(token, six.string_types): token = token.encode("utf-8") part = split_token(token) self.b64part = part self.part = [b64d(p) for p in part] self.headers = json.loads(self.part[0].decode()) return self
def deserialize(self): if self.n and self.e: try: for param in self.longs: item = getattr(self, param) if not item or isinstance(item, six.integer_types): continue else: try: val = long(deser(item)) except Exception: raise else: setattr(self, param, val) lst = [self.n, self.e] if self.d: lst.append(self.d) if self.p: lst.append(self.p) if self.q: lst.append(self.q) self.key = RSA.construct(tuple(lst)) else: self.key = RSA.construct(lst) except ValueError as err: raise DeSerializationNotPossible("%s" % err) elif self.x5c: der_cert = base64.b64decode(self.x5c[0].encode("ascii")) if self.x5t: # verify the cert if not b64d(self.x5t.encode("ascii")) == hashlib.sha1( der_cert).digest(): raise DeSerializationNotPossible( "The thumbprint ('x5t') does not match the " "certificate.") self.key = der2rsa(der_cert) self._split() if len(self.x5c) > 1: # verify chain pass else: raise DeSerializationNotPossible()
def verify_compact(self, jws, keys=None): _header, _payload, _sig = jws.split(".") self.parse_header(_header) if "alg" in self: if self["alg"] == "none": self.msg = self._decode(_payload) return self.msg _alg = self["alg"] if keys: _keys = self._pick_keys(keys) else: _keys = self._pick_keys(self._get_keys()) verifier = SIGNER_ALGS[self["alg"]] if not _keys: if "kid" in self: raise NoSuitableSigningKeys( "No key for algorithm: %s with kid: %s" % (_alg, self["kid"])) else: raise NoSuitableSigningKeys("No key for algorithm: %s" % _alg) for key in _keys: try: res = verifier.verify(_header + '.' + _payload, b64d(str(_sig)), key.get_key(alg=_alg, private=False)) except BadSignature: pass else: if res is True: logger.debug("Verified message using key with kid=%s" % key.kid) self.msg = self._decode(_payload) return self.msg raise BadSignature()
def deserialize(self): if self.n and self.e: try: for param in self.longs: item = getattr(self, param) if not item or isinstance(item, six.integer_types): continue else: try: val = long(deser(item)) except Exception: raise else: setattr(self, param, val) lst = [self.n, self.e] if self.d: lst.append(self.d) if self.p: lst.append(self.p) if self.q: lst.append(self.q) self.key = RSA.construct(tuple(lst)) else: self.key = RSA.construct(lst) except ValueError as err: raise DeSerializationNotPossible("%s" % err) elif self.x5c: der_cert = base64.b64decode(self.x5c[0].encode("ascii")) if self.x5t: # verify the cert if not b64d(self.x5t.encode("ascii")) == hashlib.sha1(der_cert).digest(): raise DeSerializationNotPossible("The thumbprint ('x5t') does not match the certificate.") self.key = der2rsa(der_cert) self._split() if len(self.x5c) > 1: # verify chain pass else: raise DeSerializationNotPossible()
def _func(self, conv): client = conv.client for instance, msg in conv.protocol_response: if isinstance(instance, message.AccessTokenResponse): _dic = json.loads(msg) header = json.loads(b64d(str(_dic["id_token"].split(".")[0]))) try: assert header["alg"].startswith("RSA") except AssertionError: self._status = self.status break dkeys = client.keyjar.get_decrypt_key(owner="") txt = JWE_RSA().decrypt(_dic["id_token"], dkeys[0].key) _tmp = unpack(txt)[0] try: assert _tmp["alg"] == "RS256" except AssertionError: self._status = self.status break return {}
# 2 txt = json.dumps(claims_set) msg = b64e(txt) # 3 header = {"alg": "none"} htxt = json.dumps(header) hdr = b64e(htxt) # (4,5),6 jws = ".".join([hdr, msg, ""]) print("JWT={}".format(jws)) # ============================================================================ # Higher level from jwkest import b64d from jwkest.jws import JWS # JWS is A class that can be used for signing and verifying signatures jws = JWS({"foo": "bar"}, alg="none").sign_compact() print("JWT={}".format(jws)) print("") # decode and print the different parts. No verification is done. for p in jws.split("."): p = p.encode("utf8") print(b64d(p))
def parse_header(self, encheader): for attr, val in json.loads(b64d(str(encheader))).items(): if attr == "jwk": self["jwk"] = keyrep(val) else: self[attr] = val
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
def __init__(self, **headers): if not headers.get("alg"): headers["alg"] = None self.headers = headers self.b64part = [b64encode_item(headers)] self.part = [b64d(self.b64part[0])]
def jwt_header(txt): return json.loads(b64d(str(txt.split(".")[0])))
def deserialize(self): self.key = b64d(bytes(self.k))
def comp(self): self.key = b64d(str(self.k))
def test_b64_encode_decode(): data = "abcd".encode("utf-8") assert b64d(b64e(data)) == data
def test_b64d_with_padded_data(): data = "abcd".encode("utf-8") encoded = base64.urlsafe_b64encode(data) assert b64d(encoded) == data
def deserialize(self): self.key = b64d(str(self.k))
def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs): """ Given a signed and/or encrypted JWT, verify its correctness and then create a class instance from the content. :param txt: The JWT :param key: keys that might be used to decrypt and/or verify the signature of the JWT :param verify: Whether the signature should be verified or not :return: A class instance """ if key is None and keyjar is not None: key = keyjar.get_verify_key(owner="") elif key is None: key = {} header = json.loads(b64d(str(txt.split(".")[0]))) logger.debug("header: %s" % (header,)) try: htype = header["typ"] except KeyError: htype = None try: _kid = header["kid"] except KeyError: _kid = "" jso = None if htype == "JWE" or ("alg" in header and "enc" in header): # encrypted if keyjar: dkeys = keyjar.get_decrypt_key(owner="") else: dkeys = {} txt = JWE().decrypt(txt, dkeys, "private") try: jso = json.loads(txt) except Exception: pass # assume htype == 'JWS' _jws = JWS() if not jso: try: jso = jwkest.unpack(txt)[1] if isinstance(jso, basestring): jso = json.loads(jso) if "jku" in header: if not keyjar.find(header["jku"], jso["iss"]): # This is really questionable try: if kwargs["trusting"]: keyjar.add(jso["iss"], header["jku"]) except KeyError: pass if _kid: _key = keyjar.get_key_by_kid(_kid, jso["iss"]) if _key: key.append(_key) try: self._add_key(keyjar, kwargs["opponent_id"], key) except KeyError: pass if verify: if keyjar: for ent in ["iss", "aud", "client_id"]: if ent not in jso: continue if ent == "aud": # list or basestring if isinstance(jso["aud"], basestring): _aud = [jso["aud"]] else: _aud = jso["aud"] for _e in _aud: self._add_key(keyjar, _e, key) else: self._add_key(keyjar, jso[ent], key) _jws.verify_compact(txt, key) except Exception: raise return self.from_dict(jso)
def _decode(self, payload): _msg = b64d(bytes(payload)) if "cty" in self: if self["cty"] == "JWT": _msg = json.loads(_msg) return _msg
def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs): """ Given a signed and/or encrypted JWT, verify its correctness and then create a class instance from the content. :param txt: The JWT :param key: keys that might be used to decrypt and/or verify the signature of the JWT :param verify: Whether the signature should be verified or not :return: A class instance """ if key is None and keyjar is not None: key = keyjar.get_verify_key(owner="") elif key is None: key = {} header = json.loads(b64d(str(txt.split(".")[0]))) logger.debug("header: %s" % (header, )) try: htype = header["typ"] except KeyError: htype = None try: _kid = header["kid"] except KeyError: _kid = "" jso = None if htype == "JWE" or ("alg" in header and "enc" in header): # encrypted if keyjar: dkeys = keyjar.get_decrypt_key(owner="") else: dkeys = {} txt = JWE().decrypt(txt, dkeys) try: jso = json.loads(txt) except Exception: pass # assume htype == 'JWS' _jws = JWS() if not jso: try: jso = jwkest.unpack(txt)[1] if isinstance(jso, basestring): jso = json.loads(jso) if keyjar: if "jku" in header: if not keyjar.find(header["jku"], jso["iss"]): # This is really questionable try: if kwargs["trusting"]: keyjar.add(jso["iss"], header["jku"]) except KeyError: pass if _kid: try: _key = keyjar.get_key_by_kid(_kid, jso["iss"]) if _key: key.append(_key) except KeyError: pass try: self._add_key(keyjar, kwargs["opponent_id"], key) except KeyError: pass if verify: if keyjar: for ent in ["iss", "aud", "client_id"]: if ent not in jso: continue if ent == "aud": # list or basestring if isinstance(jso["aud"], basestring): _aud = [jso["aud"]] else: _aud = jso["aud"] for _e in _aud: self._add_key(keyjar, _e, key) else: self._add_key(keyjar, jso[ent], key) if "alg" in header and header["alg"] != "none": if not key: raise MissingSigningKey("alg=%s" % header["alg"]) _jws.verify_compact(txt, key) except Exception: raise return self.from_dict(jso)
def decrypt(self, token, key, context, debug=False): """ Does decryption according to the JWE proposal draft-ietf-jose-json-web-encryption-06 :param token: The :param key: :return: """ b64_head, b64_jek, b64_iv, b64_ctxt, b64_tag = token.split(b".") self.parse_header(b64_head) iv = b64d(str(b64_iv)) if context == "private": _decrypt = RSAEncrypter().private_decrypt else: _decrypt = RSAEncrypter().public_decrypt jek = b64d(str(b64_jek)) if debug: print >>sys.stderr, "enc_key", hd2ia(hexlify(jek)) _alg = self["alg"] if _alg == "RSA-OAEP": cek = _decrypt(jek, key, "pkcs1_oaep_padding") elif _alg == "RSA1_5": cek = _decrypt(jek, key) else: raise NotSupportedAlgorithm(_alg) enc = self["enc"] try: assert enc in SUPPORTED["enc"] except AssertionError: raise NotSupportedAlgorithm(enc) auth_data = b64_head _ctxt = b64d(str(b64_ctxt)) _tag = b64d(str(b64_tag)) if enc == "A256GCM": msg = gcm_decrypt(cek, iv, _ctxt, auth_data, _tag) elif enc.startswith("A128CBC-") or enc.startswith("A256CBC-"): enc, hashf = enc.split("-") mac_key = cek[:16] enc_key = cek[16:] c = M2Crypto.EVP.Cipher(alg=ENC2ALG[enc], key=enc_key, iv=iv, op=DEC) msg = aes_dec(c, _ctxt) al = int2bigendian(len(auth_data) * 8) while len(al) < 8: al.insert(0, 0) _inp = str(auth_data) + iv + _ctxt + intarr2str(al) verifier = SIGNER_ALGS[hashf] # Can't use the verify function directly since the tag I have only # are the first 128 bits of the signature if not safe_str_cmp(verifier.sign(_inp, mac_key)[:16], _tag): raise BadSignature() else: raise MethodNotSupported(enc) if "zip" in self and self["zip"] == "DEF": msg = zlib.decompress(msg) return msg
#!/usr/bin/env python from jwkest import b64d from jwkest.jws import JWS # A specific JWT is a sequence of URL-safe parts separated by a period '.' character. # All JWT parts are always base64 encoded. A JWT can have different claims (similar to attributes in LDAP world): # - iss (Issuer) who issued the token # - sub (Subject) who is described by the token # - aud (Audience) who the token intended for # - exp (Expiration Time) # - nbf (Not Before) # - iat (Issued At) # - jti (JWT Id) # # An unsecured JWT is the simplest JWT possible. It can be created as follow: # - create a JOSE header (the simplest possible has only the "alg" specification set to "none") # - create a claims set (which means create a JSON object) # - base64 encode the claims set (message and header) and encode them in UTF-8 # - create the JWS by joining the claims set with the period '.' character as a separator # # Using the jwkest library the JWT can be created as follow. jwt = JWS({"foo": "bar"}, alg="none").sign_compact() print "jwt:", jwt print for p in jwt.split('.'): p = p.encode("utf8") print "-", type(p), b64d(p)
def deserialize(self): if self.k: self.key = b64d(bytes(self.k)) else: raise DeSerializationNotPossible()