예제 #1
0
def verify_proof_chain(did, did_document, proof_chain):
    #--------------Verify sha-256 in the last proof----------
    document_sha256 = hashlib.sha256()
    document_sha256.update(json.dumps(did_document).encode('utf-8'))
    document_sha256_b64 = base64url_encode(document_sha256.digest())
    last_proof = jws.JWS()
    last_proof.deserialize(proof_chain[-1])
    payload = json.loads(last_proof.objects['payload'].decode())
    if (document_sha256_b64 != payload['sha-256']):
        raise Exception("The sha-256 included in the proof is not valid")
        return -1
    #--------------Verify the chain of trust---------------
    _did = did
    signer_jwk = did_to_jwk(
        did)  #----The fist proof must be verified using the DID
    for proof in proof_chain:
        claimed_proof = jws.JWS()
        claimed_proof.deserialize(proof)
        payload = json.loads(claimed_proof.objects['payload'].decode())
        _id = payload['id']
        if (_id != _did):  #----All proofs must include DID in their id field
            raise Exception("A proof contains an invalid id")
            return -1
        claimed_proof.verify(signer_jwk)
        if ('controller' in payload):
            signer_jwk = jwk.JWK(**payload[
                'controller'])  #----The next proof must be verified with this
    return True
예제 #2
0
def verifyJWS(json_JWS):
    def verify(jws, header):
        try:
            sign_key = jwk.JWK(**header["jwk"])
            jws.verify(sign_key)
            return True
        except Exception as e:
            debug_log.info(repr(e))

    try:

        json_web_signature = jws.JWS()
        if (isinstance(json_JWS, dict)):
            json_web_signature.deserialize(dumps(json_JWS))
        elif (isinstance(json_JWS, str)):
            json_web_signature = jws.JWS(json_JWS)
            json_JWS = loads(json_JWS)

        if json_JWS.get("header", False):  # Only one signature
            if (verify(json_web_signature, json_JWS["header"])):
                return True
            return False
        elif json_JWS.get("signatures", False):  # Multiple signatures
            signatures = json_JWS["signatures"]
            for signature in signatures:
                if (verify(json_web_signature, signature["header"])):
                    return True
        return False
    except Exception as e:
        debug_log.info("M:", repr(e))
        return False
예제 #3
0
 def test_jws_loopback(self):
     sign = jws.JWS(payload='message')
     sign.add_signature(jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                        alg="HS512")
     o = sign.serialize()
     check = jws.JWS()
     check.deserialize(o,
                       jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                       alg="HS512")
     self.assertTrue(check.objects['valid'])
예제 #4
0
def decode_message(logger, message):
    """ decode jwstoken and return header, payload and signature """
    logger.debug('decode_message()')
    jwstoken = jws.JWS()
    result = False
    error = None
    try:
        jwstoken.deserialize(message)
        protected = json.loads(jwstoken.objects['protected'])
        if bool(jwstoken.objects['payload']):
            payload = json.loads(jwstoken.objects['payload'])
        else:
            payload = {}
        signature = jwstoken.objects['signature']
        result = True
    except BaseException as err:
        logger.error('decode_message() err: {0}'.format(err))
        error = str(err)
        protected = {}
        payload = {}
        signature = None

    if payload:
        payload = dkeys_lower(payload)
    return (result, error, protected, payload, signature)
예제 #5
0
def generate_db_auth_code_context(client_secret=None):
    # --> Generate a valid authorization code
    client_data, user_data = test_utils.add_user_client_context_to_db()
    db_auth_code = models.AuthorisationCode(application_id=client_data[0]['id'])
    db.session.add(db_auth_code)
    db.session.commit()
    assert db_auth_code.id

    # --> Create an appropriate payload to be signed in
    now = datetime.utcnow()
    before = now - timedelta(seconds=10)
    payload = {
        'client_id': client_data[0]['id'],
        'redirect_uri': client_data[0]['redirect_uri'],
        'expiration_date': before.strftime("%d-%m-%Y %H:%M:%S"),
        'code_id': db_auth_code.id
    }

    # --> Sign the payload and generate the JWS authorization code
    jws_obj = jws.JWS(json.dumps(payload).encode(config.Config.AUTH_CODE_ENCODING))
    private_key = jwk.JWK.from_json(config.Config.private_jwk)
    jws_obj.add_signature(private_key, None, json.dumps({"alg": config.Config.JWT_ALGORITHM}))
    post_data = {
        'grand_type': 'authorization_code',
        'client_secret': client_data[0]['client_secret'] if not client_secret else client_secret,
        'code': jws_obj.serialize(compact=True)
    }
    return post_data, client_data, db_auth_code
