【solitidy】數學&hash&簽名加密

solitidy官方文檔

數學函數

  • addmod(uint x, uint y, uint k) returns (uint)
    計算(x + y) % k。加法支持任意的精度。但不超過(wrap around?)2**256。
  • mulmod(uint x, uint y, uint k) returns (uint):
    計算(x y) % k。乘法支持任意精度,但不超過(wrap around?)2*256。

hash

  • keccak256()
    SHA3採用Keccak算法,在不少場合下KeccakSHA3是同義詞,但在2015年8月SHA3最終完成標準化時,NIST調整了填充算法,標準的SHA3和原先的Keccak算法就有所區別了。在早期的Ethereum相關代碼中,廣泛使用SHA3代指Keccak256,爲了不和NIST標準的SHA3混淆,如今的代碼直接使用Keccak256做爲函數名。html

    keccak256(...) returns (bytes32)
    // 緊密打包:參數不會補位,就直接鏈接在一塊兒的。下面來看一個例子效果同樣:
    keccak256("ab", "c")
    keccak256("abc")
    keccak256(0x616263)
    keccak256(6382179)
    keccak256(97, 98, 99)
  • sha256(...) returns (bytes32):
    使用SHA-256計算HASH值。緊密打包。
  • sha3()
    等於 keccak256()
  • ripemd160(...) returns (bytes20)
    計算RIPEMD-160 hash。緊密打包。

ecrecover()

橢圓曲線加密web

引用
pragma solidity ^0.4.4;

contract Decode{
  //公匙:0x60320b8a71bc314404ef7d194ad8cac0bee1e331
  //sha3(msg): 0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 (web3.sha3("abc");)
  //簽名後的數據:0xf4128988cbe7df8315440adde412a8955f7f5ff9a5468a791433727f82717a6753bd71882079522207060b681fbd3f5623ee7ed66e33fc8e581f442acbcf6ab800

  //驗籤數據入口函數
  function decode() returns (address){
    bytes memory signedString =hex"f4128988cbe7df8315440adde412a8955f7f5ff9a5468a791433727f82717a6753bd71882079522207060b681fbd3f5623ee7ed66e33fc8e581f442acbcf6ab800";

    bytes32  r = bytesToBytes32(slice(signedString, 0, 32));
    bytes32  s = bytesToBytes32(slice(signedString, 32, 32));
    byte  v = slice(signedString, 64, 1)[0];
    return ecrecoverDecode(r, s, v);
  }

  //將原始數據按段切割出來指定長度
  function slice(bytes memory data, uint start, uint len) returns (bytes){
    bytes memory b = new bytes(len);

    for(uint i = 0; i < len; i++){
      b[i] = data[i + start];
    }

    return b;
  }

  //使用ecrecover恢復公匙
  function ecrecoverDecode(bytes32 r, bytes32 s, byte v1) returns (address addr){
     uint8 v = uint8(v1) + 27;
     addr = ecrecover(hex"4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45", v, r, s);
  }

  //bytes轉換爲bytes32
  function bytesToBytes32(bytes memory source) returns (bytes32 result) {
    assembly {
        result := mload(add(source, 32))
    }
  }
}

上述代碼使用臨時寫的slice()函數把數據簽名中的r,s,v切割出來;因爲返回的還是一個bytes類型,因此咱們使用bytesToBytes32()進行一下類型轉換8;另外須要注意的是ecrecoverDecode()根據前面的說明,咱們須要對v值,加上27後再進行調用。最後調用decode()函數,咱們將會獲得公匙0x60320b8a71bc314404ef7d194ad8cac0bee1e331。算法

bancor.network裏面的驗證算法
function verifyTrustedSender(IERC20Token[] _path, uint256 _amount, uint256 _block, address _addr, uint8 _v, bytes32 _r, bytes32 _s) private returns(bool) {
    bytes32 hash = keccak256(_block, tx.gasprice, _addr, msg.sender, _amount, _path);

    // checking that it is the first conversion with the given signature
    // and that the current block number doesn't exceeded the maximum block
    // number that's allowed with the current signature
    require(!conversionHashes[hash] && block.number <= _block);

    // recovering the signing address and comparing it to the trusted signer
    // address that was set in the contract
    bytes32 prefixedHash = keccak256("\x19Ethereum Signed Message:\n32", hash);
    bool verified = ecrecover(prefixedHash, _v, _r, _s) == signerAddress;

    // if the signer is the trusted signer - mark the hash so that it can't
    // be used multiple times
    if (verified)
        conversionHashes[hash] = true;
    return verified;
}
相關文章
相關標籤/搜索