Stricter Use of End User's Signature in Contract

By checking the signature of the end user within Contract, processing based on the end user's signature can be executed while payment is being made.

Reference: Verification of End User's Signature

However, there is a problem of reuse.

As the signing itself is done with the private key in the terminal of the end user, it can not be signed by others, but since it passes through the internet from the end user's terminal to the contract, snooping becomes a possibility. If the exact same command is re-transmitted it will be possible to steal and use the signature.

This can be handled the following ways.

  • Timestamp method

    When calling from the end user, include the time stamp in the parameters and check on the contract side for a difference from the current time.

    Although it can be reused for a certain period of time, it can not be reused beyond that time.

    Note that the time stamp on the Contract side is the block creation time and the unit becomes seconds.
    Below is an example of adding a timestamp as the first parameter of sendTransaction.

    contract SomeContract is VersionContract {
    
        uint constant TIMESTAMP_RANGE_SEC = 600;
        mapping(address => bool) allowUsers;
    
        function SomeContract(ContractNameService _cns) VersionContract(_cns, "SomeContract") {}
    
        function someMethod(bytes _sign, uint _timestamp, uint _p1, bytes32 _p2) {
            // create all parameters hash
            bytes32 hash = calcEnvHash('someMethod');
            hash = sha3(hash, _timestamp);
            hash = sha3(hash, _p1);
            hash = sha3(hash, _p2);
            // get end user's addresss
            address endUserAddr = Utils.recoverAddress(hash, _sign);
            if (!allowUsers[endUserAddr]) throw;
    
            // check timestamp
            if (!checkTimestamp(_timestamp)) throw;
    
            // do something
        }
    
        function checkTimestamp(uint _timestamp) private constant returns(bool) {
            return (now - TIMESTAMP_RANGE_SEC< _timestamp && _timestamp < now + TIMESTAMP_RANGE_SEC);
        }
    }
    
  • Introducing transaction count

    This method is effective only for transaction issue processing, but it records the sequence number for each end user (address).
    Prepare a simple contract that counts each user as follows.

    contract TransactionCounter {
    
        mapping(address => uint) counter;
    
        function getCount(address _user) constant returns (uint) {
            return counter[_user];
        }
    
        function addCount(address _user) {
            counter[_user] += 1;
        }
    }
    

    When executing each transaction, add a count value to the parameter to prevent reuse.
    Below is an example of adding a counter to the first parameter of sendTransaction.

    contract SomeContract is VersionContract {
    
        TransactionCounter constant TX_COUNTER = TransactionCounter("0xffffffffff...");
        mapping(address => bool) allowUsers;
    
        function SomeContract(ContractNameService _cns) VersionContract(_cns, "SomeContract") {}
    
        function someMethod(bytes _sign, uint _txCount, uint _p1, bytes32 _p2) {
            // create all parameters hash
            bytes32 hash = calcEnvHash('someMethod');
            hash = sha3(hash, _txCount);
            hash = sha3(hash, _p1);
            hash = sha3(hash, _p2);
            // get end user's addresss
            address endUserAddr = Utils.recoverAddress(hash, _sign);
            if (!allowUsers[endUserAddr]) throw;
    
            // check txCount
            if (TX_COUNTER.getCount(endUserAddr) != _txCount) throw;
            TX_COUNTER.addCount(endUserAddr);
    
            // do something
        }
    }
    

    The end user calls TransactionCounter#getCount using call before issuing the transaction that needs to be written, acquires the current transaction number, sends the transaction to execute including the transaction count parameter.

results matching ""

    No results matching ""