def recover_message( message: bytes, signature: str, is_deprecated_mode: bool = False ) -> Tuple[Address, ...]: """ Recover the addresses from the hash. :param message: the message we expect :param signature: the transaction signature :param is_deprecated_mode: if the deprecated signing was used :return: the recovered addresses """ if is_deprecated_mode: assert len(message) == 32, "Message must be hashed to exactly 32 bytes." address = Account.recoverHash( # pylint: disable=no-value-for-parameter message_hash=message, signature=signature ) else: signable_message = encode_defunct(primitive=message) address = Account.recover_message( # pylint: disable=no-value-for-parameter signable_message=signable_message, signature=signature ) return (address,)
def signup(): signed_public_key = '0' try: addr = request.get_json()["address"] if isValidEthereumAddress(addr) is False: raise InvalidUsage('message', status_code=400) old_nonce = g.get('db').getObserverNonceBytes(addr) email = request.get_json()["email"] signed_message = request.get_json()["signedMessage"] payload = request.get_json()["secret"] except Exception as e: print(e) raise InvalidUsage('message', status_code=400) try: if (isValidEmailAddress(email) is False or isValidSecret(payload) is False): raise InvalidUsage('message', status_code=400) nonce = old_nonce.encode('utf-8') g.get('db').updateObserverNonceBytes(nonce='NULL', public_address=addr) message_hash = sha3.keccak_256(nonce).hexdigest() message_hash = encode_defunct(hexstr=message_hash) except Exception as e: print(e) raise InvalidUsage('message', status_code=500) try: signed_public_key = Account.recover_message(message_hash, signature=signed_message) except Exception as e: print(e) print('message could not be checked') try: if signed_public_key.lower() == addr.lower(): email_from_addr = g.get('db').selectEmailFromObserverAddress(addr) if email_from_addr == None or email_from_addr == '' or email_from_addr == b'NULL': if email != None or email != 'null' or email != 'NULL' or email != '': try: g.get('db').updateObserverEmail(email, addr) message_text = 'Save this email: TruSat account recovery info for ' + email + '\n\n' + \ 'To log into TruSat, you\'ll need your password AND this secret code:\n\n' + payload + \ '\n\nThis email is the only time we can send you this code. TruSat cannot reset your password for you. Please save this email forever and make a note of the password you used.\n\n' + \ 'Login here: trusat.org/login\n\n' + \ 'Why do we do it this way? Read more (trusat.org/faq)\n\n' + \ 'Questions? Please email: [email protected]' data = {"from": "TruSat Help <" + MAILGUN_EMAIL_ADDRESS + ">", "to": [email], "subject": "TruSat - Save this email: Recovery Info", "text": message_text} response = requests.post( "https://api.mailgun.net/v3/beta.trusat.org/messages", auth=("api", MAILGUN_API_KEY), data=data ) if response.status_code != 200: print("Email failed to send.") raise InvalidUsage('message', status_code=500) return {'result': True} except Exception as e: print(e) raise InvalidUsage('message', status_code=500) except Exception as e: print(e) else: raise InvalidUsage('message', status_code=400) raise InvalidUsage('message', status_code=500)
def on_post(self, req: falcon.Request, res: falcon.Response, annotation_id=None): logger.debug(f"Received annotation {req.media}") message = deepcopy(req.media) del message["proof"]["jws"] encoded_message = json.dumps(message, separators=(",", ":")) signed_message = encode_defunct(text=encoded_message) raw_signature = remove_0x_prefix(req.media["proof"]["jws"]) request_issuer = req.media["issuer"].split(":")[2] signature_issuer = Account.recover_message( signable_message=signed_message, vrs=( int(raw_signature[128:130], 16), # 0x1c or bust int(raw_signature[0:64], 16), int(raw_signature[64:128], 16), ), ) if request_issuer.lower() != signature_issuer.lower(): logger.debug( f"Bad signature issuer: {request_issuer} != {signature_issuer}" ) res.status = falcon.HTTP_BAD_REQUEST return # create annotation DB object annotation = Annotation.from_dict(req.media) session: Session = req.context["session"] session.add(annotation) # publish annotation on IPFS and add subject ID logger.debug("Adding and pinning annotation on TheGraph") try: response = requests.post( THEGRAPH_IPFS_ENDPOINT, files={"batch.json": json.dumps(req.media).encode("utf-8")}, timeout=5, ) except (ConnectionError, ReadTimeout) as e: logger.error(f"Connection to TheGraph timed out: {e}") res.status = falcon.HTTP_FAILED_DEPENDENCY return if response.status_code != 200: logger.error( f"Publishing to TheGraph failed with response '{response.text}'" ) res.status = falcon.HTTP_FAILED_DEPENDENCY return try: ipfs_hash = response.json()["Hash"] except (json.JSONDecodeError, KeyError): logger.error( f"TheGraph returned an invalid JSON response: '{response.text}'" ) res.status = falcon.HTTP_FAILED_DEPENDENCY return annotation.subject_id = ipfs_hash logger.debug("Pinning annotation to Pinata") try: response = requests.post( PINATA_ENDPOINT, headers={ "pinata_api_key": PINATA_API_KEY, "pinata_secret_api_key": PINATA_SECRET_API_KEY, }, json={"hashToPin": ipfs_hash}, timeout=5, ) except (ConnectionError, ReadTimeout) as e: # continue from here because Pinata is not a required dependency logger.error(f"Connection to Pinata timed out: {e}") if response.status_code != 200: logger.error( f"Pinning on Pinata failed with response '{response.text}'") session.add(annotation) res.body = json.dumps({"ipfsHash": ipfs_hash}) # check whether we should publish a new batch logger.debug("Running batch check background job") batch_publish.delay()
def signer(self): """ Get the signing account for this transaction """ return Account.recover_message(self.msg, vrs=self.signature)
def fromSignatureAndNonce(self, signature, nonce): message = encode_defunct(text=("Ethgarden login nonce: "+str(nonce))) return(Account.recover_message(message, signature=signature))
def login(): signed_public_key = '0' response_message = b'' try: addr = request.get_json()["address"] old_nonce = g.get('db').getObserverNonceBytes(addr) signed_message = request.get_json()["signedMessage"] except Exception as e: print(e) raise InvalidUsage('Address or signed message missing', status_code=400) if isValidEthereumAddress(addr) is False: raise InvalidUsage('Address is not valid', status_code=400) nonce = old_nonce.encode('utf-8') g.get('db').updateObserverNonceBytes(nonce='NULL', public_address=addr) message_hash = sha3.keccak_256(nonce).hexdigest() message_hash = encode_defunct(hexstr=message_hash) try: signed_public_key = Account.recover_message(message_hash, signature=signed_message) except Exception as e: print(e) print('message could not be checked') try: email = request.get_json()["email"] secret = request.get_json()["secret"] except Exception as e: print(e) email = None secret = None if (email is not None and isValidEmailAddress(email) is False or secret is not None and isValidSecret(secret) is False): raise InvalidUsage('Email or secret are not valid', status_code=400) if signed_public_key.lower() == addr.lower(): email_from_addr = g.get('db').selectEmailFromObserverAddress(addr) if email_from_addr == None or email_from_addr == '' or email_from_addr == b'NULL': if email != None: try: g.get('db').updateObserverEmail(email, addr) email_status = google_email.send_email(email, secret) if email_status == False: raise InvalidUsage('Email failed to send', status_code=500) return {'result': True} except Exception as e: print(e) raise InvalidUsage('Email failed', status_code=500) encoded_jwt = encode_jwt(addr.lower()) g.get('db').updateObserverJWT(encoded_jwt, '', addr) frontend_exp = time.time() + 604800 response_message += b'{ "address": "' + bytes( addr.lower(), 'utf-8') + b'", "exp": ' + bytes( str(frontend_exp), 'utf-8') + b' } ' @after_this_request def add_header(response): response.set_cookie( 'jwt', encoded_jwt.decode('utf-8'), max_age=604800, secure=True, httponly=True ) #, samesite="Strict") #secure=True, httponly=True, samesite="Strict") return response return response_message else: print("Login Failed") raise InvalidUsage('Login failed', status_code=400)
def authorize(mode): """ @route('/api/v1/authorize', methods=['GET', 'POST']) Authorization server modifed for DID-SIOP """ # to manage wrong login ot user rejection, qr code exit, any other reject if 'reject' in request.values: logging.warning('reject') session.clear() return oauth2.authorization.create_authorization_response( grant_user=None) # get client Identity from API credentials user = current_user() client_id = request.args.get('client_id') client = OAuth2Client.query.filter_by(client_id=client_id).first() # if user not logged (Auth server), then to log it in if not user: logging.info('user not registered') return redirect(url_for('oauth_login', next=request.url)) # if user is already logged we check the request and prepare the "OIDC consent screen" if request.method == 'GET': try: grant = oauth2.authorization.validate_consent_request( end_user=user) except OAuth2Error as error: logging.error('OAuth2Error') return jsonify(dict(error.get_body())) # configure consent screen : authorize.html consent_screen_scopes = [ 'openid', 'address', 'profile', 'about', 'birthdate', 'resume', 'proof_of_identity', 'email', 'phone', 'did_authn' ] checkbox = { key.replace(':', '_'): 'checked' if key in grant.request.scope.split() and key in client.scope.split() else "" for key in consent_screen_scopes } return render_template( 'did_oidc_authorize.html', **checkbox, ) # POST, call from consent view authorize.html # get credential from wallet credential = request.form['credential'] did = request.form['did'] # Verify signature of Identity with eth_sign method try: msg = encode_defunct(text=credential) signer = Account.recover_message(msg, signature=request.form['signature']) except: logging.error('signature invalid') return oauth2.authorization.create_authorization_response( grant_user=None) logging.info('signer = %s', signer) if signer != protocol.contractsToOwners('0x' + did.split(':')[3], mode): logging.error('signer is not wallet address, login rejected') return oauth2.authorization.create_authorization_response( grant_user=None) try: ns.add_vc(did, credential) except: logging.error('database locked, credential is not stored') # update scopes after user consent query_dict = parse_qs(request.query_string.decode("utf-8")) my_scope = "" for scope in query_dict['scope'][0].split(): if request.form.get(scope): my_scope = my_scope + scope + " " query_dict["scope"] = [my_scope[:-1]] # create a Oauth2Request with the updated scope in the query_dict req = OAuth2Request( "POST", request.base_url + "?" + urlencode(query_dict, doseq=True)) # send response return oauth2.authorization.create_authorization_response(grant_user=user, request=req)
def do_POST(self): response_body = b"" signed_public_key = '0' try: content_length = int(self.headers['Content-Length']) body = self.rfile.read(content_length) json_body = json.loads(body) except Exception as e: print(e) self.send_400() return ### GET NONCE ENDPOINT ### if self.path == "/getNonce": try: addr = json_body["address"] except Exception as e: print(e) self.send_400() return if isValidEthereumAddress(addr) is False: self.send_400() return try: email = json_body["email"] if isValidEmailAddress is False: self.send_400() return results = self.db.selectObserverAddressFromEmail(email) if len(results) == 42: self.send_200_JSON(json.dumps({})) return except Exception as e: print(e) pass try: public_address_count = self.db.getObserverCountByID( public_address=addr) except Exception as e: print(e) self.send_500() return random_number = str(secrets.randbits(256)) response_message = '{"nonce":\"%s\"}' % random_number if public_address_count[0] == None or public_address_count[0] == 0: # New User try: self.db.addObserver(addr, "NULL", 0, "NULL") self.db.updateObserverNonceBytes(nonce=random_number, public_address=addr) except Exception as e: print(e) self.send_500() return elif public_address_count[0] >= 1: # Old User try: self.db.updateObserverNonceBytes(nonce=random_number, public_address=addr) except Exception as e: print(e) self.send_500() return self.send_200_JSON(response_message) elif self.path == "/signup": try: addr = json_body["address"] if isValidEthereumAddress(addr) is False: self.send_400() return old_nonce = self.db.getObserverNonceBytes(addr) email = json_body["email"] signed_message = json_body["signedMessage"] payload = json_body["secret"] except Exception as e: print(e) self.send_400() return try: if (isValidEmailAddress(email) is False or isValidSecret(payload) is False): self.send_400() return nonce = old_nonce.encode('utf-8') self.db.updateObserverNonceBytes(nonce='NULL', public_address=addr) message_hash = sha3.keccak_256(nonce).hexdigest() message_hash = encode_defunct(hexstr=message_hash) except Exception as e: print(e) self.send_500() return try: signed_public_key = Account.recover_message( message_hash, signature=signed_message) except Exception as e: print(e) print('message could not be checked') try: if signed_public_key.lower() == addr.lower(): email_from_addr = self.db.selectEmailFromObserverAddress( addr) if email_from_addr == None or email_from_addr == '' or email_from_addr == b'NULL': if email != None or email != 'null' or email != 'NULL' or email != '': try: self.db.updateObserverEmail(email, addr) email_status = google_email.send_email( email, payload) if email_status == False: print("Email failed to send.") self.send_500() return self.send_200_JSON(json.dumps({'result': True})) return except Exception as e: print(e) self.send_500() return except Exception as e: print(e) else: self.send_400() return self.send_500() return ### LOGIN ENDPOINT ### elif self.path == "/login": try: addr = json_body["address"] old_nonce = self.db.getObserverNonceBytes(addr) signed_message = json_body["signedMessage"] except Exception as e: print(e) self.send_400() return if isValidEthereumAddress(addr) is False: self.send_400() return nonce = old_nonce.encode('utf-8') self.db.updateObserverNonceBytes(nonce='NULL', public_address=addr) message_hash = sha3.keccak_256(nonce).hexdigest() message_hash = encode_defunct(hexstr=message_hash) try: signed_public_key = Account.recover_message( message_hash, signature=signed_message) except Exception as e: print(e) print('message could not be checked') try: email = json_body["email"] secret = json_body["secret"] except Exception as e: print(e) email = None secret = None if (email is not None and isValidEmailAddress(email) is False or secret is not None and isValidSecret(secret) is False): self.send_400() return if signed_public_key.lower() == addr.lower(): email_from_addr = self.db.selectEmailFromObserverAddress(addr) if email_from_addr == None or email_from_addr == '' or email_from_addr == b'NULL': if email != None: try: self.db.updateObserverEmail(email, addr) email_status = google_email.send_email( email, secret) if email_status == False: self.send_500() return self.send_200_JSON(json.dumps({'result': True})) return except Exception as e: print(e) self.send_500() return encoded_jwt = encode_jwt(addr.lower()) self.db.updateObserverJWT(encoded_jwt, '', addr) response_message = b'{"jwt": "' response_message += encoded_jwt response_message += b'"} ' self.send_200_JSON2(response_message) else: print("Login Failed") self.send_400() return elif self.path == "/editProfile": try: user_jwt = json_body["jwt"] decoded_jwt = decode_jwt(user_jwt) public_address = decoded_jwt["address"] except Exception as e: print(e) self.send_400() return if isValidEthereumAddress(public_address) is False: self.send_400() return if self.db.getObserverJWT(public_address)[0].decode( "utf-8") == user_jwt: try: username = json_body["username"] if (username != "null" and username != None and isValidUserSetting(username)): self.db.updateObserverUsername(username, public_address) except Exception as e: print("Username not being updated") print(e) #try: # email = json_body["email"] # if isValidEmailAddress(email): # self.db.updateObserverEmail(email, public_address) #except Exception as e: # print("Email not being updated") # print(e) try: bio = json_body["bio"] if (bio != "null" and bio != None and isValidUserSetting(bio)): self.db.updateObserverBio(bio, public_address) except Exception as e: print("Bio not being updated") print(e) try: location = json_body["location"] if (location != "null" and location != None and isValidUserSetting(location)): self.db.updateObserverLocation(location, public_address) except Exception as e: print("Location not being updated") print(e) self.send_200_JSON(response_body) elif self.path == '/claimAccount': try: email = json_body['email'] except Exception as e: print(e) self.send_200_JSON(json.dumps({'result': False})) return if isValidEmailAddress(email) is False: self.send_400() return try: with open('unsafe_private.pem', 'r') as file: private_key = file.read() private_rsa_key = load_pem_private_key( bytes(private_key, 'utf-8'), password=None, backend=default_backend()) results = self.db.selectObserverAddressFromEmail(email) if results is not None: results = results.decode('utf-8') else: self.send_200_JSON(json.dumps({'result': False})) return old_password = self.db.selectObserverPasswordFromAddress( results) if old_password is not None: old_password = old_password.decode('utf-8') try: if decode_jwt(old_password): self.send_200_JSON(json.dumps({'result': True})) return except: print('User already claimed account.') number = str(secrets.randbits(64)) jwt_payload = { 'email': email, 'secret': number, 'exp': datetime.utcnow() + timedelta(minutes=30) } encoded_jwt = encode(jwt_payload, private_rsa_key, algorithm='RS256') self.db.updateObserverPassword(encoded_jwt.decode('utf-8'), results) email_status = google_email.send_recovery_email( email, 'http://trusat.org/claim/' + encoded_jwt.decode('utf-8')) if email_status == False: self.send_500() return else: self.send_200_JSON(json.dumps({'result': True})) return except Exception as e: print(e) self.send_500() return self.send_200_JSON(json.dumps({'result': False})) elif self.path == "/verifyClaimAccount": try: message_text = json_body["secret"] address = json_body["address"] user_jwt = json_body["jwt"] except Exception as e: print(e) self.send_400() return if (isValidEthereumAddress(address) is False or isValidSecret(message_text) is False): self.send_400() return #Lookup number and old address try: decoded_jwt = decode_jwt(user_jwt) secret = decoded_jwt["secret"] to = decoded_jwt["email"] old_address = self.db.selectObserverAddressFromPassword( user_jwt).decode('utf-8') if old_address is None: self.send_400() return #replace address encoded_jwt = encode_jwt(address) self.db.updateObserverAddress(address, old_address) email_status = google_email.send_email(to, message_text) if email_status == False: self.send_500() return self.db.updateObserverJWT(encoded_jwt, "", address) jwt_string = encoded_jwt.decode('utf-8') response_body = json.dumps({'jwt': jwt_string}) self.send_200_JSON(response_body) self.db.updateObserverPassword('NULL', address) except Exception as e: print(e) self.send_500() return elif self.path == "/submitObservation": try: user_jwt = json_body["jwt"] decoded_jwt = decode_jwt(user_jwt) user_addr = decoded_jwt["address"] except Exception as e: print(e) self.send_400() return if isValidEthereumAddress(user_addr) is False: self.send_400() return try: single = json_body["single"] except Exception as e: print(e) parsed_iod = [] try: multiple = json_body["multiple"] results = self.db.addObserverParsedIOD(multiple) if results is not False: (success, error_messages) = results else: self.send_500() return except Exception as e: print(e) self.send_500() return success_length = { 'success': success, 'error_messages': error_messages } self.send_200_JSON(json.dumps(success_length)) elif self.path == "/seesat": email_information = json_body["message"]["data"] email_history = urlsafe_b64decode(email_information).decode( 'utf-8') email_history = json.loads(email_history) print(email_history) print(google_email.get_email_history(email_history['historyId'])) self.send_204() else: self.send_response(404) self.end_headers() self.wfile.write(b'') return self.db.clean()
def test_signature_verification(message_encodings): account = Account.create() structured_msg = encode_structured_data(**message_encodings) signed = Account.sign_message(structured_msg, account.key) new_addr = Account.recover_message(structured_msg, signature=signed.signature) assert new_addr == account.address
from eth_account import Account from eth_account.messages import encode_defunct message = 'https://www.aztecprotocol.com/ignition/participant/0xb51da5f6a840098a2b78a381a2a9716ff1f112c1/?timestamp=1578775929139' hash = '0x09b6524742eab624e8aff260bf168b17d546429a7471ca43f860f7a1a59899d8' signature = '0x316c44c5db370af3cadde8101c298b6ff3bffb64147295d76446f12d2a623c9f59eec8834fd45c4bb2be950af2b5ea9db2813d1af35036866d3d035a086c844c1b' success = Account.recover_message(encode_defunct(text=message), signature=signature) == Account.recoverHash( hash, signature=signature) if success: print("Success! Verified Attestation!") else: print("WARNING! Could not verify Attestation!")
def recover_message(signature: Union[HexStr, str], message: str) -> str: message_hash = messages.encode_defunct(text=message) return Account.recover_message(message_hash, signature=signature)