Пример #1
0
 def test_4_8_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     S = jws.JWS(payload=plaintext)
     # 4_8_2
     protected = \
         base64url_decode(JWS_Protected_Header_4_8_2).decode('utf-8')
     header = json_encode(JWS_Unprotected_Header_4_8_2)
     pri_key = jwk.JWK(**RSA_Private_Key_3_4)
     S.add_signature(pri_key, None, protected, header)
     # 4_8_3
     header = json_encode(JWS_Unprotected_Header_4_8_3)
     pri_key = jwk.JWK(**EC_Private_Key_3_2)
     S.add_signature(pri_key, None, None, header)
     # 4_8_4
     protected = \
         base64url_decode(JWS_Protected_Header_4_8_4).decode('utf-8')
     sym_key = jwk.JWK(**Symmetric_Key_MAC_3_5)
     S.add_signature(sym_key, None, protected)
     sig = S.serialize()
     # Can't compare signature with reference because ECDSA uses
     # random nonces every time a signature is generated.
     rsa_key = jwk.JWK(**RSA_Public_Key_3_3)
     ec_key = jwk.JWK(**EC_Public_Key_3_1)
     S.deserialize(sig, rsa_key)
     S.deserialize(sig, ec_key)
     S.deserialize(sig, sym_key)
     # Just deserialize each example form
     S.deserialize(json_encode(JWS_general_4_8_5), rsa_key)
     S.deserialize(json_encode(JWS_general_4_8_5), ec_key)
     S.deserialize(json_encode(JWS_general_4_8_5), sym_key)
Пример #2
0
def derive_key(privkey, point_x, point_y, alg, bitsize, headers):
    # OtherInfo is defined in NIST SP 56A 5.8.1.2.1

    # AlgorithmID
    otherinfo = struct.pack('>I', len(alg))
    otherinfo += bytes(alg.encode('utf8'))

    # PartyUInfo
    apu = base64url_decode(headers['apu']) if 'apu' in headers else b''
    otherinfo += struct.pack('>I', len(apu))
    otherinfo += apu

    # PartyVInfo
    apv = base64url_decode(headers['apv']) if 'apv' in headers else b''
    otherinfo += struct.pack('>I', len(apv))
    otherinfo += apv

    # SuppPubInfo
    otherinfo += struct.pack('>I', bitsize)

    # no SuppPrivInfo

    # Shared Key generation

    x, y = point_x, point_y
    P = vulnecc.AffinePoint(vulnecc.curveP256_vuln, x, y)
    s = privkey
    shared = s * P
    shared_key = int.to_bytes(shared.x, 32, "big")

    ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                         length=bitsize // 8,
                         otherinfo=otherinfo,
                         backend=default_backend())
    return ckdf.derive(shared_key)
Пример #3
0
 def test_4_8_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     S = jws.JWS(payload=plaintext)
     # 4_8_2
     protected = \
         base64url_decode(JWS_Protected_Header_4_8_2).decode('utf-8')
     header = json_encode(JWS_Unprotected_Header_4_8_2)
     pri_key = jwk.JWK(**RSA_Private_Key_3_4)
     S.add_signature(pri_key, None, protected, header)
     # 4_8_3
     header = json_encode(JWS_Unprotected_Header_4_8_3)
     pri_key = jwk.JWK(**EC_Private_Key_3_2)
     S.add_signature(pri_key, None, None, header)
     # 4_8_4
     protected = \
         base64url_decode(JWS_Protected_Header_4_8_4).decode('utf-8')
     sym_key = jwk.JWK(**Symmetric_Key_MAC_3_5)
     S.add_signature(sym_key, None, protected)
     sig = S.serialize()
     # Can't compare signature with reference because ECDSA uses
     # random nonces every time a signature is generated.
     rsa_key = jwk.JWK(**RSA_Public_Key_3_3)
     ec_key = jwk.JWK(**EC_Public_Key_3_1)
     S.deserialize(sig, rsa_key)
     S.deserialize(sig, ec_key)
     S.deserialize(sig, sym_key)
     # Just deserialize each example form
     S.deserialize(json_encode(JWS_general_4_8_5), rsa_key)
     S.deserialize(json_encode(JWS_general_4_8_5), ec_key)
     S.deserialize(json_encode(JWS_general_4_8_5), sym_key)
Пример #4
0
    def _derive(self, privkey, pubkey, alg, bitsize, headers):
        # OtherInfo is defined in NIST SP 56A 5.8.1.2.1

        # AlgorithmID
        otherinfo = struct.pack('>I', len(alg))
        otherinfo += bytes(alg.encode('utf8'))

        # PartyUInfo
        apu = base64url_decode(headers['apu']) if 'apu' in headers else b''
        otherinfo += struct.pack('>I', len(apu))
        otherinfo += apu

        # PartyVInfo
        apv = base64url_decode(headers['apv']) if 'apv' in headers else b''
        otherinfo += struct.pack('>I', len(apv))
        otherinfo += apv

        # SuppPubInfo
        otherinfo += struct.pack('>I', bitsize)

        # no SuppPrivInfo

        # Shared Key generation
        if isinstance(privkey, ec.EllipticCurvePrivateKey):
            shared_key = privkey.exchange(ec.ECDH(), pubkey)
        else:
            # X25519/X448
            shared_key = privkey.exchange(pubkey)

        ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                             length=_inbytes(bitsize),
                             otherinfo=otherinfo,
                             backend=self.backend)
        return ckdf.derive(shared_key)
