Solidity学习::(7)智能合约案例-2(验证签名)
椭圆曲线DSA(ECDSA)
对于这个,就不介绍了。
下给出签名的⽣成和验证过程。
假如Alice要对消息m加上数字签名,⽽Bob需要验证该签名。
⽣成数字签名
1. Alice根据随机数r和基点G求出点rG = (x, y);
2. Alicce根据随机数r、消息m的散列值h、和私匙a计算
3. 最后,Alice将消息m、点rG = (x, y)和s发送给Bob,其中点rG和s就是数字签名。
验证数字签名
1. Bob接收到消息m、点rG = (x, y)和s。
2. Bob根据消息求出散列值h。
3. 最后,Bob根据上述信息,⽤Alice的公匙进⾏以下计算。
最后让上述计算结果与rG进⾏⽐较看是否相等。
如果签名结果正确,则计算结果应如下所⽰。
原书中关于这部分看了三四遍,也没看明⽩。但觉得做程序的明⽩他⼤概要⼲个什么就好。⼤体上来说,对于要签名的数据m,使⽤它的哈希后的结果h,会⽣成签名。签名结果分为r,s,v三段值。其中r,
s为32字节。v为⼀个字节,如果要⽤ecrecover()算法来验签,需对v值加27来组成27,28这两个值中的⼀个。
智能合约案例-2
⼀、打开remix-ide
⼆、先导内容
2、切⽚函数:
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;
}
3、 bytes类型转bytes32类型函数:
function bytesToBytes32(bytes memory source) returns(bytes32 result){
assembly{
result :=mload(add(source,32))
}
}
四、案例合约功能
若已知正确的对⽅公钥:0x60320b8a71bc314404ef7d194ad8cac0bee1e331
且获取到原始数据的哈希sha3(msg),0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 (web3.sha3("abc");)
和发送来的已经签名的数据:
0xf4128988cbe7df8315440adde412a8955f7f5ff9a5468a791433727f82717a6753bd71882079522207060b681fbd3f5623ee7ed66e33fc8e581f442acbc
1. 本案例中合约实现的功能是:根据发送来的已签名的数据和原始数据的哈希,来推算出发送数据来的公钥地址。通过对⽐已知的正确的公钥,达到验证签名的⽬的
五、合约代码
pragma solidity ^0.4.4;
contract Decode{
//公匙:0x60320b8a71bc314404ef7d194ad8cac0bee1e331
//公钥是⽤来算出来后对⽐看看是否⼀直⼀致的
//sha3(msg): 0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 (web3.sha3("abc");)
//这个是数据的哈希,验证签名时⽤到
//签名后的数据:0xf4128988cbe7df8315440adde412a8955f7f5ff9a5468a791433727f82717a6753bd71882079522207060b681fbd3f5623ee7ed66e33fc8e581f442acbcf6ab800
//签名后的数据,包含r,s,v三个内容
//验证签名⼊⼝函数
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];
}solidity
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))
}
}
}
六、操作展⽰
基本的步骤:
1、编译代码
2、部署合约
3、部署完成后,如下图
4、点击decode函数,等待执⾏
5、查看执⾏结果:
可以看到,这个输出的结果跟已知的对⽅公钥是⼀致的,那么就可以证明签名是正确的,数据确实是对⽅发出的。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。