Looking for help: how to verify if a Hive message is signed correctly in Python Beem. UPDATED!

avatar
(Edited)

The story so far.... my Python/Flask website now manages to fire up Hive Keychain thanks to help from @rishi556. I even manage to get the answer in the form of a json response back into the Python Flask back end:

As JSON that looks like this:

{
  "data": {
    "key": "posting",
    "message": "{\"signed_message\":{\"type\":\"login\",\"address\":\"brianoflondon\",\"page\":\"http://127.0.0.1:5000/podcaster/login\"},\"timestamp\":1613710433}",
    "method": "Posting",
    "request_id": 3,
    "type": "signBuffer",
    "username": "brianoflondon"
  },
  "error": null,
  "message": "Message signed succesfully.",
  "publicKey": "STM7B1eanwUQhXa8tdabTi2RxHnXWtyMBd6iJDZ3Z2QA6rKHQY2WJ",
  "request_id": 3,
  "result": "2031e828c6673b945a14489e23a90d5502238d56fb4df568e6ab88af703a9e3bba14ea410bed5afcb42b3d164c976a49645ee2848a8b65fbd9cc77cbc574ae2ffd",
  "success": true
}

Shhh don't tell anyone but right now the only bit my server looks at is the "success":true.

I've taken a look at the Beem Docs and even searched all of github, but there's minimal explanation here.

Can anyone else help with the python to do this?

Thanks in wondrous anticipation! I fully intent to make a very simple, reference and open source implementation of this kind of Hive Keychain interaction with Python Flask.

And huge thanks again to @crokkon:

I will publish the entire system including the javascript and the server side code when I get a chance.

#!/usr/bin/python
from beemgraphenebase.account import PublicKey
from beemgraphenebase.ecdsasig import verify_message
from binascii import hexlify, unhexlify

def validate_hivekeychain_ans(ans):
    """ takes in the answer from hivekeychain and checks everything """
    """ http://bit.ly/keychainpython """

    acc_name = ans['data']['username']
    pubkey = PublicKey(ans['publicKey'])
    enc_msg = ans['data']['message']
    signature = ans['result']

    msgkey = verify_message(enc_msg, unhexlify(signature))
    pk = PublicKey(hexlify(msgkey).decode("ascii"))
    if str(pk) == str(pubkey):
        print("SUCCESS: signature matches given pubkey")
        acc = Account(acc_name)
        match = False, 0
        for key in acc['posting']['key_auths']:
            match = match or ans['publicKey'] in key
        if match:
            print('Matches public key from Hive')
            mtime = json.loads(enc_msg)['timestamp']
            time_since = time.time() - mtime
            if time_since < 30:
                return True , time_since
            else:
                print("ERROR: answer took too long.")
    else:
        print("ERROR: message was signed with a different key")
        return False, 0

brianoflondon hive footer.png

Posted with STEMGeeks



0
0
0.000
13 comments
avatar

Not sure why you are using Flask, but if you want to use a python/django implementation.

We do this in the Holybread code and I could give you access to the Github rep, for you to look at.

Not sure what you are not receiving back and what you are trying to do.

Is it just simple logins?

Posted Using LeoFinance Beta

0
0
0.000
avatar

I'm pretty sure flask and Django would be very similar in this.

I just want to confirm the user by checking they can sign a message with their posting key.

This is my github account : https://github.com/brianoflondon

0
0
0.000
avatar
(Edited)

.

0
0
0.000
avatar

You are a wonder!

I've added this little bit which, if I'm doing this right, grabs the public key direct from Hive for this account and compares it to the one returned from the Keychain response in the client.

    acc = Account(acc_name)
    match = False
    for key in acc['posting']['key_auths']:
        match = match or ans['publicKey'] in key
    if match:
        print('Matches public key from Hive')

And here's the full script.

import json
from beemgraphenebase.account import PublicKey
from beemgraphenebase.ecdsasig import verify_message
from binascii import hexlify, unhexlify
from beem.account import Account