Пример #5
0
    def readable_jwt(txt):
        """
        Convert a JWT token in base64url into a readable dictionary object
        with decoded payload and header for printing and logging
        """
        lst = txt.split('.')
        readable = {
            'protected': json_decode(base64url_decode(lst[0])),
            'payload': json_decode(base64url_decode(lst[1])),
            'signature': lst[2]
        }

        # create readable timestamps for exp/iat claims
        payload = readable["payload"]
        if "iat" in payload:
            t = payload["iat"]
            if isinstance(t, int):
                t = datetime.fromtimestamp(t).isoformat(' ')
                payload["iat"] = t
        if "exp" in payload:
            t = payload["exp"]
            if isinstance(t, int):
                t = datetime.fromtimestamp(t).isoformat(' ')
                payload["exp"] = t

        print(json.dumps(readable, indent=4, sort_keys=False))
        return readable
Пример #6
0
    def _derive(self, privkey, pubkey, alg, keydatalen, headers):
        # OtherInfo is defined in NIST SP 56A 5.8.1.2.1

        # AlgorithmID
        otherinfo = struct.pack('>I', len(alg))
        otherinfo += bytes(alg.encode('utf8'))

        # PartyUInfo
        apu = base64url_decode(headers['apu']) if 'apu' in headers else b''
        otherinfo += struct.pack('>I', len(apu))
        otherinfo += apu

        # PartyVInfo
        apv = base64url_decode(headers['apv']) if 'apv' in headers else b''
        otherinfo += struct.pack('>I', len(apv))
        otherinfo += apv

        # SuppPubInfo
        otherinfo += struct.pack('>I', keydatalen)

        # no SuppPrivInfo

        shared_key = privkey.exchange(ec.ECDH(), pubkey)
        ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                             length=keydatalen // 8,
                             otherinfo=otherinfo,
                             backend=self.backend)
        return ckdf.derive(shared_key)
Пример #7
0
    def verify_jws(self, raw_jws: str, did_document: DidDocument or None):
        c = raw_jws.split('.')
        data = {
            'protected':
            json.loads(base64url_decode(str(c[0])).decode('utf-8')),
            'payload': json.loads(base64url_decode(str(c[1])).decode('utf-8')),
            'signature': base64url_decode(str(c[2]))
        }
        key_id = data['protected']['kid']
        issuer = data['payload']['iss']

        if did_document is None:
            _cache_pub_key_of_issuer = self.document.get_public_key(
                key_id=key_id)
            if not _cache_pub_key_of_issuer:
                self.document = self.__get_document(issuer)

        pub_key_of_issuer = self.document.get_public_key(key_id=key_id)
        if not pub_key_of_issuer:
            raise DidNotFoundException(
                error_message=f"Not Found KeyID in did document {issuer}")

        user_pub_key_hex = pub_key_of_issuer.get('publicKeyHex')
        if not user_pub_key_hex:
            return None

        user_pub_key = jwk.JWK.from_pem(
            VerifyingKey.from_string(bytes.fromhex(user_pub_key_hex),
                                     curve=SECP256k1).to_pem())
        return VerifiableSignedJWT.verify(token=raw_jws, key=user_pub_key)
Пример #8
0
 def _deserialize_signature(self, s):
     o = dict()
     o['signature'] = base64url_decode(str(s['signature']))
     if 'protected' in s:
         p = base64url_decode(str(s['protected']))
         o['protected'] = p.decode('utf-8')
     if 'header' in s:
         o['header'] = s['header']
     return o
Пример #9
0
    def deserialize(self, raw_jws, key=None, alg=None):
        """Deserialize a JWS token.

        NOTE: Destroys any current status and tries to import the raw
        JWS provided.

        :param raw_jws: a 'raw' JWS token (JSON Encoded or Compact
         notation) string.
        :param key: A (:class:`jwcrypto.jwk.JWK`) verification key (optional).
         If a key is provided a verification step will be attempted after
         the object is successfully deserialized.
        :param alg: The signing algorithm (optional). usually the algorithm
         is known as it is provided with the JOSE Headers of the token.

        :raises InvalidJWSObject: if the raw object is an invaid JWS token.
        :raises InvalidJWSSignature: if the verification fails.
        """
        self.objects = dict()
        o = dict()
        try:
            try:
                djws = json_decode(raw_jws)
                if 'signatures' in djws:
                    o['signatures'] = list()
                    for s in djws['signatures']:
                        os = self._deserialize_signature(s)
                        o['signatures'].append(os)
                        self._deserialize_b64(o, os.get('protected'))
                else:
                    o = self._deserialize_signature(djws)
                    self._deserialize_b64(o, o.get('protected'))

                if 'payload' in djws:
                    if o.get('b64', True):
                        o['payload'] = base64url_decode(str(djws['payload']))
                    else:
                        o['payload'] = djws['payload']

            except ValueError:
                c = raw_jws.split('.')
                if len(c) != 3:
                    raise InvalidJWSObject('Unrecognized representation')
                p = base64url_decode(str(c[0]))
                if len(p) > 0:
                    o['protected'] = p.decode('utf-8')
                    self._deserialize_b64(o, o['protected'])
                o['payload'] = base64url_decode(str(c[1]))
                o['signature'] = base64url_decode(str(c[2]))

            self.objects = o

        except Exception as e:  # pylint: disable=broad-except
            raise InvalidJWSObject('Invalid format', repr(e))

        if key:
            self.verify(key, alg)
Пример #10
0
 def test_4_1_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     protected = \
         base64url_decode(JWS_Protected_Header_4_1_2).decode('utf-8')
     pub_key = jwk.JWK(**RSA_Public_Key_3_3)
     pri_key = jwk.JWK(**RSA_Private_Key_3_4)
     S = jws.JWS(payload=plaintext)
     S.add_signature(pri_key, None, protected)
     self.assertEqual(JWS_compact_4_1_3, S.serialize(compact=True))
     S.deserialize(json_encode(JWS_general_4_1_3), pub_key)
     S.deserialize(json_encode(JWS_flattened_4_1_3), pub_key)