예제 #6
0
    def test_should_throw_exception_when_jws_signature_has_expired(self):

        localDir = os.path.abspath(os.path.dirname(__file__))
        clientPath = os.path.join(localDir, 'resources', 'private-jwkset1')
        hyperwalletPath = '/public-jwkset1'
        encryption = Encryption(clientPath, hyperwalletPath)

        jwsKeySet = self.__getJwkKeySet(location=clientPath)
        jwkSignKey = self.__findJwkKeyByAlgorithm(jwkKeySet=jwsKeySet,
                                                  algorithm='RS256')
        privateKeyToSign = jwk.JWK(**jwkSignKey)
        body = "Test message"
        jwsToken = cryptoJWS.JWS(body.encode('utf-8'))
        jwsToken.add_signature(
            privateKeyToSign, None,
            json_encode({
                "alg": "RS256",
                "exp": int(time.time()) - 6000,
                "kid": jwkSignKey['kid']
            }))
        signedBody = jwsToken.serialize(True)

        with self.assertRaises(HyperwalletException) as exc:
            encryption.checkJwsExpiration(signedBody)

        self.assertEqual(
            exc.exception.message,
            'JWS signature has expired, checked by [exp] JWS header')
예제 #7
0
    def encrypt(self, body=None):
        '''
        :param body:
            Body message to be 1) signed and 2) encrypted. **REQUIRED**
        :returns:
            String as a result of signature and encryption of input message body
        '''

        jwsKeySet = self.__getJwkKeySet(location = self.clientPrivateKeySetLocation)
        jwkSignKey = self.__findJwkKeyByAlgorithm(jwkKeySet = jwsKeySet, algorithm  = self.signAlgorithm)
        privateKeyToSign = jwk.JWK(**jwkSignKey)
        jwsToken = cryptoJWS.JWS(body.encode('utf-8'))
        jwsToken.add_signature(privateKeyToSign, None, json_encode({
            "alg": self.signAlgorithm,
            "kid": jwkSignKey['kid'],
            "exp": self.__getJwsExpirationTime()
        }))
        signedBody = jwsToken.serialize(True)

        jweKeySet = self.__getJwkKeySet(location = self.hyperwalletKeySetLocation)
        jwkEncryptKey = self.__findJwkKeyByAlgorithm(jwkKeySet = jweKeySet, algorithm  = self.encryptionAlgorithm)
        publicKeyToEncrypt = jwk.JWK(**jwkEncryptKey)
        protected_header = {
            "alg": self.encryptionAlgorithm,
            "enc": self.encryptionMethod,
            "typ": "JWE",
            "kid": jwkEncryptKey['kid'],
        }
        jweToken = jwe.JWE(signedBody.encode('utf-8'), recipient=publicKeyToEncrypt, protected=protected_header)
        return jweToken.serialize(True)
예제 #8
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)
    def verify(self, jwt_raw):
        web_signature = jws.JWS()
        # pylint: disable=protected-access
        web_signature._allowed_algs = ALLOWED_ALGORITHMS
        web_signature.deserialize(jwt_raw, None, 'ES256K')

        key_id = web_signature.jose_header['kid']
        key_raw = None

        try:
            key_raw = self.resolver.resolveKey(key_id)
        # pylint: disable=broad-except
        except:
            return 'Error resolving key from did'

        if key_raw is None:
            return 'Error resolving key from did'

        key = jwk.JWK.from_json(json.dumps(key_raw))

        try:
            web_signature.verify(key)
            return web_signature.payload
        # pylint: disable=broad-except
        except:
            return 'invalid'
예제 #10
0
 def sign(self, payload, private_key_pem_data, header_json_data):
     jwstoken = jws.JWS(payload.encode('utf-8'))
     rsa_private_key = jwk.JWK.from_pem(private_key_pem_data)
     jwstoken.add_signature(key=rsa_private_key, protected=header_json_data)
     sign = jwstoken.serialize(compact=True)
     print("JWS signing successful. serialized data: {}")
     return sign
