shownb / shownb.github.com

shownb.github.io
shownb.github.io
5 stars 1 forks source link

公钥,私钥和数字签名这样最好理解 #20

Open shownb opened 6 years ago

shownb commented 6 years ago

from https://blog.csdn.net/21aspnet/article/details/7249401

一、公钥加密 假设一下,我找了两个数字,一个是1,一个是2。我喜欢2这个数字,就保留起来,不告诉你们(私钥),然后我告诉大家,1是我的公钥。

我有一个文件,不能让别人看,我就用1加密了。别人找到了这个文件,但是他不知道2就是解密的私钥啊,所以他解不开,只有我可以用 数字2,就是我的私钥,来解密。这样我就可以保护数据了。

我的好朋友x用我的公钥1加密了字符a,加密后成了b,放在网上。别人偷到了这个文件,但是别人解不开,因为别人不知道2就是我的私钥, 只有我才能解密,解密后就得到a。这样,我们就可以传送加密的数据了。

RSA算法

RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

0_1328866805u7U7

二、私钥签名 如果我用私钥加密一段数据(当然只有我可以用私钥加密,因为只有我知道2是我的私钥),结果所有的人都看到我的内容了,因为他们都知 道我的公钥是1,那么这种加密有什么用处呢?

但是我的好朋友x说有人冒充我给他发信。怎么办呢?我把我要发的信,内容是c,用我的私钥2,加密,加密后的内容是d,发给x,再告诉他 解密看是不是c。他用我的公钥1解密,发现果然是c。 这个时候,他会想到,能够用我的公钥解密的数据,必然是用我的私钥加的密。只有我知道我得私钥,因此他就可以确认确实是我发的东西。 这样我们就能确认发送方身份了。这个过程叫做数字签名。当然具体的过程要稍微复杂一些。用私钥来加密数据,用途就是数字签名。

总结:公钥和私钥是成对的,它们互相解密。

公钥加密,私钥解密。

私钥数字签名,公钥验证。

举例

比如有两个用户Alice和Bob,Alice想把一段明文通过双钥加密的技术发送给Bob,Bob有一对公钥和私钥,那么加密解密的过程如下:

Bob将他的公开密钥传送给Alice。 Alice用Bob的公开密钥加密她的消息,然后传送给Bob。 Bob用他的私人密钥解密Alice的消息。 上面的过程可以用下图表示,Alice使用Bob的公钥进行加密,Bob用自己的私钥进行解密。

交易防止篡改 数字签名通过数字摘要技术把交易信息缩短成固定长度的字符串。

用户币姐发起一笔数字货币转账,需要先将该交易进行数字摘要,缩短成一段字符串,然后用自己的私钥对摘要进行加密,形成数字签名。

完成后,币姐需要将原文(交易信息)和数字签名一起广播给记录“账本的人”也就是矿工。 矿工用币姐的公钥进行验证,如果验证成功,说明该笔交易确实是币姐发出的,且信息未被更改,是完整的。

比特币地址拥有者的公钥和签名,如何防范被中间人替换呢? 比特币地址的拥有者,在支付时,需要在交易中提交,公钥和签名,以供验证其拥有权。

但是,比特币网络是如何保证不会发生中间人攻击,将公钥和签名同时替换掉呢?

付款方用私钥对交易信息(包括收款方的地址)签名,修改交易后签名就失效了,如果你连签名都能修改,那你就是盗号而就不是中间人替换了。评论区题主的意思是同时替换公钥和签名,当然可以,公钥和签名是付款方提供的,收款方只有一个地址。等于你硬塞钱给别人,这个,我们,谁都,阻止不了。

以太坊里面的geth的签名,过程是:keystore文件+密码= privateKey 用privateKey签名后调用sendRawTransaction

获取私钥 npm install keythereum https://github.com/ethereumjs/keythereum 可以导出私钥

var keyth=require('keythereum');  
var keyobj=keyth.importFromFile('账户地址','/root/.ethereum');  
var privateKey=keyth.recover('password',keyobj);  
console.log(privateKey.toString('hex'));  

签名

npm install web3 ethereumjs-tx --save

var Web3 = require('web3');
web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/YORUTOKEN"));
var Tx = require('ethereumjs-tx');

var rawTx = {
    nonce: '0x14',
    gasPrice: '0x3B9ACA00', 
    gasLimit: '0xC20A',
    to: '0x5fb30123b9efedcd15094266948fb7c862279ee1', 
    value: '0x00', 
    data: '0x' + '60fe47b1' + '000000000000000000000000000000000000000000000000000000000000000a'
}
//建立raw transaction
var tx = new Tx(rawTx);
//私钥签名
const privateKey = new Buffer('<your-private-key>', 'hex'); tx.sign(privateKey);
//序列化?
var serializedTx = tx.serialize();
//发送,并设计回调函数
//不再使用rawTransaction 函数已经改名字
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'),function(err, hash) {
    if (!err) {
        console.log(hash);
    } else {
        console.log(err)
    }
});

比特币单位转换 https://etherconverter.online

//坑是nonce 自己获取
var Web3 = require('web3');
web3 = new Web3(new Web3.providers.HttpProvider("https://api.myetherapi.com/eth"));
var number = web3.eth.getTransactionCount("自己地址");
var Tx = require('ethereumjs-tx');
var rawrawTx = {nonce:"0x03",gasPrice:"0x098bca5a00",gasLimit:"0x5208",to:"地址",value:"0x8e1bc9bf040000",data:"0x",chainId:1}
//建立raw transaction
console.log(number)
var tx = new Tx(rawrawTx);
//私钥签名
const privateKey = new Buffer('私钥', 'hex'); tx.sign(privateKey);
//序列化?
var serializedTx = tx.serialize();
//发送,并设计回掉函数
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex')).on('transactionHash', function(hash){
          console.log('Txn:' + hash);
       }).on('receipt', function(receipt){
           console.log('Receipt:' + receipt);
       });

