数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。
简单认识:
相信我们都写过信,在写信的时候落款处总是要留下自己的名字,用来表示写信的人是谁。我们签的这个字就是生活中的签名:
而数字签名呢?其实也是同样的道理,他的含义是:在网络中传输数据时候,给数据添加一个数字签名,表示是谁发的数据,而且还能证明数据没有被篡改。
OK,数字签名的主要作用就是保证了数据的有效性(验证是谁发的)和完整性(证明信息没有被篡改)。下面我们就来好好地看一下他的底层实现原理是什么样子的。
基本原理:
为了理解得清楚,我们通过案例一步一步来讲解。话说张三有俩好哥们A、B。由于工作原因,张三和AB写邮件的时候为了安全都需要加密。于是张三想到了数字签名:
整个思路是这个样子的:
第一步:加密采用非对称加密,张三有三把钥匙,两把公钥,送给朋友。一把私钥留给自己。
第二步:A或者B写邮件给张三:A先用公钥对邮件加密,然后张三收到邮件之后使用私钥解密。
第三步:张三写邮件给A或者B:
(1)张三写完邮件,先用hash函数生成邮件的摘要,附着在文章上面,这就完成了数字签名,然后张三再使用私钥加密。就可以把邮件发出去了。
(2)A或者是B收到邮件之后,先把数字签名取下来,然后使用自己的公钥解密即可。这时候取下来的数字签名中的摘要若和张三的一致,那就认为是张三发来的,再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。
上面的流程我们使用一张图来演示一下:
首先把公钥送给朋友A和B:
还有就是最后一个比较麻烦的,张三给A或者B发邮件:
Web3JS实现
数据签名:
web3.eth.sign(data, address )
解锁账户:
web3.eth.personal.unlockAccount(address, password, unlockDuraction)
unlockDuration 帐户保持解锁状态的持续时间
验证签名:
web3.eth.accounts.recover();
const Web3 = require('web3');
const ethereumUri = 'http://127.0.0.1:8545';
const web3 = new Web3(new Web3.providers.HttpProvider(ethereumUri));
const address = "以太坊账户"; //签名账户,需要解锁
let msg = web3.utils.utf8ToHex("Hello world") //要发送的data
//let msg = "Hello world";
//签名 有好多种方式去签名
let signature = web3.eth.sign(msg,address).then(function(receipte){
console.log(receipte);
let r = receipte.slice(0, 66)
let s = '0x' + receipte.slice(66, 130)
let v = '0x' + receipte.slice(130, 132)
console.log('r', r) //签名的前32个字节
console.log('s', s) //签名的后32个字节
console.log('v', v)//恢复值+ 27
console.log(web3.utils.toDecimal(v));
//验证
console.log("原始rlp编码验证:",web3.eth.accounts.recover(msg,receipte ));
// message, v, r, s
console.log("vrs验证:",web3.eth.accounts.recover(msg,v,r,s));
//打印下签名的人
console.log("签名者是",address)
}).catch((error)=>{
console.log(error);
});