Как скрыть/защитить аргументы смарт-контракта

На уровне 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?

Ответы (1)

Вы никогда не сможете по-настоящему скрыть данные там, где ваша проверка на равенство по существу a == b.

Большинство систем, которые полагаются на такие функции на основе пароля, будут использовать хэши, чтобы скрыть значение.

Вместо того, чтобы устанавливать пароль напрямую, вы passwordустанавливаете keccak256(password). Затем, когда вы хотите разблокировать контракт, вы выполняете транзакцию с фактическим паролем в качестве данных, и контракт вычисляет keccak256(input), а затем проверяет, соответствует ли он ранее предоставленному хэшу.

Конечно, это затем показывает пароль в разблокировке tx. Чтобы избежать этого, вы можете передать новый хэш ( _newpassword) при разблокировке. Если разблокировка прошла успешно, обновите хэш пароля на этот новый, и в следующий раз, когда вы захотите разблокировать, укажите пароль для этого хэша (вместе с третьим, чтобы установить его).