Example #1
0
    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()
Example #2
0
    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()
Example #3
0
    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()
Example #4
0
 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))
Example #5
0
    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
Example #6
0
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
Example #7
0
    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
Example #8
0
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
Example #9
0
 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))
Example #10
0
    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)
Example #11
0
    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
Example #12
0
    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
Example #13
0
    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
Example #14
0
    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
Example #15
0
    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
Example #16
0
    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 {}
Example #17
0
    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")
Example #18
0
    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 {}
Example #19
0
    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
Example #20
0
    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
Example #21
0
 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))
Example #22
0
    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
Example #23
0
    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
Example #24
0
    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()
Example #25
0
    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()
Example #26
0
    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()
Example #27
0
    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 {}
Example #28
0
# 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))
Example #29
0
 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
Example #30
0
    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
Example #31
0
 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])]
Example #32
0
def jwt_header(txt):
    return json.loads(b64d(str(txt.split(".")[0])))
Example #33
0
 def deserialize(self):
     self.key = b64d(bytes(self.k))
Example #34
0
 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
Example #35
0
 def comp(self):
     self.key = b64d(str(self.k))
Example #36
0
def test_b64_encode_decode():
    data = "abcd".encode("utf-8")
    assert b64d(b64e(data)) == data
Example #37
0
def test_b64d_with_padded_data():
    data = "abcd".encode("utf-8")
    encoded = base64.urlsafe_b64encode(data)
    assert b64d(encoded) == data
Example #38
0
 def deserialize(self):
     self.key = b64d(str(self.k))
Example #39
0
    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)
Example #40
0
 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])]
Example #41
0
 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 jwt_header(txt):
    return json.loads(b64d(str(txt.split(".")[0])))
Example #44
0
    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
Example #45
0
#!/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)
Example #46
0
 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))
Example #47
0
 def deserialize(self):
     self.key = b64d(str(self.k))
Example #48
0
 def deserialize(self):
     self.key = b64d(bytes(self.k))
Example #49
0
File: jws.py Project: lxp20201/lxp
 def _decode(self, payload):
     _msg = b64d(bytes(payload))
     if "cty" in self:
         if self["cty"] == "JWT":
             _msg = json.loads(_msg)
     return _msg
Example #50
0
 def deserialize(self):
     if self.k:
         self.key = b64d(bytes(self.k))
     else:
         raise DeSerializationNotPossible()