Пример #11
0
 def test_4_1_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     protected = \
         base64url_decode(JWS_Protected_Header_4_1_2).decode('utf-8')
     pub_key = jwk.JWK(**RSA_Public_Key_3_3)
     pri_key = jwk.JWK(**RSA_Private_Key_3_4)
     S = jws.JWS(payload=plaintext)
     S.add_signature(pri_key, None, protected)
     self.assertEqual(JWS_compact_4_1_3, S.serialize(compact=True))
     S.deserialize(json_encode(JWS_general_4_1_3), pub_key)
     S.deserialize(json_encode(JWS_flattened_4_1_3), pub_key)
Пример #12
0
 def test_4_6_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     protected = \
         base64url_decode(JWS_Protected_Header_4_6_2).decode('utf-8')
     header = json_encode(JWS_Unprotected_Header_4_6_2)
     key = jwk.JWK(**Symmetric_Key_MAC_3_5)
     S = jws.JWS(payload=plaintext)
     S.add_signature(key, None, protected, header)
     sig = S.serialize()
     S.deserialize(sig, key)
     self.assertEqual(json_decode(sig), JWS_flattened_4_6_3)
     # Just deserialize each example form
     S.deserialize(json_encode(JWS_general_4_6_3), key)
     S.deserialize(json_encode(JWS_flattened_4_6_3), key)
