На уровне Ethernaut 8 вам дается этот контракт на взлом:
pragma solidity ^0.4.18;
contract Vault {
bool public locked;
bytes32 private password;
function Vault(bytes32 _password) public {
locked = true;
password = _password;
}
function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}
Пароль, который передается в контракт через аргументы конструктора, находится легко; Перейдя к транзакции создания в Etherscan и прочитав код ввода инициализации в тексте. Или:
web3.eth.getStorageAt(contractAddress, 1, function(error, result) {password = result}))
Есть ли способ закодировать эти аргументы (bytes32 _password) и сделать так, чтобы никто не мог получить их через etherscan или web3?
Вы никогда не сможете по-настоящему скрыть данные там, где ваша проверка на равенство по существу a == b
.
Большинство систем, которые полагаются на такие функции на основе пароля, будут использовать хэши, чтобы скрыть значение.
Вместо того, чтобы устанавливать пароль напрямую, вы password
устанавливаете keccak256(password)
. Затем, когда вы хотите разблокировать контракт, вы выполняете транзакцию с фактическим паролем в качестве данных, и контракт вычисляет keccak256(input)
, а затем проверяет, соответствует ли он ранее предоставленному хэшу.
Конечно, это затем показывает пароль в разблокировке tx. Чтобы избежать этого, вы можете передать новый хэш ( _newpassword
) при разблокировке. Если разблокировка прошла успешно, обновите хэш пароля на этот новый, и в следующий раз, когда вы захотите разблокировать, укажите пароль для этого хэша (вместе с третьим, чтобы установить его).