参考网址 http://forum.sourcecc.io/topic/148/以太坊开发-如何使用web3js通过私钥签名发起一笔交易 https://zhuanlan.zhihu.com/p/33820638

作者:余天升 链接:https://www.zhihu.com/question/20744215/answer/16056710 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

不知道各位有没有见过一种锁,当用钥匙打开这种锁之后,钥匙就可以拔出来了,剩下一个开着的锁头。拿着这个开着的锁,没有钥匙,一旦锁上了就开不了。这是现实生活这的一种非对称加密的物件,能上锁,但是不能开锁。现在故事开始,假设我们回到了那个只能寄信的时代,大家都需要和知乎通信,而且通信的内容必须要保密。于是负责接收大家消息的@顾惜朝 想出来一个办法,找了很多把上面说的那种锁(公钥),都用钥匙打开,挂在外面。需要和知乎通信的人,在通信之前,需要拥有另外一把有两个钥匙的锁(对称加密算法),然后把这把锁和其中一把钥匙(对称密钥),放进一个无法被破拆的铁盒子里面,用知乎提供的那把开着的锁把铁盒子锁上。这时候,这个铁盒子就无法打开了,除了拥有钥匙的顾惜朝。这个装有一把锁和钥匙的铁盒子,可以放心地交到任何一个人手上,然后让他拿去给顾惜朝。顾惜朝拿到这个铁盒子之后,加密通信会话就建立了。她就会用钥匙打开铁盒子,取出锁和钥匙,写下“亲爱的知乎用户,你好,我是顾惜朝”小纸条,放进铁盒子里,然后用你提供的锁把铁盒子锁上,然后交回到你的手上。这个时候,铁盒子被你提供的锁锁上了,除了你和顾惜朝,没有别人有钥匙能够打开这个铁盒子,铁盒子也就可以安全地经过邮递送到你的手上;你收到铁盒子之后,用你自己的钥匙打开锁,读铁盒子里面的消息,然后放进新的小纸条,再寄送回去。以上是加密通信的过程。接下来,别有用心的@匿名用户 出现了,偷偷地换掉了几个知乎打开放在外面的锁,并且自己充当了邮递员的身份在外面晃悠。当你需要和知乎通信的时候,匿名用户递给你一把他自己的锁,骗你说这把是知乎挂在外面的锁。当你把你自己的锁和钥匙放进去,然后交给匿名用户,麻烦他把这些送给顾惜朝的时候,匿名用户就可以找到另外一个铁盒子,装上自己的另外一把两个钥匙的锁,用真正的知乎提供的锁锁上,然后寄给顾惜朝。我们辛勤的顾惜朝依然会正常的收到一个铁盒子,里面装着一把锁和一把钥匙,只不过,这个锁已经不是你的了,而是匿名用户的,你的那把锁实际上在匿名用户手上。顾惜朝把“亲爱的知乎用户,你好,我是顾惜朝”的小纸条放进铁盒,然后让匿名用户带回去给你,而这个时候,匿名用户就可以打开这个小铁盒,偷看你们之间的消息,然后自己编造一条消息,放进铁盒里面,然后传回去给你。以上是中间人攻击。为了避免中间人攻击,我们聪明的顾惜朝,发明了一种神奇的、无法撕毁、涂改和变造的小纸条(数字签名),上面写着“这把锁经过顾惜朝认证,是知乎加密通信专用锁”,然后在每一把知乎提供的锁上贴上,这样子匿名用户就不能伪造锁了,这时候这个锁叫作证书。但是问题又来了,许多新来的知乎用户不认识顾惜朝,他们怎么知道顾惜朝就是可信的,她认证的锁就是可用的?于是@黄继新在这个小纸条的下方又贴了一个小纸条,“顾惜朝经过黄继新的认证,可以对知乎加密通信专用锁进行认证”。黄继新不仅可以认证锁,还可以认证顾惜朝等管理员的权力,这时候黄继新就是CA。可是问题还没有解决,还是有很多知乎用户不认识黄继新,于是李开复又在黄继新的小纸条上又贴了一个小纸条,“黄继新经过李开复的认证,可以对知乎加密通信专用锁进行认证”。问题依然没有解决,还是有人不认识李开复,于是这时候需要一个权威的、人们无条件相信的机构来对李开复进行认证,这个机构就是根CA,他贴上去的小纸条就叫作根证书。以上是信任体系,另见《既然这个世界没有绝对的“权威”,那么我们该相信谁?》。最后一个问题,TLS的中间人攻击怎么实施。这时候@Rio出场了,因为是知乎的工作人员,具有一个可信的证书,类似于“Rio经过黄继新的认证,可以对知乎加密通信专用锁进行认证”。于是他自己伪造了一个锁,然后利用上一级CA对他的信任,去骗取知乎用户使用他提供的锁初始化加密会话。因为他的锁上面有上一级CA的认证,所以你会认为这个锁是可信的,而实际上Rio通过自己拥有的证书,可以实施中间人攻击,窃取你和顾惜朝之间通信的内容。以上便是TLS的中间人攻击。手里掌握权力的人,只有道德能够防止他做坏事。