Пример #13
0
 def test_5_10_encryption(self):
     plaintext = Payload_plaintext_5
     protected = base64url_decode(JWE_Protected_Header_5_10_4)
     aad = base64url_decode(AAD_5_10_1)
     aes_key = jwk.JWK(**AES_key_5_8_1)
     E = jwe.JWE(plaintext, protected, aad=aad)
     E.add_recipient(aes_key)
     e = E.serialize()
     E.deserialize(e, aes_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(json_encode(JWE_general_5_10_5), aes_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(json_encode(JWE_flattened_5_10_5), aes_key)
     self.assertEqual(E.payload, plaintext)
Пример #14
0
 def test_5_10_encryption(self):
     plaintext = Payload_plaintext_5
     protected = base64url_decode(JWE_Protected_Header_5_10_4)
     aad = base64url_decode(AAD_5_10_1)
     aes_key = jwk.JWK(**AES_key_5_8_1)
     E = jwe.JWE(plaintext, protected, aad=aad)
     E.add_recipient(aes_key)
     e = E.serialize()
     E.deserialize(e, aes_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(json_encode(JWE_general_5_10_5), aes_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(json_encode(JWE_flattened_5_10_5), aes_key)
     self.assertEqual(E.payload, plaintext)
Пример #15
0
 def test_4_6_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     protected = \
         base64url_decode(JWS_Protected_Header_4_6_2).decode('utf-8')
     header = json_encode(JWS_Unprotected_Header_4_6_2)
     key = jwk.JWK(**Symmetric_Key_MAC_3_5)
     S = jws.JWS(payload=plaintext)
     S.add_signature(key, None, protected, header)
     sig = S.serialize()
     S.deserialize(sig, key)
     self.assertEqual(json_decode(sig), JWS_flattened_4_6_3)
     # Just deserialize each example form
     S.deserialize(json_encode(JWS_general_4_6_3), key)
     S.deserialize(json_encode(JWS_flattened_4_6_3), key)
Пример #16
0
    def deserialize(self, raw_jws, key=None, alg=None):
        """Deserialize a JWS token.

        NOTE: Destroys any current status and tries to import the raw
        JWS provided.

        :param raw_jws: a 'raw' JWS token (JSON Encoded or Compact
         notation) string.
        :param key: A (:class:`jwcrypto.jwk.JWK`) verification key (optional).
         If a key is provided a verification step will be attempted after
         the object is successfully deserialized.
        :param alg: The signing algorithm (optional). usually the algorithm
         is known as it is provided with the JOSE Headers of the token.

        :raises InvalidJWSObject: if the raw object is an invaid JWS token.
        :raises InvalidJWSSignature: if the verification fails.
        """
        self.objects = dict()
        o = dict()
        try:
            try:
                djws = json_decode(raw_jws)
                o['payload'] = base64url_decode(str(djws['payload']))
                if 'signatures' in djws:
                    o['signatures'] = list()
                    for s in djws['signatures']:
                        os = dict()
                        os['signature'] = base64url_decode(str(s['signature']))
                        if 'protected' in s:
                            p = base64url_decode(str(s['protected']))
                            os['protected'] = p.decode('utf-8')
                        if 'header' in s:
                            os['header'] = s['header']
                        o['signatures'].append(os)
                else:
                    o['signature'] = base64url_decode(str(djws['signature']))
                    if 'protected' in djws:
                        p = base64url_decode(str(djws['protected']))
                        o['protected'] = p.decode('utf-8')
                    if 'header' in djws:
                        o['header'] = djws['header']

            except ValueError:
                c = raw_jws.split('.')
                if len(c) != 3:
                    raise InvalidJWSObject('Unrecognized representation')
                p = base64url_decode(str(c[0]))
                if len(p) > 0:
                    o['protected'] = p.decode('utf-8')
                o['payload'] = base64url_decode(str(c[1]))
                o['signature'] = base64url_decode(str(c[2]))

            self.objects = o

        except Exception as e:  # pylint: disable=broad-except
            raise InvalidJWSObject('Invalid format', repr(e))

        if key:
            self.verify(key, alg)
Пример #17
0
 def _get_public_key(self, arg=None):
     if self._params['kty'] == 'oct':
         return self._key['k']
     elif self._params['kty'] == 'RSA':
         return self._rsa_pub(self._key).public_key(default_backend())
     elif self._params['kty'] == 'EC':
         try:
             return self._ec_pub(self._key, arg).public_key(default_backend())
         except ValueError:
             # invalid point
             from jwcrypto.jwa import _decode_int
             return _decode_int(base64url_decode(self._key['x'])), _decode_int(base64url_decode(self._key['y']))
     elif self._params['kty'] == 'OKP':
         return self._okp_pub(self._key)
     else:
         raise NotImplementedError
Пример #18
0
 def get_key(self, key, op):
     if key.key_type != 'oct':
         raise InvalidJWEKeyType('oct', key.key_type)
     rk = base64url_decode(key.get_op_key(op))
     if len(rk) != self.keysize:
         raise InvalidJWEKeyLength(self.keysize * 8, len(rk) * 8)
     return rk
Пример #19
0
    def _okp_pri(self, k):
        try:
            privkey = _OKP_CURVES_TABLE[k['crv']].privkey
        except KeyError:
            raise InvalidJWKValue('Unknown curve "%s"' % k['crv'])

        return privkey.from_private_bytes(base64url_decode(k['d']))
Пример #20
0
 def verify(self, key, payload, signature):
     vkey = base64url_decode(key.get_op_key('verify'))
     h = self._hmac_setup(vkey, payload)
     try:
         h.verify(signature)
     except InvalidSignature as e:
         raise InvalidJWSSignature(exception=e)
    def _load(self):
        logger.debug('finding eq_session_id in database',
                     eq_session_id=self.eq_session_id)

        self._eq_session = data_access.get_by_key(EQSession,
                                                  self.eq_session_id)

        if self._eq_session:
            self.user_id = self._eq_session.user_id

            if self._eq_session.session_data:
                encrypted_session_data = self._eq_session.session_data
                session_data = StorageEncryption(self.user_id, self.user_ik, self.pepper)\
                    .decrypt_data(encrypted_session_data)

                # for backwards compatibility
                # session data used to be base64 encoded before encryption
                try:
                    session_data = base64url_decode(
                        session_data.decode()).decode()
                except ValueError:
                    pass

                self.session_data = json.loads(
                    session_data, object_hook=lambda d: SessionData(**d))

            logger.debug(
                'found matching eq_session for eq_session_id in database',
                session_id=self._eq_session.eq_session_id,
                user_id=self._eq_session.user_id)
        else:
            logger.debug('eq_session_id not found in database',
                         eq_session_id=self.eq_session_id)

        return self._eq_session
Пример #22
0
def process_jwt(jwt):
    """
    Process a JSON Web Token without verifying it.

    Call this before :func:`verify_jwt` if you need access to the header or claims in the token before verifying it. For example, the claims might identify the issuer such that you can retrieve the appropriate public key.

    :param jwt: The JSON Web Token to verify.
    :type jwt: str or unicode

    :rtype: tuple
    :returns: ``(header, claims)``
    """
    header, claims, _ = jwt.split('.')
    parsed_header = json_decode(base64url_decode(header))
    parsed_claims = json_decode(base64url_decode(claims))
    return parsed_header, parsed_claims
    def _load(self) -> None:
        logger.debug("finding eq_session_id in database",
                     eq_session_id=self.eq_session_id)
        self._eq_session: Optional[EQSession] = current_app.eq["storage"].get(
            EQSession, self.eq_session_id)  # type: ignore

        if self._eq_session and self._eq_session.session_data:
            self.user_id = self._eq_session.user_id

            encrypted_session_data = self._eq_session.session_data
            session_data_as_bytes = StorageEncryption(
                self.user_id, self.user_ik,
                self.pepper).decrypt_data(encrypted_session_data)

            session_data_as_str = session_data_as_bytes.decode()
            # for backwards compatibility
            # session data used to be base64 encoded before encryption
            try:
                session_data_as_str = base64url_decode(
                    session_data_as_str).decode()
            except ValueError:
                pass

            self.session_data = json_loads(
                session_data_as_str, object_hook=lambda d: SessionData(**d))

            logger.debug(
                "found matching eq_session for eq_session_id in database",
                session_id=self._eq_session.eq_session_id,
                user_id=self._eq_session.user_id,
            )
        else:
            logger.debug("eq_session_id not found in database",
                         eq_session_id=self.eq_session_id)
Пример #24
0
 def verify(self, key, payload, signature):
     vkey = base64url_decode(key.get_op_key('verify'))
     h = self._hmac_setup(vkey, payload)
     try:
         h.verify(signature)
     except InvalidSignature as e:
         raise InvalidJWSSignature(exception=e)
Пример #25
0
 def jti_size_should_be_as_expected(self, claims):
     """ Check jti size """
     if jti_size and not callable(
             privk
     ):  # don't assume format of externally-generated JTIs
         expect(len(base64url_decode(
             claims['jti']))).to_equal(jti_size)
Пример #26
0
def process_jwt(jwt):
    """
    Process a JSON Web Token without verifying it.

    Call this before :func:`verify_jwt` if you need access to the header or claims in the token before verifying it. For example, the claims might identify the issuer such that you can retrieve the appropriate public key.

    :param jwt: The JSON Web Token to verify.
    :type jwt: str or unicode

    :rtype: tuple
    :returns: ``(header, claims)``
    """
    header, claims, _ = jwt.split('.')
    parsed_header = json_decode(base64url_decode(header))
    parsed_claims = json_decode(base64url_decode(claims))
    return parsed_header, parsed_claims
Пример #27
0
    def _get_key(self, alg, key, p2s, p2c):
        if not isinstance(key, JWK):
            # backwards compatiblity for old interface
            if isinstance(key, bytes):
                plain = key
            else:
                plain = key.encode('utf8')
        else:
            plain = base64url_decode(key.get_op_key())

        salt = bytes(self.name.encode('utf8')) + b'\x00' + p2s

        if self.hashsize == 256:
            hashalg = hashes.SHA256()
        elif self.hashsize == 384:
            hashalg = hashes.SHA384()
        elif self.hashsize == 512:
            hashalg = hashes.SHA512()
        else:
            raise ValueError('Unknown Hash Size')

        kdf = PBKDF2HMAC(algorithm=hashalg, length=_inbytes(self.keysize),
                         salt=salt, iterations=p2c, backend=self.backend)
        rk = kdf.derive(plain)
        if _bitsize(rk) != self.keysize:
            raise InvalidJWEKeyLength(self.keysize, len(rk))
        return JWK(kty="oct", use="enc", k=base64url_encode(rk))
Пример #28
0
 def test_4_3_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     protected = \
         base64url_decode(JWS_Protected_Header_4_3_2).decode('utf-8')
     pub_key = jwk.JWK(**EC_Public_Key_3_1)
     pri_key = jwk.JWK(**EC_Private_Key_3_2)
     S = jws.JWS(payload=plaintext)
     S.add_signature(pri_key, None, protected)
     # Can't compare signature with reference because ECDSA uses
     # random nonces every time a signature is generated.
     sig = S.serialize()
     S.deserialize(sig, pub_key)
     # Just deserialize each example form
     S.deserialize(JWS_compact_4_3_3, pub_key)
     S.deserialize(json_encode(JWS_general_4_3_3), pub_key)
     S.deserialize(json_encode(JWS_flattened_4_3_3), pub_key)
Пример #29
0
 def topic(self):
     """ Generate token """
     token = jwt.generate_jwt(payload, None, 'none', timedelta(seconds=60))
     header, claims, _ = token.split('.')
     parsed_header = json_decode(base64url_decode(header))
     del parsed_header['alg']
     return u"%s.%s." % (base64url_encode(json_encode(parsed_header)), claims)
Пример #30
0
 def test_4_3_signing(self):
     plaintext = base64url_decode(Payload_plaintext_b64_4)
     protected = \
         base64url_decode(JWS_Protected_Header_4_3_2).decode('utf-8')
     pub_key = jwk.JWK(**EC_Public_Key_3_1)
     pri_key = jwk.JWK(**EC_Private_Key_3_2)
     S = jws.JWS(payload=plaintext)
     S.add_signature(pri_key, None, protected)
     # Can't compare signature with reference because ECDSA uses
     # random nonces every time a signature is generated.
     sig = S.serialize()
     S.deserialize(sig, pub_key)
     # Just deserialize each example form
     S.deserialize(JWS_compact_4_3_3, pub_key)
     S.deserialize(json_encode(JWS_general_4_3_3), pub_key)
     S.deserialize(json_encode(JWS_flattened_4_3_3), pub_key)
Пример #31
0
    def _verify(self, prop: str, key: JWK, alg: Optional[AlgorithmName],
                header: JsonObject, signer: Optional[JsonObject],
                patch_header: _PatchHeader) -> None:
        a = self._get_alg(alg, signer or header, InvalidJWSSignature)

        # Prepare payload for verification algorithm
        payload = copy(self._payload)
        h = copy(header)
        s = copy(signer)
        signature = base64url_decode((s or h).pop(_VALUE))
        exclude = h.pop(_EXCLUDES, [])
        for x in exclude:
            payload.pop(x, None)

        h.update(patch_header(s))

        payload[prop] = h
        canonical = _dumpb(payload)

        # Verify signature
        if key is None:
            key = JWK(**((s or h).get(_PUBLICKEY, None)))
        c = JWSCore(a, key, header=None, payload='',
                    algs=self._allowed_algs)
        c.engine.verify(key, canonical, signature)
Пример #32
0
 def unwrap(self, key, keylen, ek, headers):
     self._check_key(key)
     if ek != b'':
         raise InvalidJWEData('Invalid Encryption Key.')
     cek = base64url_decode(key.get_op_key('decrypt'))
     if len(cek) != keylen:
         raise InvalidJWEKeyLength(keylen, len(cek))
     return cek
Пример #33
0
    def unwrap(self, key, bitsize, ek, headers):
        rk = self._get_key(key, 'decrypt')

        if 'iv' not in headers:
            raise ValueError('Invalid Header, missing "iv" parameter')
        iv = base64url_decode(headers['iv'])
        if 'tag' not in headers:
            raise ValueError('Invalid Header, missing "tag" parameter')
        tag = base64url_decode(headers['tag'])

        cipher = Cipher(algorithms.AES(rk), modes.GCM(iv, tag),
                        backend=self.backend)
        decryptor = cipher.decryptor()
        cek = decryptor.update(ek) + decryptor.finalize()
        if _bitsize(cek) != bitsize:
            raise InvalidJWEKeyLength(bitsize, _bitsize(cek))
        return cek
Пример #34
0
 def wrap(self, key, bitsize, cek, headers):
     self._check_key(key)
     if cek:
         return (cek, None)
     k = base64url_decode(key.get_op_key('encrypt'))
     if _bitsize(k) != bitsize:
         raise InvalidCEKeyLength(bitsize, _bitsize(k))
     return {'cek': k}
 def _get_base64_encoded_data(self, data):
     """
     Legacy data was stored in a dict, base64-encoded, and not compressed:
     { 'data': '<base 64 encoded and encrypted data' }
     """
     data = json.loads(data).get('data')
     decrypted_data = self.encrypter.decrypt_data(data)
     return base64url_decode(decrypted_data.decode()).decode()
Пример #36
0
    def unwrap(self, key, keylen, ek, headers):
        rk = self._get_key(key, 'decrypt')

        if 'iv' not in headers:
            raise InvalidJWEData('Invalid Header, missing "iv" parameter')
        iv = base64url_decode(headers['iv'])
        if 'tag' not in headers:
            raise InvalidJWEData('Invalid Header, missing "tag" parameter')
        tag = base64url_decode(headers['tag'])

        cipher = Cipher(algorithms.AES(rk), modes.GCM(iv, tag),
                        backend=self.backend)
        decryptor = cipher.decryptor()
        cek = decryptor.update(ek) + decryptor.finalize()
        if len(cek) != keylen:
            raise InvalidJWEKeyLength(keylen, len(cek))
        return cek
Пример #37
0
 def wrap(self, key, keylen, cek):
     self.check_key(key)
     if cek:
         return (cek, None)
     k = base64url_decode(key.get_op_key('encrypt'))
     if len(k) != keylen:
         raise InvalidCEKeyLength(keylen, len(k))
     return (k, '')
Пример #38
0
 def unwrap(self, key, bitsize, ek, headers):
     self._check_key(key)
     if ek != b'':
         raise ValueError('Invalid Encryption Key.')
     cek = base64url_decode(key.get_op_key('decrypt'))
     if _bitsize(cek) != bitsize:
         raise InvalidJWEKeyLength(bitsize, _bitsize(cek))
     return cek
Пример #39
0
 def topic(self):
     """ Generate token """
     token = jwt.generate_jwt(payload, None, 'none', timedelta(seconds=60))
     header, claims, _ = token.split('.')
     parsed_header = json_decode(base64url_decode(header))
     del parsed_header['alg']
     return u"%s.%s." % (base64url_encode(
         json_encode(parsed_header)), claims)
Пример #40
0
    def _okp_pub(self):
        crv = self._params.get('crv', None)
        try:
            pubkey = _OKP_CURVES_TABLE[crv].pubkey
        except KeyError:
            raise InvalidJWKValue('Unknown curve "%s"' % crv)

        x = base64url_decode(self._params['x'])
        return pubkey.from_public_bytes(x)
Пример #41
0
    def _okp_pri(self):
        crv = self._params.get('crv', None)
        try:
            privkey = _OKP_CURVES_TABLE[crv].privkey
        except KeyError:
            raise InvalidJWKValue('Unknown curve "%s"' % crv)

        d = base64url_decode(self._params['d'])
        return privkey.from_private_bytes(d)
Пример #42
0
 def _get_key(self, key, op):
     if not isinstance(key, JWK):
         raise ValueError('key is not a JWK object')
     if key.key_type != 'oct':
         raise InvalidJWEKeyType('oct', key.key_type)
     rk = base64url_decode(key.get_op_key(op))
     if len(rk) != self.keysize:
         raise InvalidJWEKeyLength(self.keysize * 8, len(rk) * 8)
     return rk
Пример #43
0
 def _get_key(self, key, op):
     if not isinstance(key, JWK):
         raise ValueError('key is not a JWK object')
     if key.key_type != 'oct':
         raise InvalidJWEKeyType('oct', key.key_type)
     rk = base64url_decode(key.get_op_key(op))
     if _bitsize(rk) != self.keysize:
         raise InvalidJWEKeyLength(self.keysize, _bitsize(rk))
     return rk
Пример #44
0
def verify(sjws, pub_pem):
    sjws = json_decode(sjws)
    pub_pem = json_decode(pub_pem.replace('\n', '\\n'))
    if pub_pem.startswith("-----BEGIN"):
        pub_key = JWK.from_pem(to_bytes_2and3(pub_pem))
    else:
        pub_key = JWK(kty='oct', k=base64url_encode(pub_pem))
    sig = JWS()
    sig.deserialize(sjws, pub_key)
    sys.stdout.write(base64url_decode(json_decode(sig.serialize())['payload']))
Пример #45
0
    def unwrap(self, key, keylen, ek, headers):
        if 'p2s' not in headers:
            raise InvalidJWEData('Invalid Header, missing "p2s" parameter')
        if 'p2c' not in headers:
            raise InvalidJWEData('Invalid Header, missing "p2c" parameter')
        p2s = base64url_decode(headers['p2s'])
        p2c = headers['p2c']
        kek = self._get_key(headers['alg'], key, p2s, p2c)

        aeskw = _AesKw(self.keysize * 8)
        return aeskw.unwrap(kek, keylen, ek, headers)
 def f(sjwt, iat_skew=timedelta()):
     """ verify token using node-jsjws """
     r = spawn(
         "fixtures.verify({now}, {sjwt}, {iat_skew}, {key}, {alg})".format(
             now=timegm(datetime.utcnow().utctimetuple()),
             sjwt=json_encode(sjwt),
             iat_skew=iat_skew.total_seconds(),
             key=json_encode(base64url_decode(json_decode(key.export())['k']) if key.is_symmetric else key.export_to_pem()),
             alg=json_encode(alg)),
         True)
     return tuple(r)
 def f(claims, alg, lifetime=None, expires=None, not_before=None):
     """ generate token using node-jsjws """
     now = datetime.utcnow()
     return spawn(
         "fixtures.generate({now}, {header}, {claims}, {expires}, {not_before}, {key})".format(
             now=timegm(now.utctimetuple()),
             header=json_encode({'alg': alg}),
             claims=json_encode(claims),
             expires=timegm(((now + lifetime) if lifetime else expires).utctimetuple()),
             not_before=timegm((not_before or now).utctimetuple()),
             key=json_encode(base64url_decode(json_decode(key.export())['k']) if key.is_symmetric else key.export_to_pem(True, None))),
         False)
Пример #48
0
 def test_5_6_encryption(self):
     plaintext = Payload_plaintext_5
     protected = base64url_decode(JWE_Protected_Header_5_6_3)
     aes_key = jwk.JWK(**AES_key_5_6_1)
     E = jwe.JWE(plaintext, protected)
     E.add_recipient(aes_key)
     _ = E.serialize(compact=True)
     e = E.serialize()
     E.deserialize(e, aes_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(JWE_compact_5_6_4, aes_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(json_encode(JWE_general_5_6_4), aes_key)
     self.assertEqual(E.payload, plaintext)
Пример #49
0
 def test_5_2_encryption(self):
     plaintext = Payload_plaintext_5
     protected = base64url_decode(JWE_Protected_Header_5_2_4)
     rsa_key = jwk.JWK(**RSA_key_5_2_1)
     E = jwe.JWE(plaintext, protected)
     E.add_recipient(rsa_key)
     e = E.serialize()
     E.deserialize(e, rsa_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(JWE_compact_5_2_5, rsa_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(json_encode(JWE_general_5_2_5), rsa_key)
     self.assertEqual(E.payload, plaintext)
     E.deserialize(json_encode(JWE_flattened_5_2_5), rsa_key)
     self.assertEqual(E.payload, plaintext)
Пример #50
0
 def check_sign(self, test):
     s = jws.JWSCore(test['alg'],
                     jwk.JWK(**test['key']),
                     test['protected'],
                     test['payload'],
                     test.get('allowed_algs', None))
     sig = s.sign()
     decsig = base64url_decode(sig['signature'])
     s.verify(decsig)
     # ECDSA signatures are always different every time
     # they are generated unlike RSA or symmetric ones
     if test['key']['kty'] != 'EC':
         self.assertEqual(decsig, test['signature'])
     else:
         # Check we can verify the test signature independently
         # this is so taht we can test the ECDSA agaist a known
         # good signature
         s.verify(test['signature'])
Пример #51
0
    def deserialize(self, raw_jwe, key=None):
        """Deserialize a JWE token.

        NOTE: Destroys any current status and tries to import the raw
        JWE provided.

        :param raw_jwe: a 'raw' JWE token (JSON Encoded or Compact
         notation) string.
        :param key: A (:class:`jwcrypto.jwk.JWK`) decryption key (optional).
         If a key is provided a idecryption step will be attempted after
         the object is successfully deserialized.

        :raises InvalidJWEData: if the raw object is an invaid JWE token.
        :raises InvalidJWEOperation: if the decryption fails.
        """

        self.objects = dict()
        self.plaintext = None
        self.cek = None

        o = dict()
        try:
            try:
                djwe = json_decode(raw_jwe)
                o['iv'] = base64url_decode(str(djwe['iv']))
                o['ciphertext'] = base64url_decode(str(djwe['ciphertext']))
                o['tag'] = base64url_decode(str(djwe['tag']))
                if 'protected' in djwe:
                    p = base64url_decode(str(djwe['protected']))
                    o['protected'] = p.decode('utf-8')
                if 'unprotected' in djwe:
                    o['unprotected'] = json_encode(djwe['unprotected'])
                if 'aad' in djwe:
                    o['aad'] = base64url_decode(str(djwe['aad']))
                if 'recipients' in djwe:
                    o['recipients'] = list()
                    for rec in djwe['recipients']:
                        e = dict()
                        if 'encrypted_key' in rec:
                            e['encrypted_key'] = \
                                base64url_decode(str(rec['encrypted_key']))
                        if 'header' in rec:
                            e['header'] = json_encode(rec['header'])
                        o['recipients'].append(e)
                else:
                    if 'encrypted_key' in djwe:
                        o['encrypted_key'] = \
                            base64url_decode(str(djwe['encrypted_key']))
                    if 'header' in djwe:
                        o['header'] = json_encode(djwe['header'])

            except ValueError:
                c = raw_jwe.split('.')
                if len(c) != 5:
                    raise InvalidJWEData()
                p = base64url_decode(str(c[0]))
                o['protected'] = p.decode('utf-8')
                ekey = base64url_decode(str(c[1]))
                if ekey != '':
                    o['encrypted_key'] = base64url_decode(str(c[1]))
                o['iv'] = base64url_decode(str(c[2]))
                o['ciphertext'] = base64url_decode(str(c[3]))
                o['tag'] = base64url_decode(str(c[4]))

            self.objects = o

        except Exception as e:  # pylint: disable=broad-except
            raise InvalidJWEData('Invalid format', repr(e))

        if key:
            self.decrypt(key)
Пример #52
0
 def unwrap(self, key, ek):
     self.check_key(key)
     if ek != b'':
         raise InvalidJWEData('Invalid Encryption Key.')
     return base64url_decode(key.get_op_key('decrypt'))
Пример #53
0
 def jti_size_should_be_as_expected(self, claims):
     """ Check jti size """
     if jti_size and not callable(privk): # don't assume format of externally-generated JTIs
         expect(len(base64url_decode(claims['jti']))).to_equal(jti_size)
Пример #54
0
def verify_jwt(jwt,
               pub_key=None,
               allowed_algs=None,
               iat_skew=timedelta(),
               checks_optional=False,
               ignore_not_implemented=False):
    """
    Verify a JSON Web Token.

    :param jwt: The JSON Web Token to verify.
    :type jwt: str or unicode

    :param pub_key: The public key to be used to verify the token. Note: if you pass ``None`` and **allowed_algs** contains ``none`` then the token's signature will not be verified.
    :type pub_key: `jwcrypto.jwk.JWK <https://jwcrypto.readthedocs.io/en/latest/jwk.html>`_

    :param allowed_algs: Algorithms expected to be used to sign the token. The ``in`` operator is used to test membership.
    :type allowed_algs: list or NoneType (meaning an empty list)

    :param iat_skew: The amount of leeway to allow between the issuer's clock and the verifier's clock when verifiying that the token was generated in the past. Defaults to no leeway.
    :type iat_skew: datetime.timedelta

    :param checks_optional: If ``False``, then the token must contain the **typ** header property and the **iat**, **nbf** and **exp** claim properties.
    :type checks_optional: bool

    :param ignore_not_implemented: If ``False``, then the token must *not* contain the **jku**, **jwk**, **x5u**, **x5c** or **x5t** header properties.
    :type ignore_not_implemented: bool

    :rtype: tuple
    :returns: ``(header, claims)`` if the token was verified successfully. The token must pass the following tests:

    - Its header must contain a property **alg** with a value in **allowed_algs**.
    - Its signature must verify using **pub_key** (unless its algorithm is ``none`` and ``none`` is in **allowed_algs**).
    - If the corresponding property is present or **checks_optional** is ``False``:

      - Its header must contain a property **typ** with the value ``JWT``.
      - Its claims must contain a property **iat** which represents a date in the past (taking into account :obj:`iat_skew`).
      - Its claims must contain a property **nbf** which represents a date in the past.
      - Its claims must contain a property **exp** which represents a date in the future.

    :raises: If the token failed to verify.
    """
    if allowed_algs is None:
        allowed_algs = []

    if not isinstance(allowed_algs, list):
        # jwcrypto only supports list of allowed algorithms
        raise _JWTError('allowed_algs must be a list')

    header, claims, _ = jwt.split('.')

    parsed_header = json_decode(base64url_decode(header))

    alg = parsed_header.get('alg')
    if alg is None:
        raise _JWTError('alg header not present')
    if alg not in allowed_algs:
        raise _JWTError('algorithm not allowed: ' + alg)

    if not ignore_not_implemented:
        for k in parsed_header:
            if k not in JWSHeaderRegistry:
                raise _JWTError('unknown header: ' + k)
            if not JWSHeaderRegistry[k].supported:
                raise _JWTError('header not implemented: ' + k)

    if pub_key:
        token = JWS()
        token.allowed_algs = allowed_algs
        token.deserialize(jwt, pub_key)
    elif 'none' not in allowed_algs:
        raise _JWTError('no key but none alg not allowed')

    parsed_claims = json_decode(base64url_decode(claims))

    utcnow = datetime.utcnow()
    now = timegm(utcnow.utctimetuple())

    typ = parsed_header.get('typ')
    if typ is None:
        if not checks_optional:
            raise _JWTError('typ header not present')
    elif typ != 'JWT':
        raise _JWTError('typ header is not JWT')

    iat = parsed_claims.get('iat')
    if iat is None:
        if not checks_optional:
            raise _JWTError('iat claim not present')
    elif iat > timegm((utcnow + iat_skew).utctimetuple()):
        raise _JWTError('issued in the future')

    nbf = parsed_claims.get('nbf')
    if nbf is None:
        if not checks_optional:
            raise _JWTError('nbf claim not present')
    elif nbf > now:
        raise _JWTError('not yet valid')

    exp = parsed_claims.get('exp')
    if exp is None:
        if not checks_optional:
            raise _JWTError('exp claim not present')
    elif exp <= now:
        raise _JWTError('expired')

    return parsed_header, parsed_claims
Пример #55
0
 def _decode_int(self, n):
     return int(hexlify(base64url_decode(n)), 16)
Пример #56
0
 def sign(self, key, payload):
     skey = base64url_decode(key.get_op_key('sign'))
     h = self._hmac_setup(skey, payload)
     return h.finalize()
Пример #57
0
    def add_signature(self, key, alg=None, protected=None, header=None):
        """Adds a new signature to the object.

        :param key: A (:class:`jwcrypto.jwk.JWK`) key of appropriate for
         the "alg" provided.
        :param alg: An optional algorithm name. If already provided as an
         element of the protected or unprotected header it can be safely
         omitted.
        :param potected: The Protected Header (optional)
        :param header: The Unprotected Header (optional)

        :raises InvalidJWSObject: if no payload has been set on the object.
        :raises ValueError: if the key is not a :class:`JWK` object.
        :raises ValueError: if the algorithm is missing or is not provided
         by one of the headers.
        :raises InvalidJWAAlgorithm: if the algorithm is not valid, is
         unknown or otherwise not yet implemented.
        """

        if not self.objects.get('payload', None):
            raise InvalidJWSObject('Missing Payload')

        p = dict()
        if protected:
            p = json_decode(protected)
            # TODO: allow caller to specify list of headers it understands
            if 'crit' in p:
                self._check_crit(p['crit'])

        if header:
            h = json_decode(header)
            p = self._merge_headers(p, h)

        if 'alg' in p:
            if alg is None:
                alg = p['alg']
            elif alg != p['alg']:
                raise ValueError('"alg" value mismatch, specified "alg" '
                                 'does not match JOSE header value')

        if alg is None:
            raise ValueError('"alg" not specified')

        S = JWSCore(alg, key, protected, self.objects['payload'])
        sig = S.sign()

        o = dict()
        o['signature'] = base64url_decode(sig['signature'])
        if protected:
            o['protected'] = protected
        if header:
            o['header'] = h
        o['valid'] = True

        if 'signatures' in self.objects:
            self.objects['signatures'].append(o)
        elif 'signature' in self.objects:
            self.objects['signatures'] = list()
            n = dict()
            n['signature'] = self.objects['signature']
            del self.objects['signature']
            if 'protected' in self.objects:
                n['protected'] = self.objects['protected']
                del self.objects['protected']
            if 'header' in self.objects:
                n['header'] = self.objects['header']
                del self.objects['header']
            if 'valid' in self.objects:
                n['valid'] = self.objects['valid']
                del self.objects['valid']
            self.objects['signatures'].append(n)
            self.objects['signatures'].append(o)
        else:
            self.objects.update(o)
Пример #58
0
A4_example = {'key': A4_key,
              'alg': 'ES512',
              'protected': bytes(bytearray(A4_protected)).decode('utf-8'),
              'payload': bytes(bytearray(A4_payload)),
              'signature': bytes(bytearray(A4_signature))}


# RFC 7515 - A.4
A5_protected = 'eyJhbGciOiJub25lIn0'
A5_payload = A2_payload
A5_key = \
    {"kty": "oct", "k": ""}
A5_signature = b''
A5_example = {'key': A5_key,
              'alg': 'none',
              'protected': base64url_decode(A5_protected).decode('utf-8'),
              'payload': bytes(bytearray(A5_payload)),
              'signature': A5_signature}

A6_serialized = \
    '{' + \
    '"payload":' + \
    '"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF' + \
    'tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",' + \
    '"signatures":[' + \
    '{"protected":"eyJhbGciOiJSUzI1NiJ9",' + \
    '"header":' + \
    '{"kid":"2010-12-29"},' + \
    '"signature":' + \
    '"cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ' + \
    'mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb' + \