예제 #11
0
    def decrypt_and_verify(self, content):
      # decrypt
      jwetoken = jwe.JWE()
      jwetoken.deserialize(content, key=encryption_private_key)
      if json.loads(jwetoken.objects['protected'])['alg'] != 'RSA-OAEP-256' or json.loads(jwetoken.objects['protected'])['enc'] != 'A256CBC-HS512':
        raise Exception('Unsupported encryption') # we have to check those, otherwise other encryptions can be used as an attack vector

      # verify
      jwstoken = jws.JWS()
      jwstoken.deserialize(jwetoken.payload)

      if signature_public_key is None:
        jku = json.loads(jwstoken.objects['protected'])['jku']
        kid = json.loads(jwstoken.objects['protected'])['kid']

        #NOTE: to be certain to use a valid public key, one would have to check the
        #      domain name and SSL certificate's Common Name against a whitelisted list
        keys = requests.get(jku).content
        keyset = jwk.JWKSet()
        keyset.import_keyset(keys)
        verification_key = keyset.get_key(kid)
      else:
        verification_key = signature_public_key

      if json.loads(jwstoken.objects['protected'])['alg'] != 'RS512':
        raise Exception('Unsupported signature algorithm') # we have to check, otherwise other algorithms can be used as an attack vector

      jwstoken.verify(verification_key) # if there's no exception, the signature is valid
      return jwstoken.payload
예제 #12
0
    def _signed_request(self,
                        url: str,
                        payload: dict,
                        kid: str = None) -> requests.Response:
        p = json.dumps(payload)
        account_jwk = jwk.JWK.from_pem(self._account.key_pem.encode())

        protected = {'alg': 'RS256', 'url': url, 'nonce': self._nonce}
        if kid is None:
            protected['jwk'] = json.loads(account_jwk.export_public())
        else:
            protected['kid'] = kid

        jws_token = jws.JWS(p.encode())
        jws_token.add_signature(account_jwk,
                                None,
                                protected=protected,
                                header=None)

        sig = jws_token.serialize()
        response = requests.post(
            url, data=sig, headers={'Content-Type': 'application/jose+json'})
        reply_nonce = response.headers.get('Replay-Nonce', None)
        if reply_nonce is not None:
            self._nonce = reply_nonce
        return response
예제 #13
0
def message_authentication_thread():
    """Get messages from decrypted queue, auth and drop to filebeat socket."""
    global DECRYPTED_MESSAGES
    global AUTHENTICATED_MESSAGES
    global VALID_SENDERS
    global BAIL
    while True:
        if BAIL:
            print("Bailing out of authentication thread.")
            break
        content = DECRYPTED_MESSAGES.get()
        try:
            contents = message_is_authentic(content)
            if not contents:
                continue
            jwstoken = jws.JWS()
            jwstoken.deserialize(content)
            dns_uri = jwstoken.jose_header["x5u"]
            sender_id = Util.get_name_from_dns_uri(dns_uri)
            print("Message is authentic from {}".format(sender_id))
            message = "{} says: {}".format(sender_id, contents.decode())
            AUTHENTICATED_MESSAGES.put(json.dumps(message))
        except InvalidJWSSignature as err:
            print("Failed to authenticate! ({})".format(err))
        except InvalidJWSObject as err:
            print("Unable to load JWS object: {}".format(err))
예제 #14
0
    def test_valid_request_correct_url_code(self, other_private_jwk):
        '''Ensure that the a code url parameter is passed and is valid
        '''

        url_args = {
            'grand_type': 'authorization_code',
            'client_secret': 'something',
            'code': 'Not a valid token'
        }

        # ---> Invalid representation of JWS Format
        auth_token = oauth_code.AuthorisationToken(url_args=url_args)
        assert not auth_token.validate_request()
        assert 'non-valid representation' in auth_token.errors[
            'error_description']
        assert auth_token.errors['code'] == 400

        # ---> JWS has not been signed by us
        # Create a JWS with given payload and a different private key
        payload = {'dummy': 'data'}
        jws_obj = jws.JWS(
            json.dumps(payload).encode(config.Config.AUTH_CODE_ENCODING))
        jws_obj.add_signature(other_private_jwk, None,
                              json.dumps({"alg": config.Config.JWT_ALGORITHM}))
        auth_token.code = jws_obj.serialize(compact=True)

        assert not auth_token.validate_request()
        assert 'token that has not been signed in' in auth_token.errors[
            'error_description']
        assert auth_token.errors['code'] == 403
