def gen_account_key(account_id=None): """ Generate key for account ID :param account_id: :return: Key ID for created key """ if account_id is None: raise AttributeError("Provide account_id as parameter") account_kid = "acc-kid-" + str(uuid4()) logger.debug('Generated account_kid: ' + str(account_kid)) try: account_key = gen_key_as_jwk(account_kid=account_kid) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Failed to generate key for account') logger.error('Failed to generate key for account: ' + repr(exp)) raise try: store_jwk(account_id=account_id, account_kid=account_kid, account_key=account_key) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Failed to store generated key. Key must be regenerated.') logger.error('Failed to store generated key: ' + repr(exp)) raise else: logger.info('For account with id: ' + str(account_id) + ' has been generated JWK with kid: ' + str(account_kid)) return account_kid
def jwk_json_to_object(jwk_json=None): """ Converts JWK json presentation to JWK object :param jwk_json: :return: JWK object """ if jwk_json is None: raise AttributeError("Provide jwk_json as parameter") else: logger.debug("As parameter jwk_json: " + repr(jwk_json).replace('u\'', '\'')) try: jwk_dict = json.loads(jwk_json) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not convert JWK json to dict') logger.error('Could not convert JWK json to JWK dict: ' + repr(exp)) raise else: logger.debug("jwk_json: " + repr(jwk_json)) logger.info("JWK json converted to JWK dict") try: jwk_object = jwk.JWK(**jwk_dict) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not convert JWK json to JWK object') logger.error('Could not convert JWK json to JWK object: ' + repr(exp)) raise else: logger.debug('JWK json converted to JWK object') logger.debug('jwk_object: ' + repr(jwk_object.__dict__)) return jwk_object
def clear_blackbox_sqlite_db(): """ Initializes SQLite database. :param connection: Database connection object :return: Database connection object """ try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get database connection') logger.error('get_sqlite_connection: ' + repr(exp)) raise sql_query = '''DELETE FROM account_keys WHERE account_id > 3;''' try: logger.info('Clearing database') logger.debug('Executing: ' + str(sql_query)) connection.execute(sql_query) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not clear database') logger.error('connection.execute(sql): ' + repr(exp)) connection.rollback() connection.close() raise else: connection.commit() connection.close() logger.info('Database cleared') return True
def jws_object_to_json(jws_object=None): """ Converts JWS object to JWS JSON presentation - http://jwcrypto.readthedocs.io/en/stable/jws.html :param jws_object: JSON object :return: JSON presentation of JWS object """ if jws_object is None: raise AttributeError("Provide jws_object as parameter") else: logger.debug("As parameter jws_object: " + repr(jws_object.__dict__).replace('u\'', '\'')) try: jws_json = jws_object.serialize(compact=False) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not convert JWS object to JWS json') logger.error('Could not convert JWS object to JWS json: ' + repr(exp)) raise else: logger.debug('jws_json: ' + str(jws_json)) logger.info('JWS object converted to JWS json') try: jws_json_fixed = jws_header_fix(malformed_jws_json=jws_json) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not fix header in JWS json') logger.error('Could not fix header in JWS json: ' + repr(exp)) raise else: logger.debug('jws_json_fixed: ' + str(jws_json_fixed)) logger.info('Header fixed in JWS json') return jws_json_fixed
def get_key_by_account_id(account_id=None, cursor=None): """ Gets Key by user account ID :param account_id: ID of user account :param cursor: Database cursor :return: Database cursor, JSON presentation of Key and Key ID """ if account_id is None: raise AttributeError("Provide account_id as parameter") if cursor is None: raise AttributeError("Provide cursor as parameter") try: cursor, jwk_object, kid = get_key(account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get JWK object') logger.error('Could not get JWK object: ' + repr(exp)) raise try: jwk_json = jwk_object_to_json(jwk_object=jwk_object) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not export key from JWK object') logger.error('Could not export key from JWK object: ' + repr(exp)) raise else: logger.debug('kid: ' + str(kid)) logger.debug('jwk_object_public: ' + repr(jwk_object)) return cursor, jwk_json, kid
def execute_sql_select(cursor=None, sql_query=None): """ Executes SQL SELECT queries. :param cursor: Database cursor :param sql_query: SQl query to execute :return: Database cursor and result of database query """ if cursor is None: raise AttributeError("Provide cursor as parameter") if sql_query is None: raise AttributeError("Provide sql_query as parameter") try: cursor.execute(sql_query) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Error in SQL SELECT query execution') logger.error('Error in SQL query execution: ' + repr(exp)) raise else: logger.debug('SQL query executed') try: data = cursor.fetchall() except Exception as exp: exp = append_description_to_exception( exp=exp, description='cursor.fetchall() failed') logger.error('cursor.fetchall() failed: ' + repr(exp)) raise else: logger.debug('Data fetched') return cursor, data
def get_key(account_id=None, cursor=None): """ Fetches JSON presentation of JWK object from database and converts JSON presentation to JWK object. :param account_id: ID of user account :param cursor: Database cursor :return: Database cursot, JWK Object and Key ID """ if account_id is None: raise AttributeError("Provide account_id as parameter") if cursor is None: raise AttributeError("Provide cursor as parameter") jwk_dict = {} sql_query = "SELECT id, kid, account_id, jwk FROM account_keys WHERE account_id='%s' ORDER BY id DESC LIMIT 1" % ( account_id) try: cursor, data = execute_sql_select(sql_query=sql_query, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not fetch key from database') logger.error('Could not fetch key from database: ' + repr(exp)) logger.debug('sql_query: ' + repr(sql_query)) raise else: logger.debug("JWK json fetched from database") try: jwk_dict['id'] = data[0][0] jwk_dict['kid'] = data[0][1] jwk_dict['account_id'] = data[0][2] jwk_dict['jwk_key'] = data[0][3] except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not move database response to new dict') logger.error('Key for account not found from database: ' + repr(exp)) raise KeyNotFoundError("Key for account not found from database") log_dict_as_json(data=jwk_dict, pretty=0) try: jwk_object = jwk_json_to_object(jwk_json=jwk_dict['jwk_key']) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not convert JWK json to JWK object') logger.error('Could not convert JWK json to JWK object: ' + repr(exp)) raise else: logger.debug('jwk_object: ' + str(jwk_object.__dict__)) logger.debug('kid: ' + str(jwk_dict['kid'])) return cursor, jwk_object, jwk_dict['kid']
def jws_sign(account_id=None, account_kid=None, jws_object=None, jwk_object=None, jwk_public_json=None, alg="ES256"): """ Signs JWS with JWK. :param account_id: User account ID :param account_kid: Key ID for user's key :param jws_object: JWS object :param jwk_object: JWK object :param jwk_public_json: JSON presentation of public part of JWK :param alg: Signature algorithm to use, Defaults to ES256 :return: Signed JWS object """ if account_id is None: raise AttributeError("Provide account_id as parameter") if account_kid is None: raise AttributeError("Provide account_kid as parameter") if jws_object is None: raise AttributeError("Provide jws_object as parameter") if jwk_object is None: raise AttributeError("Provide jwk_object as parameter") if jwk_public_json is None: raise AttributeError("Provide jwk_public_json as parameter") if alg is None: raise AttributeError("Provide alg as parameter") try: unprotected_header = {'kid': account_kid, 'jwk': json.loads(jwk_public_json)} protected_header = {'alg': alg} unprotected_header_json = json.dumps(unprotected_header) protected_header_json = json.dumps(protected_header) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not create headers') logger.error('Could not create headers: ' + repr(exp)) raise else: logger.info("Created headers") log_dict_as_json(data=unprotected_header) log_dict_as_json(data=protected_header) try: logger.debug("Signing JWS with following") log_dict_as_json(lineno=get_current_line_no(), data={'jws_object': repr(jws_object.__dict__)}) log_dict_as_json(lineno=get_current_line_no(), data={'alg': alg}) log_dict_as_json(lineno=get_current_line_no(), data={'unprotected_header_json': unprotected_header}) log_dict_as_json(lineno=get_current_line_no(), data={'protected_header_json': protected_header}) jws_object.add_signature(jwk_object, alg=alg, header=unprotected_header_json, protected=protected_header_json) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not sign JWS with JWK') logger.error('Could not sign JWS with JWK: ' + repr(exp)) #log_dict_as_json(data={'msg': 'Could not sign JWS with JWK', 'unprotected_header': unprotected_header, 'protected_header': protected_header}) raise else: logger.info("Signed JWS with JWK") logger.debug("Signed jws_object: " + str(jws_object.__dict__)) return jws_object
def store_jwk(account_id=None, account_kid=None, account_key=None): """ Stores JWK to key storage :param account_id: User account ID :param account_kid: Key ID :param account_key: JWK :return: """ if account_id is None: raise AttributeError("Provide account_id as parameter") if account_kid is None: raise AttributeError("Provide account_kid as parameter") if account_key is None: raise AttributeError("Provide account_key as parameter") try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise try: cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise try: cursor = store_jwk_to_db(account_id=account_id, account_kid=account_kid, account_key=account_key, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not store jwk to database') logger.error('Could not store jwk to database: ' + repr(exp)) connection.rollback() connection.close() raise else: connection.commit() connection.close() logger.debug('JWK, kid and account_id stored')
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 init_sqlite_db(connection=None): """ Initializes SQLite database. :param connection: Database connection object :return: Database connection object """ if connection is None: raise AttributeError("Provide connection as parameter") sql_query = '''CREATE TABLE account_keys ( id INTEGER PRIMARY KEY AUTOINCREMENT, kid TEXT UNIQUE NOT NULL, account_id INTEGER UNIQUE NOT NULL, jwk BLOB NOT NULL );''' try: logger.debug('Initializing database') connection.execute(sql_query) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not initialize database') logger.error('connection.execute(sql): ' + repr(exp)) connection.rollback() raise else: connection.commit() logger.debug('Database initialized') return connection
def store_jwk_to_db(account_id=None, account_kid=None, account_key=None, cursor=None): """ Stores JWK to database. :param account_id: User account ID :param account_kid: Key ID :param account_key: Key :param cursor: Database cursor :return: Database cursor and last inserted row id """ if account_id is None: raise AttributeError("Provide account_id as parameter") if account_kid is None: raise AttributeError("Provide account_kid as parameter") if account_key is None: raise AttributeError("Provide account_key as parameter") if cursor is None: raise AttributeError("Provide cursor as parameter") sql_query = "INSERT INTO account_keys (kid, account_id, jws_key) VALUES ('%s', '%s', '%s')" % \ (account_kid, account_id, account_key) try: cursor, last_id = execute_sql_insert(cursor=cursor, sql_query=sql_query) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not store JWK to Database') logger.error('Could not store JWK to Database: ' + repr(exp)) logger.debug('sql_query: ' + repr(sql_query)) raise else: return cursor, last_id
def gen_key_as_jwk(account_kid=None): """ Generates JWK (JSON Web Key) object with JWCrypto's jwk module. - Module documentation: http://jwcrypto.readthedocs.io/en/stable/jwk.html :param account_kid: Key ID, https://tools.ietf.org/html/rfc7517#section-4.5 :return: Generated JWK object """ if account_kid is None: raise AttributeError("Provide account_kid as parameter") gen = {"generate": "EC", "cvr": "P-256", "kid": account_kid} try: account_key = jwk.JWK(**gen) account_key = jwk_object_to_json(jwk_object=account_key) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not generate JWK') logger.error('Could not generate JWK: ' + repr(exp)) raise else: logger.debug('JWK for account generated') logger.debug('account_key: ' + repr(account_key)) return account_key
def get_sqlite_connection(): """ Get connection for SQLite Database :return: Database connection object """ if (os.path.exists(DATABASE) and os.path.isfile(DATABASE)): logger.debug("init_db = False") init_db = False else: logger.debug("init_db = True") init_db = True try: connection = sqlite3.connect(DATABASE) except Exception as exp: exp = append_description_to_exception( exp=exp, description= "Could not get database connection. Could not open db file.") logger.error('sqlite3.connect(' + DATABASE + '): ' + repr(exp)) raise else: if init_db: try: connection = init_sqlite_db(connection=connection) except Exception: raise logger.debug('DB connection at ' + repr(connection)) return connection
def gen_account_api_key(account_id=None): """ Generate API Key for account ID :param account_id: :return: API Key """ if account_id is None: raise AttributeError("Provide account_id as parameter") account_api_key = "account-api-key-" + str(uuid4()) account_api_key = base64.b64encode(account_api_key) logger.debug('Generated account_api_key: ' + str(account_api_key)) try: store_api_key(account_id=account_id, account_api_key=account_api_key) except Exception as exp: exp = append_description_to_exception( exp=exp, description= 'Failed to store generated Api key. Key must be regenerated.') logger.error('Failed to store generated api key: ' + repr(exp)) raise else: logger.info('For account with id: ' + str(account_id) + ' has been generated Api Key: ' + str(account_api_key)) return account_api_key
def get_account_key(account_id=None): """ Get Key by account ID :param account_id: :return: Key """ if (True): # For to disable usage of this function raise NotImplementedError() if account_id is None: raise AttributeError("Provide account_id as parameter") try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise try: cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise try: cursor, key, kid = get_key_by_account_id(account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not lget jwk from database') logger.error('Could not get jwk from database: ' + repr(exp)) connection.rollback() connection.close() raise else: connection.close() logger.debug('JWK fetched') return key
def get_account_api_key(account_id=None): """ Get API Key by account ID :param account_id: :return: API Key """ logger.info("Get Account APIKey by Account ID") if account_id is None: raise AttributeError("Provide account_id as parameter") try: logger.info("Getting DB connection") connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise else: logger.info("Got DB connection") try: logger.info("Getting DB cursor") cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise else: logger.info("Got DB cursor") try: cursor, api_key = get_api_key(account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not find API key from database') logger.error('Could not get API key from database: ' + repr(exp)) connection.rollback() connection.close() raise else: connection.close() logger.debug('API key fetched') return api_key
def get_account_public_key(account_id=None): """ Get public Key by account ID :param account_id: :return: public Key & Key ID """ if account_id is None: raise AttributeError("Provide account_id as parameter") try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise try: cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise try: cursor, key_public, kid = get_public_key_by_account_id( account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get public key from database') logger.error('Could not get public key from database: ' + repr(exp)) connection.rollback() connection.close() raise else: connection.close() logger.debug('Public key fetched') return key_public, kid
def delete_entry_from_blackbox_sqlite_db(account_id=None): """ Delete entry from Blackbox database. :return: Database connection object """ if account_id is None: raise AttributeError("Provide account_id as parameter") try: account_id = str(account_id) except Exception: raise TypeError("account_id MUST be str, not " + str(type(account_id))) try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get database connection') logger.error('get_sqlite_connection: ' + repr(exp)) raise sql_query = "DELETE FROM account_keys WHERE account_id='%s';" % ( account_id) try: logger.info('Deleting entry') logger.debug('Executing: ' + str(sql_query)) connection.execute(sql_query) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not delete entry from database') logger.error('connection.execute(sql): ' + repr(exp)) connection.rollback() connection.close() raise else: connection.commit() connection.close() logger.info('Entry deleted') return True
def get_account_id_by_api_key(api_key=None): """ Get User account ID by Api Key :param api_key: :return: User account ID """ if api_key is None: raise AttributeError("Provide api_key as parameter") try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise try: cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise try: cursor, account_id = get_account_id(api_key=api_key, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not Account ID from database') logger.error('Could not get Account ID from database: ' + repr(exp)) connection.rollback() connection.close() raise else: connection.close() logger.debug('Account ID fetched') return account_id
def check_api_auth_user(api_key): logger.info("Checking Api-Key") try: logger.debug("Fetching Account ID") account_id = get_account_id_by_api_key(api_key=api_key) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Fetching Account ID failed') logger.error('Fetching Account ID failed: ' + repr(exp)) return False else: logger.debug("Found account_id: " + str(account_id) + " with api_key: " + str(api_key)) return True
def execute_sql_insert(cursor, sql_query): """ Executes SQL INSERT queries. :param cursor: Database cursor :param sql_query: SQl query to execute :return: Database cursor and last inserted row id """ if cursor is None: raise AttributeError("Provide cursor as parameter") if sql_query is None: raise AttributeError("Provide sql_query as parameter") last_id = "" try: cursor.execute(sql_query) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Error in SQL INSERT query execution') logger.error('Error in SQL query execution: ' + repr(exp)) raise else: logger.debug('SQL query executed') try: last_id = str(cursor.lastrowid) except Exception as exp: exp = append_description_to_exception( exp=exp, description='lastrowid not found') logger.error('cursor.lastrowid not found: ' + repr(exp)) logger.info('cursor.lastrowid not found. Using None instead') last_id = None else: logger.debug('cursor.lastrowid: ' + last_id) return cursor, last_id
def get_sqlite_connection(): """ Get connection for SQLite Database :return: Database connection object """ if (os.path.exists(DATABASE) and os.path.isfile(DATABASE)): logger.debug("init_db = False") init_db = False else: logger.debug("init_db = True") init_db = True # If there is no db directory it will be created if DATABASE_DIRECTORY != "./": if not os.path.isdir(DATABASE_DIRECTORY): try: os.mkdir(DATABASE_DIRECTORY) print( "Creating LOG_PATH: '{}'.".format(DATABASE_DIRECTORY)) except IOError: print("LOG_PATH: '{}' already exists.".format( DATABASE_DIRECTORY)) except Exception as e: print( "LOG_PATH: '{}' could not be created. Exception: {}.". format(DATABASE_DIRECTORY, repr(e))) try: connection = sqlite3.connect(DATABASE) except Exception as exp: exp = append_description_to_exception( exp=exp, description= "Could not get database connection. Could not open db file.") logger.error('sqlite3.connect(' + DATABASE + '): ' + repr(exp)) raise else: if init_db: try: connection = init_sqlite_db(connection=connection) except Exception: raise logger.debug('DB connection at ' + repr(connection)) return connection
def get_sqlite_cursor(connection=None): """ Get cursor for SQLite database connection. :param connection: Database connection object :return: Database cursor object and Database connection object """ if connection is None: raise AttributeError("Provide connection as parameter") try: cursor = connection.cursor() except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not get database cursor') logger.error('connection.cursor(): ' + repr(exp)) raise else: logger.debug('DB cursor at ' + repr(cursor)) return cursor, connection
def jws_generate(payload=None): if payload is None: raise AttributeError("Provide payload as parameter") payload_json = json.dumps(payload) logger.debug('payload_json: ' + payload_json) try: jws_object = jws.JWS(payload=payload_json) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not generate JWS object with payload') logger.error('Could not generate JWS object with payload: ' + repr(exp)) log_dict_as_json(data={'payload': repr(payload)}) raise else: logger.debug('jws_object: ' + str(jws_object)) log_dict_as_json(lineno=get_current_line_no(), data={'jws_object': jws_object.__dict__}) logger.info('JWS object created') return jws_object
def jwk_object_to_json_public_part(jwk_object=None): """ Exports JWK object's public part to JSON presentation :param jwk_object: :return: JSON presentation of JWK object """ if jwk_object is None: raise AttributeError("Provide jwk_object as parameter") try: jwk_json_public = jwk_object.export_public() except Exception as exp: exp = append_description_to_exception(exp=exp, description='Could not export public part of JWK') logger.error('Could not export public part of JWK: ' + repr(exp)) raise else: logger.debug('JWK exported') logger.debug('jwk_json: ' + repr(jwk_json_public)) return jwk_json_public
def jws_verify(jws_object=None, jwk_object=None): """ Verifies signature of JWS. :param jws_object: JWS object to verify :param jwk_object: JWK onject to use in verification :return: Boolean, presenting if verification passed """ if jws_object is None: raise AttributeError("Provide jws_json as parameter") if jwk_object is None: raise AttributeError("Provide jwk_object as parameter") try: jws_object.verify(jwk_object) except Exception as exp: exp = append_description_to_exception(exp=exp, description='Signature verification failed') logger.error('Signature verification failed: ' + repr(exp)) return False else: logger.info("JWS verified") return True
def generate_and_sign_jws(account_id=None, jws_payload=None): if account_id is None: raise AttributeError("Provide account_id or as parameter") if jws_payload is None: raise AttributeError("Provide jws_payload or as parameter") # Prepare database connection try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise else: logger.info("######## DB Connection -> OK ########") # Prepare database cursor try: cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise else: logger.info("######## DB Cursor -> OK ########") # Get public Key as JSON and Key ID kid = {} try: cursor, key_public_json, kid[0] = get_public_key_by_account_id( account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get public key as JSON') logger.error('Could not get public key as JSON: ' + repr(exp)) connection.rollback() connection.close() raise else: logger.info("######## Public Key -> OK ########") # Get Key as JWK object and Key ID try: cursor, key_object, kid[1] = get_key(account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get key object') logger.error('Could not get key object: ' + repr(exp)) connection.rollback() connection.close() raise else: logger.info("######## Key Object -> OK ########") connection.close() # Generate JWS try: jws_object = jws_generate(payload=jws_payload) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not generate JWS object') logger.error('Could not generate JWS object: ' + repr(exp)) raise else: logger.info("######## JWS Object -> OK ########") # Sign JWS try: jws_object_signed = jws_sign(account_id=account_id, account_kid=kid[0], jws_object=jws_object, jwk_object=key_object, jwk_public_json=key_public_json) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not sign JWS object') logger.error('Could not sign JWS object: ' + repr(exp)) raise else: logger.info("######## JWS signature -> OK ########") # JWS object to JWS JSON try: jws_json = jws_object_to_json(jws_object=jws_object_signed) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not convert JWS object to JWS json') logger.error('Could not convert JWS object to JWS json: ' + repr(exp)) raise else: logger.info("######## JWS conversion -> OK ########") return jws_json
def verify_jws_signature_with_jwk(account_id=None, jws_json_to_verify=None): """ Verifies signature of JWS with key related to user account. Key used in verification is fetched from database by account_id. :param account_id: User account ID :param jws_json_to_verify: JSON presentation of JWS object that should be verified :return: Boolean, presenting if verification passed """ if account_id is None: raise AttributeError("Provide account_id or as parameter") if jws_json_to_verify is None: raise AttributeError("Provide jws_json_to_verify or as parameter") # Prepare JWS for signing try: jws_object_to_verify = jws_json_to_object(jws_json=jws_json_to_verify) 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.debug("jws_object_to_verify: " + str(jws_object_to_verify.__dict__)) logger.info("######## JWS object -> OK ########") # Prepare database connection try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise else: logger.info("######## DB Connection -> OK ########") # Prepare database cursor try: cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise else: logger.info("######## DB Cursor -> OK ########") # Get Key as JWK object and Key ID try: cursor, key_object, kid = get_key(account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get key object') logger.error('Could not get key object: ' + repr(exp)) connection.rollback() connection.close() raise else: logger.info("######## Key Object -> OK ########") connection.close() # Verifying JWS logger.info("Verifying JWS") jws_signature_valid = jws_verify(jws_object=jws_object_to_verify, jwk_object=key_object) logger.info("JWS verified: " + str(jws_signature_valid)) return jws_signature_valid
def sign_jws_with_jwk(account_id=None, jws_json_to_sign=None): """ For signing JWSs that have been generated by others. Gathers necessary data for JWS signing. Signs JWS. :param account_id: User account ID :param jws_json_to_sign: JSON presentation of JWS that should be signed :return: Signed JWS json """ if account_id is None: raise AttributeError("Provide account_id or as parameter") if jws_json_to_sign is None: raise AttributeError("Provide jws_json_to_sign or as parameter") # jws_json_to_sign to dict try: jws_structure = json.loads(jws_json_to_sign) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not convert jws_json_to_sign to dict') logger.error('Could not convert jws_json_to_sign to dict: ' + repr(exp)) raise else: log_dict_as_json(jws_structure) logger.info("######## jws_json_to_sign to dict -> OK ########") # Fix incorrect padding of base64 string try: # dict_keys = jws_structure.keys() # Top-level dict key to enable access to JWS payload # first_key_in_dict = dict_keys[0] # logger.debug('JWS payload before Base64 fix: ' + str(jws_structure[first_key_in_dict]['payload'])) # jws_structure[first_key_in_dict]['payload'] += '=' * (-len(jws_structure[first_key_in_dict]['payload']) % 4) # Fix incorrect padding of base64 string. logger.debug('JWS payload before Base64 fix: ' + str(jws_structure['payload'])) jws_structure['payload'] += '=' * ( -len(jws_structure['payload']) % 4 ) # Fix incorrect padding of base64 string. except Exception as exp: exp = append_description_to_exception( exp=exp, description='Failed to fix incorrect padding of base64 string') logger.error('Failed to fix incorrect padding of base64 string: ' + repr(exp)) raise else: #logger.debug('JWS payload after Base64 fix: ' + str(jws_structure[first_key_in_dict]['payload'])) logger.debug('JWS payload after Base64 fix: ' + str(jws_structure['payload'])) logger.info("######## Base64 fix -> OK ########") # Convert jws_structure to JSON for future steps try: #jws_structure_json = json.dumps(jws_structure[first_key_in_dict]) jws_structure_json = json.dumps(jws_structure) except Exception as exp: exp = append_description_to_exception( exp=exp, description='JSON conversion failed') logger.error('JSON conversion failed: ' + repr(exp)) raise else: logger.info("######## JSON conversion -> OK ########") # Prepare JWS for signing try: jws_object_to_sign = jws_json_to_object(jws_json=jws_structure_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.debug("jws_object_to_sign: " + str(jws_object_to_sign.__dict__)) logger.info("######## JWS object -> OK ########") # Prepare database connection try: connection = get_sqlite_connection() except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get connection SQL database.') logger.error('Could not get connection SQL database: ' + repr(exp)) raise else: logger.info("######## DB Connection -> OK ########") # Prepare database cursor try: cursor, connection = get_sqlite_cursor(connection=connection) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get cursor for database connection') logger.error('Could not get cursor for database connection: ' + repr(exp)) raise else: logger.info("######## DB Cursor -> OK ########") # Get public Key as JSON and Key ID kid = {} try: cursor, key_public_json, kid[0] = get_public_key_by_account_id( account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get public key as JSON') logger.error('Could not get public key as JSON: ' + repr(exp)) connection.rollback() connection.close() raise else: logger.info("######## Public Key -> OK ########") # Get Key as JWK object and Key ID try: cursor, key_object, kid[1] = get_key(account_id=account_id, cursor=cursor) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not get key object') logger.error('Could not get key object: ' + repr(exp)) connection.rollback() connection.close() raise else: logger.info("######## Key Object -> OK ########") connection.close() # Sign JWS try: jws_object_signed = jws_sign(account_id=account_id, account_kid=kid[0], jws_object=jws_object_to_sign, jwk_object=key_object, jwk_public_json=key_public_json) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not sign JWS object') logger.error('Could not sign JWS object: ' + repr(exp)) raise else: logger.info("######## JWS signature -> OK ########") # JWS object to JWS JSON try: jws_json = jws_object_to_json(jws_object=jws_object_signed) except Exception as exp: exp = append_description_to_exception( exp=exp, description='Could not convert JWS object to JWS json') logger.error('Could not convert JWS object to JWS json: ' + repr(exp)) raise else: logger.info("######## JWS conversion -> OK ########") return jws_json