The idea of securing your critical functions with additional password is very good, but the way you implemented it is not secure due to the publicity of all transaction input data:
- Once you call storePassword function to initialize your password, the data in this call is visible to anyone who runs full node.
- The data is also visible when looking at the contract transaction history (it needs to be disassembled but it is quite easy for hackers)
- Each time you call a function that is protected with password you also expose it in the transaction data and again it is visible
So i thought about how to have password protected functions in a secure way and here is what i came out with:
1. You need to set a password and calculate its hash offline. Then hard-code the hash value into the contract (or create a function to initialize the password hash)
2. Whenever you call a function that is password protected, you need to set a new password hash (since the function call data is visible to anyone). Therefore, you need to hold an offline list of passwords and their matching hashes and each password protected function needs to accept the next password hash parameter and replaces the current hash with the new one
* you may create a list of hashes and initialize the contract with the whole list. So you will not need to change the hash in each call, but just lookup the hash of the current password in the list and then remove it so it cannot be reused
Now there are some risks you need to consider:
1. Each password must be very different than the others to prevent guessing relying on previous passwords.
2. To prevent hash cracking you should also use a Salt value for the hashing - a long random string that you concatenate with the password before hashing. The Salt can be a single value stored in the contract (it will be visible but it anyway has its added value to prevent cracking the hashes with existing rainbow tables)
3. Since you need to have many passwords and make them complex and different from each other you will probably need to write them down somewhere, so there is also a risk you will lose access to the passwords and the risk of someone getting access to this list
4. There is also a race condition risk - when you submit a transaction to your contract with a password, before the transaction is confirmed in a block, the attacker (who has your private key, as this is the reason the password exists in the first place) can make a competing transaction with higher gas price, making it in higher priority for the miners. This way, the attacker use your hash to access the password protected function and if the function also replaces the hash the attacker can set the next password and now he is in control of the passwords and not you (this is why initializing the contract with a list of hashes is more secure)
And one idea i have regarding the case where your private key is stolen but you still have access to it as well:
- Create a kill-switch function with hard-coded password hash (that matches to a dedicated kill-switch password you have offline)
- This function will turn on a global boolean flag that indicates to all other functions that the contract is disabled forever (there is no function to set it back to false)
- Once you know your private was stolen call this function and the attacker cannot abuse his access to the contract (the race-condition attack is not a risk in this case as the attacker cannot use the password of the kill-switch function for any other functions and the kill-switch function will be called anyway)
Lot of interesting comments.
- About the hash, you are right, but I don't see how to overcome this problem. The best solution would be to use a salt and something like blowfish, but it would cost too much gas to include this into the contract. Otherwise every solution I can think of, including your suggestions are not hacker proof since both the parameters and the return result are known and public. Also I do not want to have something too complicated to manage with the risk to forget the password and not being able to remember what was the last hash...
This password system is good to discourage the guy who stole your computer, but if a pro hacker do it, there is nothing to do.
I published the password contract separately at Github [here](https://github.com/TheWolf-Patarawan/PasswordClassSolidity)
- About the kill-switch I got the idea but I think that the isPaused function is doing this job (block the contract) and the destroyContract function is killing the contract too. So I think that there the functionalities are already here.
I will publish the tarpitting code, because I don't think anyone did it, I removed it from the 10X contract because it was taking too much gas and was not really useful.
Also if you are a programmer there an interesting idea, based on what I learned from the way the exchanges are working.
The idea would be to modify the ERC20 standard to also store every transaction (buy/sell) in a public table with the source and dest address, and in return calculate the price of the token based on the values transmitted.
That would greatly enhance the traceability of the transactions in the Ethereum world.