Beispiel #1
0
    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,)
Beispiel #2
0
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))
Beispiel #6
0
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)
Beispiel #7
0
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)
Beispiel #8
0
    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!")
Beispiel #11
0
 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)