Sign in Javascript validate in Beem! : Journal Entry for 2018 08(August) 06

in steemdev •  3 months ago

August 6th, 2018
sign-in-javascript-verify-in-beem.png

Validation of Signatures from Javascript in Beem

Make your signatures in javascript, and validate them in Beem. This is now used in Steemfiles as a login system. You can login to Steemfiles with any of your Steem keys and you will be authenticated as that Steem user. A session is signed and the session with signature is sent to the server. The private keys never leave your computer.

Deciding that transactions were a source of complexity, and it was enough that the user could sign a string, is what prompted me to fork steem-js. In doing so, I only exposed a previously hidden routine deep inside the library.

Now, there is a routine called steem.auth.signBuffer(). When a transaction is signed a digest is created, the digest is sent to this routine and the signature is created. A recovery parameter is included so we know which square root to to give as the public key. If the public key matches tha public key that was supposedly used to sign, the signature verifies.

My change for steem-js amounts to a single non-comment line of code:

    // @parameter 1 : buffer (string)
    // @parameter 2 : private_signing_key (string)
    // returns a signature of type Signature (which can be made readable with .toHex() or .toBuffer())
    Auth.signBuffer = Signature.signBuffer;

Such a small amount of code should be easy to maintian.

Instead of passing the raw signature to the CGI script, the signature has to made into hex string like this:

    let session_signature = steem.auth.signBuffer(session, private_signing_key);
    let session_signature_string = session_signature.toHex();

The bad news was signatures in the Javascript implementation, Steem-js, are encoding the signatures like Beem expects. Whereas in Beem, the first byte always gets 27 + 4 + the recovery parameter, in Steem-js this isn't always the case. In Steem-js, they only add 27.

That was a source of some problems in retrieving the correct key!

In my Python code, I have my own customized verify_message implementation:

    verify_message(session.id, session_signature, public_key)

session.id is a string, session_signature can be a 65 byte run of bytes or 130 hex string, and the public_key is actually an address of the form : STM.... This is the form of objects that you will see when streaming transactions using Steem-python or Beem.

It turns out there are similar routines to my implementation but only mine really works with the Steem notion of what a signature and a public key should be. Other implementations do not expect a 65 byte signature or keys that start with STM or STX. Mine does.

Here is Steem-specific verify_message routine implemented in beem:

    # Verify a message has signature message_signature with address address.
    # If this verifies the routine returns nothing at all, but it it doesn't an exception is thrown.
    def verify_message(message: str, signature: str or bytes, address : str):
        if not isinstance(message, bytes_types):
            message = py23_bytes(message, "utf-8")
        if not isinstance(signature, bytes_types):
            signature = py23_bytes(signature, "utf-8")
        if not isinstance(message, bytes_types):
            raise AssertionError()
        if not isinstance(signature, bytes_types):
            raise AssertionError()
        if len(signature) == 130:
            signature = binascii.unhexlify(signature)
        if len(signature) != 65:
            raise AssertionError()
        digest = hashlib.sha256(message).digest()
        sig = signature[1:]
        recover_parameter = (bytearray(signature)[0] - 27) % 4  # recover parameter only
    
        uncompressed_public_key = beemgraphenebase.ecdsasig.recover_public_key(digest, sig, recover_parameter)
        # Will throw an exception if not valid
        uncompressed_public_key.verify_digest(
            sig,
            digest,
            sigdecode=ecdsa.util.sigdecode_string
        )
        phex = beemgraphenebase.ecdsasig.compressedPubkey(uncompressed_public_key)
    
        recovered_public_key = beemgraphenebase.account.PublicKey(binascii.hexlify(phex).decode("ascii"))
        if format(recovered_public_key, address[0:3]) != address:
            raise Exception("Incorrect supplied key or message")

Journal Entry List

Dash XjzjT4mr4f7T3E8G9jQQzozTgA2J1ehMkV
LTC LLXj1ZPQPaBA1LFtoU1Gkvu5ZrxYzeLGKt
BitcoinCash 1KVqnW7wZwn2cWbrXmSxsrzqYVC5Wj836u
Bitcoin 1Q1WX5gVPKxJKoQXF6pNNZmstWLR87ityw (too expensive to use for tips)

See also


sign-in-javascript-verify-in-beem.png

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!