ans = {'data':{'key': 'posting','message': '{"signed_message":{"type":"login","address":"brianoflondon","page":"http://127.0.0.1:5000/podcaster/login"},"timestamp":1613710433}', 'method': 'Posting', 'request_id': 3, 'type': 'signBuffer', 'username': 'brianoflondon'}, 'error': None, 'message': 'Message signed succesfully.', 'publicKey': 'STM7B1eanwUQhXa8tdabTi2RxHnXWtyMBd6iJDZ3Z2QA6rKHQY2WJ', 'request_id': 3, 'result': '2031e828c6673b945a14489e23a90d5502238d56fb4df568e6ab88af703a9e3bba14ea410bed5afcb42b3d164c976a49645ee2848a8b65fbd9cc77cbc574ae2ffd', 'success': True}
ansfail = {'data':{'key': 'posting','message': '{"signed_message":{"type":"login","address":"brianoflondon","page":"http://127.0.0.1:5000/podcaster/login"},"timestamp":1613710433}', 'method': 'Posting', 'request_id': 3, 'type': 'signBuffer', 'username': 'brianoflondon'}, 'error': None, 'message': 'Message signed succesfully.', 'publicKey': 'STM7B1eanwUQhXa8tdabTi2RxHnXWtyMBd6iJDZ3Z2QA6rKHQY2WJ', 'request_id': 3, 'result': '2031e828c6673b945a14489e23a90d5502238d56fb4df568e6ab88af703a9e3bba14ea410bed5afcb42b3d164c976a49645ee2848a8b65fbd9cc77cbc574ae2ffe', 'success': True}

# with open("msg.txt") as f:
#     msg = json.loads(f.read())

acc_name = ans['data']['username']
pubkey = PublicKey(ans['publicKey'])
enc_msg = ans['data']['message']
signature = ans['result']

msgkey = verify_message(enc_msg, unhexlify(signature))
pk = PublicKey(hexlify(msgkey).decode("ascii"))
if str(pk) == str(pubkey):
    print("SUCCESS: signature matches given pubkey")
    acc = Account(acc_name)
    match = False
    for key in acc['posting']['key_auths']:
        match = match or ans['publicKey'] in key
    if match:
        print('Matches public key from Hive')

else:
    print("ERROR: message was signed with a different key")
0
0
0.000
avatar

I added one more enhancement to check if the answer is older than 30 seconds... Thank you so much! This is a very important part of what I'm doing.

I absolutely will make a very clear post about this soon.

0
0
0.000
avatar
(Edited)

.

0
0
0.000
avatar

Hmmmm I'm so used to having Keychain unlocked I'll try locking it and perhaps upping the timeout to 5 mins. I doubt that replay attacks will be a huge issue!

Posted using Dapplr

0
0
0.000
avatar

Congrats, you were upvoted from this account because you were in Top 25 engagers yesterday on STEMGeeks .
You made a total of 3 comments and talked to 2 different authors .
Your rank is 3 .
For more details about this project please read here - link to announcement post
You can also delegate and get weekly payouts.

0
0
0.000
avatar

Congrats, you were upvoted from this account because you were in Top 25 engagers yesterday on STEMGeeks .
You made a total of 1 comments and talked to 1 different authors .
Your rank is 4 .
For more details about this project please read here - link to announcement post
You can also delegate and get weekly payouts.

0
0
0.000
avatar

Can we build an encrypted chat like whatsapp based on memo features ?

0
0
0.000
avatar

Congratulations @brianoflondon! You have completed the following achievement on the Hive blockchain and have been rewarded with new badge(s) :

You distributed more than 42000 upvotes.
Your next target is to reach 43000 upvotes.

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

Check out the last post from @hivebuzz:

Hive Tour Update - Communities
Hive Tour Update - Advanced posting
0
0
0.000