예제 #15
0
def jws_json_to_object(jws_json=None):
    """
    Converts JWS json presentation to JWS object
    - http://jwcrypto.readthedocs.io/en/stable/jws.html

    :param jws_json: JSON presentation of JWS object
    :return: JWS object
    """
    if jws_json is None:
        raise AttributeError("Provide jws_json as parameter")
    else:
        logger.debug("As parameter jws_json: " +
                     repr(jws_json).replace('u\'', '\''))

    try:
        jws_object = jws.JWS()
        jws_object.deserialize(raw_jws=jws_json)
    except Exception as exp:
        exp = append_description_to_exception(
            exp=exp, description='Could not convert JWS json to JWS object')
        logger.error('Could not convert JWS json to JWS object: ' + repr(exp))
        raise
    else:
        logger.info('JWS json converted to JWS object')
        logger.debug('jws_object: ' + repr(jws_object.__dict__))
        return jws_object
 def decode_jwt(jwt_data: str):
     jws_token = jws.JWS(jwt_data)
     jws_token.deserialize(jwt_data)
     return {
         "header": jws_token.jose_header,
         "payload": json.loads(jws_token.objects.get('payload'))
     }
예제 #17
0
def signature_check(logger, message, pub_key):
    """ check JWS """
    logger.debug('signature_check()')

    result = False
    error = None

    if pub_key:
        # load key
        try:
            jwkey = jwk.JWK(**pub_key)
        except BaseException as err:
            logger.error('load key failed {0}'.format(err))
            jwkey = None
            result = False
            error = str(err)

        # verify signature
        if jwkey:
            jwstoken = jws.JWS()
            jwstoken.deserialize(message)
            try:
                jwstoken.verify(jwkey)
                result = True
            except BaseException as err:
                logger.error('verify failed {0}'.format(err))
                error = str(err)
    else:
        error = 'No key specified.'

    # return result
    return (result, error)
예제 #18
0
    def response(self):
        '''Given a valid request, craft an 'authorization code' to be sent back to the client as specified by oAuth
        '''

        # Create a unique id in the database to be associated to this token
        auth_code = models.AuthorisationCode(application_id=self.client_id)
        db.session.add(auth_code)
        db.session.commit()

        exp_date = (datetime.utcnow() + timedelta(seconds=config.Config.AUTH_CODE_EXPIRATION_TIME)).\
            strftime("%d-%m-%Y %H:%M:%S")
        payload = {
            'client_id': self.client_id,
            'redirect_uri': base64.urlsafe_b64encode(self.redirect_uri.encode()).decode(),
            'expiration_date': exp_date,
            'code_id': auth_code.id
        }

        # Create a JWS with given payload
        jws_obj = jws.JWS(json.dumps(payload).encode(config.Config.AUTH_CODE_ENCODING))
        private_key = jwk.JWK.from_json(config.Config.private_jwk)
        jws_obj.add_signature(private_key, None, json.dumps({"alg": config.Config.JWT_ALGORITHM}))

        # return code and state as defined by oAuth
        return {
            'code': jws_obj.serialize(compact=True),
            'state': self.state
        }
예제 #19
0
def decrypt_verify_and_get_payload(private_encryption_key,
                                   public_signature_key, content):
    # decrypt
    jwetoken = jwe.JWE()
    jwetoken.deserialize(content, key=private_encryption_key)
    logging.debug(f'Payload correctly decrypted using our private key')
    if json.loads(jwetoken.objects['protected']
                  )['alg'] != 'RSA-OAEP-256' or json.loads(
                      jwetoken.objects['protected'])['enc'] != 'A256CBC-HS512':
        raise Exception(
            'Unsupported encryption'
        )  # we have to check those, otherwise other encryptions can be used as an attack vector

    logging.debug(f'JWE payload: {jwetoken.payload}')
    # verify
    jwstoken = jws.JWS()
    jwstoken.deserialize(jwetoken.payload)

    if json.loads(jwstoken.objects['protected'])['alg'] != 'RS512':
        raise Exception(
            'Unsupported signature algorithm'
        )  # we have to check, otherwise other algorithms can be used as an attack vector

    jwstoken.verify(public_signature_key
                    )  # if there's no exception, the signature is valid
    return jwstoken.payload
예제 #20
0
def get_payload_from_token(token, key):
    jws_token = jws.JWS()
    jws_token.deserialize(token)
    try:
        jws_token.verify(key)
        return Box(json.loads(jws_token.payload))
    except jws.InvalidJWSSignature:
        return None
예제 #21
0
 def verify_message(self, signature):
     try:
         verifier = jws.JWS()
         verifier.deserialize(signature)
         verifier.verify(self._key, alg='EdDSA')
         return verifier.payload.decode("utf-8")
     except jws.InvalidJWSSignature:
         raise OffChainInvalidSignature(signature)
