How to verify that a transaction was signed by a given account ID in NEAR protocol?

Viewed 213

I have a signed transaction and I want to verify that it is signed by the account ID that exists on NEAR.

1 Answers

The question is three-fold:

  1. Check the transaction hash. Serialize the transaction with Borsh and compute sha256, it should match the transaction.hash.
  2. Verify that the signature is valid for the given public key. Use any available tools that can verify the given signature type. There is ed25519 package in Python, so here is the example:

    import ed25519
    import base58
    
    transaction = {
        "hash": "EzvvJEqdxKA62oAjG32y5herDtRGYEdmZXHDDyxorJ48",
        "public_key": "ed25519:oNCFEmRotRHTySKqmAwifNZ8VRpYS973p8cL61y7eiE",
        "signature": "ed25519:46WsywQYe31isWcHASrnR2pYCja4Mtjzs4n87isrTHWyDdX5uwrUaUn4SbhY9BMwWKvWwdcuyCjMsXdkXdPJv8ko",
    }
    
    pk_bytes = base58.b58decode(transaction['public_key'][len('ed25519:'):])
    pk = ed25519.VerifyingKey(pk_bytes)
    
    # OK:
    pk.verify(
        sig=base58.b58decode(transaction['signature'][len('ed25519:'):]),
        msg=base58.b58decode(transaction['hash'])
    )
    
    # Exception BadSignatureError:
    pk.verify(
        sig=base58.b58decode('66666666' + transaction['signature'][len('ed25519:') + 8:]),
        msg=base58.b58decode(transaction['hash'])
    )
    
  3. Check that the key exists for the given account ID with near-shell, near-api-*, or raw RPC call:

    $ http post https://rpc.nearprotocol.com method=query params:='["access_key/test/ed25519:oNCFEmRotRHTySKqmAwifNZ8VRpYS973p8cL61y7eiE", ""]' id=123 jsonrpc=2.0
    
    {
        ...
        "result": {
            "block_height": 3297678,
            "nonce": 10493,
            "permission": "FullAccess"
        }
    }
    
Related