2

I want my server to modify the state of the contract. The server has the contract's secret key and a way of broadcasting signed transactions to the network using web3 ethereum provider hosted by Infura. Here's the contract code:

pragma solidity ^0.4.0;
contract Contract {
    bytes32 password;
    uint public someVar;

    function Contract(string secret){
        password = sha3(secret);
    }

    function changeSomeVar(string secret, uint someValue) passwordProtected(secret){
        someVar = someValue;
    }

    modifier passwordProtected(string secret){
        if(sha3(secret) != password) {
            throw;
        }
        _;
    }
}

What are the most vulnerable points in my setup?

Should I continue with it or use something else?

1 Answer 1

5

Not secure.

I'll explain the weaknesses and outline a different approach.

The problem isn't the secret stored in obfuscated form. It's true the secret can't be recreated from that. The problem is no one can run this contract without knowledge of the true value of the secret. No one can calculate the sha3 of the secret without having the secret. Secret is going to be transmitted every time.

The secret will end up forever part of the history the chain - broadcast to all with the constructor and with each message to changeSomeVar. If it helps, verifiers/miners (all) need to know the secret to calculate the sha3. That means everybody knows.

The usual approach is to use Ethereum's built-in msg.sender to identify the user. A signed message (they all are) from this entity demonstrates knowledge of the private key, but the private key isn't transmitted. As a privileged user, your server will have an address and the contract will associate privileges with that address.

Usual simple pattern for this:

pragma solidity ^0.4.6;

contract Contract {

    address public owner;
    uint public someVar;

    modifier onlyOwner() {
        if(owner != msg.sender) throw;
        _;
    }

    function Contract() {
        owner = msg.sender; // server deploys the contract
    }

    function changeSomeVar(string secret, uint someValue) 
        onlyOwner 
    {
        someVar = someValue;
    }

}

That basic structure is extendable.

It's possible to change servers by migrating the private key file (the secret) to a new server. Obviously important to safeguard knowledge of the private key from internal users who shouldn't know it.

It's also possible to build in a changeOwner() function, commonly something onlyOwner is authorized to do.

It's possible to imagine and implement more intricate structures of user privileges. The principle is the same. The msg.sender is usually the best way to identify the user. On-chain secrets usually aren't so secret.

Hope it helps.

1
  • It's a very helpful answer. It's now very clear to me what's the problem with my approach. Thank you, sir!
    – manidos
    Commented Feb 9, 2017 at 6:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.