예제 #22
0
def get_controller(proof):
    delegation_proof = jws.JWS()
    delegation_proof.deserialize(proof)
    payload = json.loads(delegation_proof.objects['payload'].decode())
    if ('controller' in payload):
        return jwk.JWK(**payload['controller'])
    else:
        return None
예제 #23
0
def create_jwe(header, payload, sign_key, enc_key):
    jws_token = jws.JWS(json_encode(payload))
    jws_token.add_signature(sign_key, None, json_encode({'alg': 'ES256'}))

    jwe_token = jwe.JWE(jws_token.serialize(compact=True), json_encode(header))
    jwe_token.add_recipient(enc_key)

    return jwe_token.serialize(compact=True)
예제 #24
0
def make_private_key_jwt(payload):
    """Generate a new compact JWS to identify us to ISB"""
    jwstoken = jws.JWS(payload)
    jwstoken.add_signature(signing_key,
                           alg="RS256",
                           protected=json_encode(
                               dict(alg='RS256',
                                    kid=signing_key.thumbprint())))
    return jwstoken.serialize(True)
예제 #25
0
 def verify(self, jws_payload, public_key_pem_data):
     jwstoken = jws.JWS()
     jwstoken.deserialize(raw_jws=jws_payload)
     jwk_token = jwk.JWK()
     jwk_token.import_from_pem(public_key_pem_data)
     jwstoken.verify(jwk_token)
     payload = jwstoken.payload
     print(payload)
     return payload
예제 #26
0
 def validate_token(self, token):
     key = jwk.JWK(**JWK_KEY)
     jwstoken = jws.JWS()
     jwstoken.deserialize(token)
     try:
         jwstoken.verify(key)
         return True
     except:
         return False
예제 #27
0
 async def jwsToken(self, payload: str):
     try:
         jwk = await self.privJwk()
         token = jws.JWS(payload.encode('utf-8'))
         token.add_signature(jwk, None, json_encode({"alg": "RS256"}),
                             json_encode({"kid": jwk.thumbprint()}))
         return token
     except Exception as err:
         self.debug(f'Cannot create JWS token: {err}')
예제 #28
0
 def sign(self):
     """return a signed JWT header token"""
     self.__pol = Policy()
     self.__tok = jws.JWS(json_encode(self.__pol.claims))
     self.__tok.add_signature(self.__key,
                              alg=None,
                              protected=json_encode(self.__header))
     self.__sig = self.__tok.serialize()
     self.__hdr = self.serialize(self.__sig)
     return self.__hdr
예제 #29
0
 def generate_authorization_header(self):
     # print(dumps(self.json_structure, indent=2))
     """
     Generates the actual PoP token and the string for Authorization header
     :return:
     """
     token = jws.JWS(dumps(self.json_structure).encode("utf-8"))
     token.add_signature(key=self.sign_key, alg=self.alg, header=self.header, protected=self.protected)
     authorization_header = "PoP {}".format(token.serialize(compact=True))
     return authorization_header
예제 #30
0
def test_example_sign_verify():
    from jwcrypto.common import json_encode

    # Generate and export keys
    key = jwk.JWK.generate(kty='OKP', crv='Ed25519')
    pub_data = key.export_to_pem(private_key=False, password=None)
    print('--- KEY / SIGN / VERIFY TEST ---')

    # Export full key:
    full = key.export_private()
    print('K.Pair:', full)

    # Export public
    pub = key.export_public()
    print('Public:', pub)
    key_pub = jwk.JWK(**json.loads(pub))

    # Sign a message
    payload = "My Integrity protected message"
    print('Payload:', payload)
    jwstoken = jws.JWS(payload.encode('utf-8'))
    jwstoken.add_signature(
        key,
        alg=None,
        protected=json_encode({"alg": "EdDSA"}),
        header=json_encode({"kid": key.thumbprint()}))
    sig = jwstoken.serialize(compact=True)
    print('Signature:', sig)

    # Verify a message
    verifier = jws.JWS()
    verifier.deserialize(sig)
    verifier.verify(key)  # , alg='EdDSA')
    payload2 = verifier.payload

    # Verify a message -- pub only
    verifier_pub = jws.JWS()
    verifier_pub.deserialize(sig)
    verifier_pub.verify(key_pub)  #, alg='EdDSA')
    payload3 = verifier_pub.payload

    assert payload.encode('utf-8') == payload3