Search code examples
nearprotocol

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


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


Solution

  • 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"
          }
      }