Verification of End User's Signature in Contract

The end user signs with the end user's own KeyPair, the API server issues a transaction including the signature, and the contract verifies the signature.

Contract Sign Check

First, we take a look at how the end user's signature is generated on the client side.

Since the end user's signature is generated within AltExecCnsContract, we do not need to be conscious of the details, but we explain it to help understand signature verification in the contract side.

  • End user signing

An example of how to call this service on the end user side is as follows.

  • Calling part

    var contract = new AltExecCnsContract(account, '__CNS_ADDRESS__');
    contract.sendTransaction('__PASSWORD__', 'SomeContract', 'someMethod', ['p0', 1, 'p2'], abi, function(err, res) {
        if (err) console.error(err);
        else console.log(res.join(','));
    }
    

    The actual signature is generated within AltExecCnsContract#sendTransaction.

  • Source code excerpt

    AltExecCnsContract.prototype.sendTransaction = function(password, contractName, functionName, params, abi, callback) {
        ...
        var altParams = new AltExecCnsParams(cnsAddress, contractName, functionName, params);
        altParams.setTypesFromAbi(abi);
        const hash = altParams.getHashedParams();
        ...
        this.account.sign(password, hash).then(function(sign) {
            ...
        };
    };
    

Here we derive the hash value from the "all" parameters used by the end user in the call and create a signature for that hash value.
The entire source code of AltExecCnsContract is here.

  • Verification within Contract

    The way to verify the end user's signature within the contract is as follows.

    • Contract Implementation

      contract SomeContract is VersionContract {
          function SomeContract(ContractNameService _cns)     VersionContract(_cns, "SomeContract") {}
          function someMethod(bytes _sign, bytes32 _p0, uint _p1, bytes32 _p2) constant returns (string) {
              // create all parameters hash
              bytes32 hash = calcEnvHash('someMethod');
              hash = sha3(hash, _p0);
              hash = sha3(hash, _p1);
              hash = sha3(hash, _p2);
              // get end user's addresss
              address endUserAddr = Utils.recoverAddress(hash, _sign);
              ...
          }
      }
      

    Verifying the signature within the contract performs similar processing to the check done by the end user's client.

    Generate hash initially with "VersionContract#calcEnvHash" which hashes the fields below.

    • Address of ContractNameService
    • Contract name
    • Name of the function

    Then we calculate and update the hash with the value of all the parameters.

    Finally, we get the address of the end user from the generated hash value.

    address endUserAddr = Utils.recoverAddress(hash, _sign);
    

    If the value signed by the end user differs even by 1 bit, the hash value will change and the address recovered will be different so that it is not possible to change the parameters. It is also not possible to impersonate the end user (address) without access to the end user's signature.

    Furthermore, if you implement access control on the recovered endUserAddr, it will only be possible for the specified end users to call.

  • Limiting signatures

    With the processing so far, we were able to execute Contract processing based on the signature of the end user, but we can further tighten the security around signatures.

    Please refer to the next section Stricter Use of End User's Signature.

results matching ""

    No results matching ""