def validate(ticket): try: utils.verify_signature(ticket.get_unique_repr(), ticket.signature, ticket.node.public_key) except InvalidSignature: ticket.errors = "Invalid ballot claim ticket signature" raise InvalidSignature(ticket.errors)
def validate_transaction(transaction): """Validates a transaction's signature and returns whether its content matches the signature. Note that this validation may not be enough for a transaction; the content for a specific transaction may need further validation. Use this method as a first-step verification of any transaction. Args: transaction transaction to be validated """ try: utils.verify_signature( transaction.get_unique_repr(**transaction.signature_kwargs), transaction.signature, transaction.node.public_key) except InvalidSignature as e: public_key = transaction.node.public_key raise InvalidSignature( 'Invalid signature by public key: {}'.format(hash(public_key)))
def trigger_build(): """ Endpoint where GitHub will send a POST request to (payload URL), with details of a subscribed event. For now, we only do something special when we get a 'push' event. Events: https://developer.github.com/webhooks/#events """ delivery_id = request.headers.get('X-Github-Delivery') # soon for logging event = request.headers.get('X-Github-Event') signature = request.headers.get('X-Hub-Signature') if event != 'push': return (jsonify({'msg': 'Payload received'}), 200) data = request.get_data() if not verify_signature(data, signature): return (jsonify({'msg': 'Hash signatures do not match'}), 400) payload = request.get_json() # This part is where we execute our deploy/build scripts, depending on how # we want it to be run. # For this case, we do the following: # 1) Check branch, only proceed if branch is `master`. # 2) Get project/repository name (for handling many repositories' webhooks) # 3) Check if there are npm dependency changes via commits' modified files # 4) If so, make sure we could tell the deploy script (using flags, etc.) # 5) Execute deploy script with the project name, and the above flag (#4) # only proceed if branch is master if payload.get('ref') == 'refs/heads/master': # get project name project_name = payload.get('repository').get('name') # check if there are npm dependency changes commits = payload.get('commits') dependency_change_commits = [commit for commit in commits if 'package.json' in commit['modified']] # take directory of deploy script from environment variable default_script_dir = os.path.join(os.getcwd(), 'deploy.sh') command_params = [config('DEPLOY_SCRIPT_DIR', default_script_dir)] # append command params, add -d flag if npm dependency changes exist if len(dependency_change_commits) > 1: command_params.append('-d') command_params.append(project_name) # TODO: Add logging try: cmd_output = subprocess.check_output(command_params,) return (jsonify({ 'msg': 'Build success', 'output': cmd_output.decode('utf-8') }), 200) except subprocess.CalledProcessError as error: return (jsonify({'msg': error.output.decode('utf-8')}), 400) return (jsonify({'msg': 'Valid, but push not in master branch'}), 200)
def get_packages_data(): "Function queries the iQuality website for packages json data" if config.use_local_json_files: with open(r"%s\packages.json" % config.local_json_files_path, 'r') as f: data = f.read() return json.loads(data, object_pairs_hook=OrderedDict) try: obj = urllib2.urlopen(config.packages_json_url, timeout=config.webservices_timeout) data = obj.read() obj.close() obj = urllib2.urlopen("%s.sign" % config.packages_json_url, timeout=config.webservices_timeout) sign = obj.read() obj.close() assert utils.verify_signature(data, sign, config.pubkey_path) log.debug('packages_json_url signature check passed') return json.loads(data, object_pairs_hook=OrderedDict) except: log.error('packages_json_url signature check FAILED:') log.error(traceback.format_exc()) return {}
def handle_payload(): content = request.get_json(silent=True) #embed() header_signature = request.headers['X-Hub-Signature'] embed() if header_signature is None: abort(403) if not utils.verify_signature(header_signature,request.data,GITHUB_HOOK_SECRET): abort(403) return "Authenticated request :D"
def post(self): # FIXME implement some sort of size limits, i.e. no results over 1MB or something like that # FIXME implement some sort of rate limits, i.e. no client can submit over 1000 results per hour or something like that args = result_parser().parse_args() # fetch info about the machine with DB() as (conn, cursor): cursor.execute('SELECT id, secret_key FROM machines WHERE name = %(name)s AND is_approved AND is_active', {'name' : args.machine}) machine = cursor.fetchone() if not machine: abort(401, message="unknown / inactive machine") # verify the signature if not verify_signature(args, secret=machine['secret_key'], signature=args.signature): abort(401, message='invalid signature') cursor.execute('SELECT v.id AS id FROM distribution_versions v JOIN distributions d ON (d.id = v.dist_id) WHERE dist_name = %(name)s AND version_number = %(version)s', {'name' : args.distribution, 'version' : args.version}) version = cursor.fetchone() if not version: abort(401, message="unknown distribution/version") # check that we haven't seen the UUID before (this means someone bad can't replay the message over and over) cursor.execute('SELECT result_uuid AS uuid FROM results WHERE result_uuid = %(uuid)s LIMIT 1', {'uuid' : args.uuid}) result = cursor.fetchone() if result: abort(401, message="duplicate uuid") # OK, so the submitted result seems to be OK ... let's store the data with DB(False) as (conn, cursor): cursor.execute('''INSERT INTO results (result_uuid, machine_id, dist_version_id, pg_version, pg_config, env_info, load_result, install_result, check_result, load_duration, install_duration, check_duration, log_load, log_install, log_check, check_diff) VALUES (%(uuid)s, %(machine)s, %(version)s, %(pgversion)s, %(config)s, %(env)s, %(load)s, %(install)s, %(check)s, %(load_duration)s, %(install_duration)s, %(check_duration)s, %(load_log)s, %(install_log)s, %(check_log)s, %(diff)s)''', {'uuid' : args.uuid, 'machine' : machine['id'], 'version' : version['id'], 'pgversion' : get_pg_version(args.config), 'load' : (args.load != 'unknown' and args.load or None), 'install' : (args.install != 'unknown' and args.install or None), 'check' : (args.check != 'unknown' and args.check or None), 'install_log' : base64.b64decode(args.install_log), 'load_log' : base64.b64decode(args.load_log), 'check_log' : base64.b64decode(args.check_log), 'diff' : base64.b64decode(args.check_diff), 'install_duration' : args.install_duration, 'load_duration' : args.load_duration, 'check_duration' : args.check_duration, 'config' : args.config, 'env' : args.env}) conn.commit() return {'uuid' : args.uuid}
def get_packages_data(): "Function queries the iQuality website for packages json data" try: obj = urllib2.urlopen(config.packages_json_url, timeout=config.webservices_timeout) data = obj.read() obj.close() obj = urllib2.urlopen("%s.sign" % config.packages_json_url, timeout=config.webservices_timeout) sign = obj.read() obj.close() assert utils.verify_signature(data, sign, config.pubkey_path) log.debug('packages_json_url signature check passed') return json.loads(data, object_pairs_hook=OrderedDict) except: log.error('packages_json_url signature check FAILED:') log.error(traceback.format_exc()) return {}
def verify_server(self, message): if self.state != SERVER_AUTH: logger.debug("Invalid state") self.transport.close() self.loop.stop() logger.info("Verifying server") data = message.get("data", None) server_certificate = certificate_object_from_pem( base64.b64decode(data['certificate'].encode())) signed_nonce = base64.b64decode(data['sign_nonce'].encode()) certificates = load_certificates("client_certs/") chain = [] chain_completed = construct_certificate_chain(chain, server_certificate, certificates) if not chain_completed: error_message = "Couldn't complete the certificate chain" logger.warning(error_message) message = {"type": "ERROR", "message": error_message} self._send(message) self.transport.close() self.loop.stop() else: valid_chain, error_messages = validate_certificate_chain(chain) if not valid_chain: logger.error(error_messages) message = {"type": "ERROR", "message": error_messages} self._send(message) self.transport.close() self.loop.stop() else: if verify_signature(server_certificate, signed_nonce, self.nonce): message = {"type": "SUCCESS_AUTH"} self._send(message) self.state = STATE_AUTH
def get_components_data(): "Function queries the iQuality website for components json data" try: obj = urllib2.urlopen(config.components_json_url, timeout=config.webservices_timeout) data = obj.read() obj.close() obj = urllib2.urlopen("%s.sign" % config.components_json_url, timeout=config.webservices_timeout) sign = obj.read() obj.close() assert utils.verify_signature(data, sign, config.pubkey_path) log.debug('components_json_url signature check passed') return json.loads(data, object_pairs_hook=OrderedDict) except: log.error('components_json_url signature check FAILED:') log.error('config.components_json_url = %s' % config.components_json_url) log.error(traceback.format_exc()) return {}
def get_components_data(): "Function queries the iQuality website for components json data" if config.use_local_json_files: with open(r"%s\components.json" % config.local_json_files_path, 'r') as f: data = f.read() return json.loads(data, object_pairs_hook=OrderedDict) try: obj = urllib2.urlopen(config.components_json_url, timeout=config.webservices_timeout) data = obj.read() obj.close() obj = urllib2.urlopen("%s.sign" % config.components_json_url, timeout=config.webservices_timeout) sign = obj.read() obj.close() assert utils.verify_signature(data, sign, config.pubkey_path) log.debug('components_json_url signature check passed') return json.loads(data, object_pairs_hook=OrderedDict) except: log.error('components_json_url signature check FAILED:') log.error(traceback.format_exc()) return {}
def test_verify_signature(self): message = "nooneknows" message_encoded = message.encode('utf8') signature = rsa.sign(message_encoded, self.privkey, "SHA-256") actual = utils.verify_signature(message_encoded, signature, self.pubkey) self.assertTrue(actual, True)
async def stripe_hook(request: web.Request): if not verify_signature(request, signing_key): return web.Response(status=401) print(await request.json()) return web.Response()
def abort_submission(request): logger = utils.CloudLogger().log_request(request) try: data = request.get_json() # 1) Validate the token if not isinstance(data, dict): return ({ 'error': "Bad Request", 'message': ("No data was provided" if data is None else "Expected JSON dictionary in request body") }, 400) token = utils.extract_token(request.headers, data) if token is None: return ({ 'error': 'Bad Request', 'message': 'Token must be provided in header or body' }, 400) token_info = utils.get_token_info(token) if 'error' in token_info: return ({ 'error': 'Invalid Token', 'message': token_info['error_description'] if 'error_description' in token_info else 'Google rejected the client token' }, 401) if not utils.validate_token(token_info): return ({ 'error': 'Rejected token', 'message': 'Token was valid but did not meet Lapdog security requirements. Token must have email, profile, openid, and devstorage.read_write scopes.' ' Broad users must authenticate via a LapdogToken' }, 403) # 2) Validate user's permission for the bucket if 'bucket' not in data: return ({ 'error': 'Bad Request', 'message': 'Missing required parameter "bucket"' }, 400) session = utils.generate_user_session(token) read, write = utils.validate_permissions(session, data['bucket']) if read is None: # Error, write will contain a message return ({ 'error': 'Cannot Validate Bucket Permissions', 'message': write }, 400) if not (read and write): # User doesn't have full permissions to the bucket return ({ 'error': 'Not Authorized', 'message': 'User lacks read/write permissions to the requested bucket' }, 401) # 3) Check that submission.json exists, and is less than 1 Gib if 'submission_id' not in data: return ({ 'error': 'Bad Request', 'message': 'Missing required parameter "submission_id"' }, 400) submission = utils.fetch_submission_blob(session, data['bucket'], data['submission_id']) result, message = utils.validate_submission_file(submission) if not result: return ({'error': 'Bad Submission', 'message': message}, 400) # 4) Download submission and parse operation try: submission = json.loads(submission.download_as_string().decode()) except: return ({ 'error': 'Invalid Submission', 'message': 'Submission was not valid JSON' }, 400) if 'operation' not in submission: return ({ 'error': 'Invalid Submission', 'message': 'Submission contained no operation metadata' }, 400) signature_blob = utils.getblob( 'gs://{bucket}/lapdog-executions/{submission_id}/signature'.format( bucket=data['bucket'], submission_id=data['submission_id']), credentials=session.credentials) if not signature_blob.exists(): return ({ 'error': 'No Signature', 'message': 'The submission signature could not be found. Refusing to abort job' }, 403) if not utils.verify_signature( signature_blob, (data['submission_id'] + submission['operation']).encode()): return ({ 'error': 'Invalid Signature', 'message': 'Could not validate submission signature. Refusing to abort job' }, 403) core_session = utils.generate_core_session() # 5) Generate abort key logger.log("Generating new signature", data=data['submission_id']) utils.sign_object( data['submission_id'].encode(), utils.getblob( 'gs://{bucket}/lapdog-executions/{submission_id}/abort-key'. format(bucket=data['bucket'], submission_id=data['submission_id']), credentials=session.credentials), core_session.credentials) if 'hard' in data and data['hard']: # 6) Abort operation logger.log("Hard-aborting submission", submission_id=data['submission_id'], operation_id=submission['operation'], severity='NOTICE') response = core_session.post( "https://genomics.googleapis.com/v2alpha1/{operation}:cancel". format(operation=quote( submission['operation']) # Do not quote slashes here )) return response.text, response.status_code return ({ 'status': 'Aborting', 'message': 'A soft-abort request has been sent.' ' If the submission does not abort soon, abort it with hard=True to force-kill the cromwell server' }, 200) except: logger.log_exception() return ({ 'error': 'Unknown Error', 'message': traceback.format_exc() }, 500)
def setup(self): print("The merchant is running on port: 3000.") print( "\n -------------------------------------------------------------------------------------------- \n" ) # -------------------------------------- Setup protocol ---------------------------------------- print("Setup sub-protocol: \n") # 2 # receive data data = self.connection.recv(4096) # deserialize data payload = pickle.loads(data) # Hybrid decryption of AES and RSA client's key k, self.public_client_key = hybrid_decryption(payload, self.private_key) print(f"[RECEIVED] Client's AES key: \n{k}\n") print(f"[RECEIVED] Client's public key: \n{self.public_client_key}\n") # Create session id and digital signature using private merchant RSA key session_id = utils.get_session_id() client_signature = utils.proceed_signature(session_id, self.private_key) print(f"[CREATE] Session id: \n{session_id}\n") print(f"[CREATE] Client signature: \n{client_signature}\n") # Encrypt data with AES key k = utils.generate_k() encrypted_session_id = utils.aes_encryption(k, session_id) encrypted_client_signature = utils.aes_encryption(k, client_signature) # Encrypt AES key with client's RSA public key encrypted_k = utils.rsa_encryption( k, RSA.importKey(self.public_client_key)) # Send payload to client prepared_payload = { "session_id": encrypted_session_id, "sid_signature": encrypted_client_signature, "k_encryption": encrypted_k } print(f"[SENT] Encrypted session id: \n{encrypted_session_id}\n") print( f"[SENT] Encrypted client signature: \n{encrypted_client_signature}\n" ) self.connection.send(pickle.dumps(prepared_payload)) # ---------------------------------- Exchange protocol ----------------------------------------- print( "\n -------------------------------------------------------------------------------------------- \n" ) print("Exchange protocol:\n") # receive data data = self.connection.recv(4096) # deserialize data second_payload = pickle.loads(data) # decrypt pm_po_key = utils.rsa_decryption(second_payload["pm_po_key"], self.private_key) pm_po = utils.aes_decryption(pm_po_key, second_payload["pm_po"]) # deserialize PM, PO loaded_pm_po = pickle.loads(pm_po) pm, po = loaded_pm_po[0], loaded_pm_po[1] print(f"[RECEIVED] PM: \n{pm}\n") print(f"[RECEIVED] PO: \n{po}\n") # verify signature if utils.verify_signature( pickle.dumps( [po["OrderDesc"], po["SID"], po["Amount"], po["NC"]]), RSA.importKey(self.public_client_key), po["SigC"]): # 4. # Create signature for pg using merchant private key (SigM(SID, Amount, PubKC)) merchant_signature = utils.proceed_signature( pickle.dumps([po["SID"], po["Amount"], self.public_client_key]), self.private_key) print(f"[CREATE] Merchant signature: \n{merchant_signature}\n") # Encrypt data (PM, SigM) and AES symmetric key k = utils.generate_k() encrypted_pm = utils.aes_encryption( k, pickle.dumps([pm, merchant_signature])) encrypted_pm_k = utils.rsa_encryption(k, self.pg_public_key) # Prepare payload prepared_pg_payload = { "encrypted_pm": encrypted_pm, "encrypted_pm_k": encrypted_pm_k } # Connecting to PG server self.pg_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.pg_socket.connect(("127.0.0.1", 3001)) # Send data to PG (PM + SigM(Sid, PubKC, Amount)) print( f"[SENT] Encrypted PM + SigM(Sid, PubKC, Amount): \n{encrypted_pm}\n" ) self.pg_socket.send(pickle.dumps(prepared_pg_payload)) # 5 # Receive data from PG (Resp, Sid, SigPG(Resp, Sid, Amount, NC)) data = self.pg_socket.recv(4096) pg_payload = pickle.loads(data) decrypted_pg_key = utils.rsa_decryption(pg_payload[1], self.private_key) decrypted_pg_payload = utils.aes_decryption( decrypted_pg_key, pg_payload[0]) deserialized_pg_payload = pickle.loads(decrypted_pg_payload) print( f"[RECEIVED] Resp, Sid, SigPG(Resp, Sid, Amount, NC): \n{deserialized_pg_payload}\n" ) # 6 # Verify PG signature and session id. if session_id == deserialized_pg_payload["SID"]: if utils.verify_signature( pickle.dumps([ deserialized_pg_payload["Resp"], po["SID"], po["Amount"], po["NC"] ]), self.pg_public_key, deserialized_pg_payload["SigPG"]): # Encrypt data (Resp, Sid, SigPG(Resp, Sid, Amount, NC)) with client's public key k = utils.generate_k() encrypted_merchant_payload = utils.aes_encryption( k, decrypted_pg_payload) encrypted_merchant_key = utils.rsa_encryption( k, RSA.importKey(self.public_client_key)) prepared_payload = { "encrypted_payload": encrypted_merchant_payload, "encrypted_key": encrypted_merchant_key } print( f"[SENT] Resp, Sid, SigPG(Resp, Sid, Amount, NC): \n{prepared_payload}\n" ) self.connection.send(pickle.dumps(prepared_payload)) else: print(f"[ERROR] Invalid signature") exit(2) else: print(f"[ERROR] Invalid session id") exit(1) else: print("[ERROR] Invalid signature") exit(0) self.connection.close()
def add_coins(request): """ Add Pinna coins to the current user's account """ session = utils.check_auth_token(request) if not session: return utils.invalid_auth_response() coins = request.DATA.get('coins', None) purchase_data = request.DATA.get('purchase_data', None) signature = request.DATA.get('signature', None) if not (coins and purchase_data and signature): msg = "Missing: " misses = [] if not coins: misses.append("coins") if not purchase_data: misses.append("purchase_data") if not signature: misses.append("signature") msg += ",".join(misses) return utils.failed_response(msg, "empty_fields") try: json_data = json.loads(purchase_data) except: msg = "Invalid purchase_data" return utils.failed_response(msg, "invalid_purchase_data") if not utils.verify_signature(purchase_data, signature): msg = "Signature does not match" return utils.failed_response(msg, "signature_not_match") order_id = json_data.get('orderId', '') date = datetime.fromtimestamp(json_data.get('purchaseTime')/1000) state = json_data.get('purchase_state', 1) try: PinnaOrder.objects.get(pk=order_id) msg = "The order already existed" return utils.failed_response(msg, "order_existed") except PinnaOrder.DoesNotExist: order = None try: order = PinnaOrder.objects.create(order_id=order_id, user=session.user, purchase_state=state, purchase_time=date, purchase_data=purchase_data) session.user.profile.amount += int(coins) session.user.profile.save() msg = "%s PINNA coins were added to the user account" %coins return utils.successful_response(msg, "ok", amount=session.user.profile.amount) except: if order: order.delete() msg = "Can't add PINNA coins to the user account" return utils.failed_response(msg, "failed")
def run(self): # -------------------------------------- Exchange protocol ------------------------------------------------ print("\nExchange protocol: \n") data = self.connection.recv(4096) payload = pickle.loads(data) # Decrypt PM from merchant decrypted_pm_key = utils.rsa_decryption(payload["encrypted_pm_k"], self.private_key) decrypted_pm = utils.aes_decryption(decrypted_pm_key, payload["encrypted_pm"]) deserialized_pm = pickle.loads( decrypted_pm) # contains PM, merchant signature. # Decrypt PI, SigC(PI) decrypted_pi_key = utils.rsa_decryption( deserialized_pm[0]["encrypted_key"], self.private_key) decrypted_pi = utils.aes_decryption( decrypted_pi_key, deserialized_pm[0]["encrypted_data"]) # PI pi = pickle.loads(decrypted_pi)[0] # SigC(PI) pi_client_signature = pickle.loads(decrypted_pi)[1] # Decrypted merchant signature SigM(Sid, PubKC, Amount) decrypted_merchant_signature = deserialized_pm[1] print(f"[RECEIVED] PI: \n{pi}\n") print(f"[RECEIVED] SigC(PI): \n{pi_client_signature}\n") print( f"[RECEIVED] SigM(Sid, PubKC, Amount): \n{decrypted_merchant_signature}\n" ) self.get_merchant_public_key() # Verify merchant's signature SigM(Sid, Amount, PubKC) if utils.verify_signature( pickle.dumps([pi["SID"], pi["Amount"], pi["PubKC"]]), self.merchant_public_key, decrypted_merchant_signature): # Verify client's signature SigC(PI) if utils.verify_signature(pickle.dumps(pi), RSA.importKey(pi["PubKC"]), pi_client_signature): response = None for i in range(len(bank)): item = bank[i] if item["CardN"] == pi["CardN"] and item["CardExp"] == pi["CardExp"] and \ item["CCode"] == pi["CCode"]: if pi["Amount"] <= item["Balance"]: item["Balance"] -= pi["Amount"] response = "Transaction accepted" bank[i] = item json.dump(bank, open("bank/accounts.json", "w")) else: response = "Transaction refused" # 5. # Creating PG signature SigPG(Resp, Sid, Amount, NC) pg_signature = utils.proceed_signature( pickle.dumps( [response, pi["SID"], pi["Amount"], pi["NC"]]), self.private_key) print( f"[CREATE] Payment gateway signature: \n{pg_signature}\n" ) # Preparing payload to be sent to merchant. prepared_payload = { "Resp": response, "SID": pi["SID"], "SigPG": pg_signature } # Hybrid encryption using merchant's public key k = utils.generate_k() encrypted_payload = utils.aes_encryption( k, pickle.dumps(prepared_payload)) encrypted_payload_key = utils.rsa_encryption( k, self.merchant_public_key) # Send data to merchant (Resp, Sid, SigPG(Resp, Sid, Amount, NC)) print( f"[SENT] Resp, Sid, SigPG(Resp, Sid, Amount, NC): " f"\n{pickle.dumps([encrypted_payload_key, encrypted_payload])}\n" ) self.connection.send( pickle.dumps( [encrypted_payload, encrypted_payload_key])) else: print(f"[ERROR] Invalid signature") exit(1) else: print(f"[ERROR] Invalid signature") exit(0) self.connection.close()
def connect_to_merchant(self, host, port): self.socket.connect((host, port)) # -------------------------------------- Setup protocol ------------------------------------------- # 1 self.get_merchant_public_key() # Encrypt client key with AES symmetric key + AES symmetric key encrypted with merchant rsa public key payload = hybrid_encryption(self.public_key, self.merchant_public_key) self.socket.send(pickle.dumps(payload)) # Received data from Merchant. (Session id and SigM(Sid)) data = self.socket.recv(8192) payload = pickle.loads(data) encrypted_aes_key = payload['k_encryption'] decrypted_aes_key = utils.rsa_decryption(encrypted_aes_key, self.private_key) self.session_id = utils.aes_decryption(decrypted_aes_key, payload['session_id']) self.session_signature = utils.aes_decryption(decrypted_aes_key, payload['sid_signature']) if utils.verify_signature(self.session_id, self.merchant_public_key, self.session_signature): print(f"[RECEIVED] Session id: \n{self.session_id}\n") print( f"[RECEIVED] Session signature: \n{self.session_signature}\n") else: print("[ERROR] Invalid signature") exit(0) # ------------------------------------------- Exchange ------------------------------------------- self.get_pg_public_key() nonce = random.getrandbits(16) order_description = "Omen by HP 15-dc0018nq" amount = 3000 # PO signature po_client_signature = utils.proceed_signature( pickle.dumps([order_description, self.session_id, amount, nonce]), self.private_key) # payment order po = { "OrderDesc": order_description, "SID": self.session_id, "Amount": amount, "NC": nonce, "SigC": po_client_signature } # payment information pi = { "CardN": "4034783123305160", "CardExp": "04/2025", "CCode": "627", "SID": self.session_id, "Amount": amount, "PubKC": self.public_key, "NC": nonce, "M": "Amazon" } print(f"[CREATE] PO: \n{po}\n") print(f"[CREATE] PI: \n{pi}\n") # PI client signature pi_client_signature = utils.proceed_signature(pickle.dumps(pi), self.private_key) print(f"[CREATE] PI Client Signature: \n{pi_client_signature}\n") # Encrypt PI, SigC(PI) with PG RSA public key k = utils.generate_k() encrypted_pi = utils.aes_encryption( k, pickle.dumps([pi, pi_client_signature])) encrypted_key = utils.rsa_encryption(k, self.pg_public_key) pm = { "encrypted_data": encrypted_pi, # encrypted_data = PI, SigC(PI) "encrypted_key": encrypted_key } print(f"[CREATE] PM: \n{pm}\n") # Encrypt PM, PO with M rsa public key k = utils.generate_k() encrypted_pm_po = utils.aes_encryption(k, pickle.dumps([pm, po])) encrypted_pm_po_key = utils.rsa_encryption(k, self.merchant_public_key) payload = {"pm_po": encrypted_pm_po, "pm_po_key": encrypted_pm_po_key} # 3. print(f"[SENT] PM, PO: \n{payload}\n") self.socket.send(pickle.dumps(payload)) # 6. # Receive payload Resp, Sid, SigPG(Resp, Sid, Amount, NC) data = self.socket.recv(4096) payload = pickle.loads(data) print( f"[RECEIVED] Resp, Sid, SigPG(Resp, Sid, Amount, NC): \n{payload}\n" ) # Decrypt data decrypted_payload_key = utils.rsa_decryption(payload["encrypted_key"], self.private_key) decrypted_payload = pickle.loads( utils.aes_decryption(decrypted_payload_key, payload["encrypted_payload"])) # Verify signature and session id if self.session_id == decrypted_payload["SID"]: if utils.verify_signature( pickle.dumps([ decrypted_payload["Resp"], self.session_id, pi["Amount"], pi["NC"] ]), self.pg_public_key, decrypted_payload["SigPG"]): print( f"[RECEIVED] Response of transaction: \n{decrypted_payload['Resp']}\n" ) self.socket.close() else: print(f"[ERROR] Invalid signature") else: print(f"[ERROR] Invalid session id")
def login(self, message): if self.state != LOGIN: logger.warning("Invalid State") return False logger.info(f"Loging in") data = message.get("data", None) self.state = LOGIN_FINISH status = False # status = False -> if login wasn't a success if AUTH_TYPE == AUTH_MEM: new_otp = base64.b64decode(data["otp"].encode()) current_otp_client = digest(new_otp, "SHA256") message = { "type": "ERROR", "message": "Invalid credentials for logging in" } if self.current_otp == current_otp_client: # success login status = True if self.clear_credentials: logger.info( "Clearing old credentials and saving new ones.") self.current_otp_index = self.new_index + 1 self.current_otp_root = self.new_root new_otp = self.new_otp with open(f"credentials/{self.user_id}_index", "wb") as file: file.write(f"{self.current_otp_index - 1}".encode()) with open(f"credentials/{self.user_id}_root", "wb") as file: file.write(self.current_otp_root) with open(f"credentials/{self.user_id}_otp", "wb") as file: file.write(new_otp) logger.info( "User logged in with success! Credentials updated.") else: logger.info( "User not logged in! Wrong credentials where given.") elif AUTH_TYPE == AUTH_CC: cc_certificate = certificate_object( base64.b64decode(data["certificate"].encode())) signed_nonce = base64.b64decode(data["sign_nonce"].encode()) certificates = load_certificates("cc_certificates/") chain = [] chain_completed = construct_certificate_chain( chain, cc_certificate, certificates) if not chain_completed: error_message = "Couldn't complete the certificate chain" logger.warning(error_message) message = {"type": "ERROR", "message": error_message} status = False else: valid_chain, error_messages = validate_certificate_chain(chain) if not valid_chain: logger.error(error_messages) message = {"type": "ERROR", "message": error_messages} status = False else: status = verify_signature(cc_certificate, signed_nonce, self.nonce) if status: oid = ObjectIdentifier( "2.5.4.5") # oid of citizens card's CI (civil id) self.user_id = cc_certificate.subject.get_attributes_for_oid( oid)[0].value logger.info("User logged in with success") message = {"type": "OK"} # Access verification if status: access_result = self.check_access() if not access_result[0]: logger.warning(access_result[1]) status = False message = {"type": "ERROR", "message": access_result[1]} else: message = {"type": "OK"} logger.info(access_result[1]) self._send(message) return status
def server_init(self): # Generating server nonce self.generate_server_nonce() # Reading from server certificate to send it to client with open (self.servercert, 'r') as data: server_certificate = data.read() # Generating the message for client, using | as delimiter, with the nonce, the acknowledgement # of the cipher and the server certificate self.serverinit = 'ServerInit' + '|' + self.server_nonce + '|' + self.client_cipher + '|' + server_certificate if self.authentication == 'ClientAuth': self.serverinit = self.serverinit + '|' + 'CertReq' self.clientsock.send(self.serverinit) # We store serverinit without the cipher for the checksum message # (it's in the slide, but I wouldn't do this) self.serverinit = 'ServerInit' + '|' + self.server_nonce + '|' + server_certificate if self.authentication == 'ClientAuth': self.serverinit = self.serverinit + '|' + 'CertReq' # ------------------------------------------------------------------------------ # Getting response from client to go on with the handshake procedure client_response = self.clientsock.recv(8192) print '-------------------------------\n' print client_response print '\n-------------------------------' # Splitting the message and checking if it is the expected type splitted_response = client_response.split('|') if not splitted_response[0] == 'ClientKex': self.clientsock.close() raise Exception('Unexpected message type') rsa_encrypted_pms = splitted_response[1] # If the authentication type requires the client cert: if self.authentication == 'ClientAuth': self.client_certificate = splitted_response[3] nonce_signature = splitted_response[4] # Checking client certs if not self.certificate_is_valid(self.client_certificate): self.clientsock.send('Invalid certificate') raise Exception('Invalid certificate') self.server_connection.close() # Checking if the received nonce is valid to prevent attacks client_pubkey = utils.read_pubkey_from_pem(self.client_certificate) if not utils.verify_signature(client_pubkey, nonce_signature, self.server_nonce + rsa_encrypted_pms): self.clientsock.send('Server nonce verification failed') raise Exception('Server nonce verification failed') self.server_connection.close() # Getting server's private key and decrypting the pms sent by the server # and encrypted with the server pubkey with open (self.serverprivatekey, 'r') as server_key: server_key_data=server_key.read() privkey = utils.read_privkey_from_pem(server_key_data) pre_master_secret = utils.decrypt_rsa(privkey, rsa_encrypted_pms) # Generating key couple key_1_payload = binascii.unhexlify(self.client_nonce + self.server_nonce + '00000000') key_2_payload = binascii.unhexlify(self.client_nonce + self.server_nonce + '11111111') self.key_1 = utils.create_hmac(pre_master_secret, key_1_payload) self.key_2 = utils.create_hmac(pre_master_secret, key_2_payload) # Check if message_checksum is legit, terminate and send back error to client # otherwise message_checksum = splitted_response[2] message_control = utils.create_hmac( self.key_2, self.clientinit + self.serverinit ) if message_checksum != message_control: self.clientsock.send('Wrong message checksum') raise Exception('Wrong message checksum') self.clientsock.close() # Generate check for last msg and send it back if self.authentication == 'ClientAuth': _verifymessage = client_response.replace('|' + splitted_response[4], '') else: _verifymessage = client_response server_message_checksum = utils.create_hmac(self.key_2, _verifymessage) self.clientsock.send(server_message_checksum) self.handshake_done = True
def verify_transaction(transaction): """Validates a transaction's signature and returns whether its content matches its hash""" return utils.verify_signature( transaction.get_signature_contents(**transaction.signature_kwargs), transaction.signature, transaction.node.public_key)
def update(request): """ Handles update request from the master update webhook """ logger = utils.CloudLogger().log_request(request) try: # 1) Validate the request if 'X-Lapdog-Signature' not in request.headers: return { 'error': 'Missing Signature', 'message': "The required X-Lapdog-Signature header was not provided" }, 400 signature = request.headers['X-Lapdog-Signature'] data = request.get_json() if not isinstance(data, dict): return ( { 'error': "Bad Request", 'message': ("No data was provided" if data is None else "Expected JSON dictionary in request body") }, 400 ) result = utils.verify_signature( bytes.fromhex(signature), json.dumps(data).encode(), utils.UPDATE_KEY_PATH, _is_blob=False ) if not result: return { 'error': 'Bad Signature', 'message': "The provided signature for this update was invalid" }, 403 if not ('tag' in data and 'url' in data and 'random' in data and 'timestamp' in data): return { 'error': 'Missing parameters', 'message': 'Missing one or more of the required parameters "tag", "url", "timestamp", and "random"', }, 400 if (datetime.datetime.utcnow().timestamp() - data['timestamp']) > 300: return { 'error': 'Expired', 'message': 'This update signature has expired' }, 403 # 2) Build pipeline to boot update VM regions = utils.enabled_regions() if len(regions) < 1: return { 'error': 'No regions', 'message': 'There are no regions enabled in this project' }, 503 pipeline = { 'pipeline': { 'actions': [ { 'imageUri': 'gcr.io/broad-cga-aarong-gtex/self_update:' + utils.UPDATE_IMAGE_TAG, 'commands': ['/update.sh'], 'environment': { 'LAPDOG_PROJECT': os.environ.get('GCP_PROJECT'), 'LAPDOG_LOG_PATH': "gs://{bucket}/update-logs/{time}-{tag}/".format( bucket=utils.ld_meta_bucket_for_project(), tag=data['tag'], time=int(time.time()) ), 'LAPDOG_CLONE_URL': data['url'], 'LAPDOG_NAMESPACE': utils.getblob( 'gs://{bucket}/resolution'.format( bucket=utils.ld_meta_bucket_for_project(os.environ.get('GCP_PROJECT')) ) ).download_as_string().decode(), 'LAPDOG_TAG': data['tag'] } } ], 'resources': { 'regions': regions, 'virtualMachine': { 'machineType': 'f1-micro', 'preemptible': False, 'labels': { 'lapdog-execution-role': 'self-update', }, 'serviceAccount': { 'email': 'lapdog-update@{}.iam.gserviceaccount.com'.format(os.environ.get('GCP_PROJECT')), 'scopes': [ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/devstorage.read_write", "https://www.googleapis.com/auth/genomics" ] }, 'bootDiskSizeGb': 20, 'network': { 'network': 'default', 'usePrivateAddress': False } } }, } } # 3) Launch pipeline papi_url = 'https://lifesciences.googleapis.com/v2beta/projects/{}/locations/{}/pipelines:run'.format( os.environ.get('GCP_PROJECT'), regions[0] ) logger.log( "Launching PAPIv2 pipeline", pipeline=pipeline['pipeline'], url=papi_url, severity='NOTICE' ) response = utils.generate_default_session( [ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/genomics" ] ).post( papi_url, headers={ 'Content-Type': 'application/json' }, json=pipeline ) try: if response.status_code == 200: return response.json()['name'], 200 return ( { 'error': 'Unable to start update', 'message': 'Google rejected the pipeline request (%d) : %s' % (response.status_code, response.text) }, 400 ) except: logger.log_exception("PAPIv2 request failed") return ( { 'error': 'Unable to start update', 'message': traceback.format_exc() }, 500 ) except: logger.log_exception() return { 'error': 'Unknown error', 'message': traceback.format_exc() }, 500