【solitidy】数学&hash&签名加密

37次阅读

共计 2846 个字符,预计需要花费 8 分钟才能阅读完成。

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 算法,在很多场合下 Keccak 和 SHA3 是同义词,但在 2015 年 8 月 SHA3 最终完成标准化时,NIST 调整了填充算法,标准的 SHA3 和原先的 Keccak 算法就有所区别了。在早期的 Ethereum 相关代码中,普遍使用 SHA3 代指 Keccak256,为了避免和 NIST 标准的 SHA3 混淆,现在的代码直接使用 Keccak256 作为函数名。
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()
椭圆曲线加密
引用
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;
}

正文完
 0