区块链核心技术-密码学

大家好,首先感谢腾讯云提供云社区这样一个让技术人员沟通交流的平台,其次很高兴入驻到云+社区认识到大家,我是腾讯云TVP一员,专注于云计算、区块链、Web架构方向,myPagination作者,Github也开源了很多区块链的项目:https://github.com/linapex,有需要的朋友可以下载学习,本文是区块链技术实战系列的第二篇(不定期更新):

《区块链从钱包应用到技术本质》

《区块链核心技术-密码学》

《区块链核心技术-P2P网络构建》

《区块链核心技术-分布式一致性与共识算法》

《区块链核心技术-区块设计与存储》

今天我们聊一聊区块链的核心技术密码学,区块链技术离不开密码学,可以说密码学是区块链系统的基石之一,我们先来了解一下。

这是以太坊黄皮书关于钱包(私钥、公钥、地址)的描述,仅仅 2 行文字。主要讲解私钥通过 ECDSA(椭圆曲线签名算法)推导出公钥,继而经过 Keccak 单向散列函数推导出地址。分解为 3 个步骤:

1. 创建随机私钥 (64 位 16 进制字符 / 256 比特 / 32 字节)

2. 从私钥推导出公钥 (128 位 16 进制字符 / 512 比特 / 64 字节)

3. 从公钥推导出地址 (40 位 16 进制字符 / 160 比特 / 20 字节)

这是从ethereumjs/keythereum中剥离出来的 JavaScript 代码,关于黄皮书上的公式的具体实现,仅仅 6 行代码。

这是一件很奇妙的事情,2 行文字,6 行代码承载着亿万级别的资产,但往往越简单,越奥妙。以上的 6 行代码,就已经囊括密码学中大多数技术,比如随机数生成器、非对称加密,单向散列函数等。

什么是随机数生成器?

随机数用于生成私钥,若随机数可以被预测或重现,则私钥就会立刻形同虚设。所以保证随机数拥有下列三项特征,至关重要:

1.随机性:不存在统计学偏差,完全杂乱的数列

2.不可预测性:不能从过去的数列推测下一个出现的数

3.不可重现性:除非将数列保存下来,否则不能重现相同的数列

软件本身是无法生成具有不可重现性的随机数,因为运行软件的计算机本身仅具备有限的内部状态。所以通过确定性的代码,在周期足够长的情况下,必然会出现相同的随机数。因此要生成具备不可重现性的随机数,需要从不确定的物理现象中获取信息,比如周围温度、环境噪音、鼠标移动,键盘输入间隔等。

在 Linux 内核中维护了一个熵(shāng)池用来收集来自设备驱动程序和其它来源的环境噪音。熵(entropy)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。

所以在选择生成私钥的随机数方法时,需要选择满足密码学强度的随机数方法,比如 Node 中的 crypto.randomBytes。当你调用 crypto.randomBytes(32) 方法时,它会等待熵池搜集足够的信息后,返回 64 位的随机数,即私钥。

const privateKey = crypto.randomBytes(32)
privateKey.toString('hex'): 
ea4692a11d962b249f8f0439d642a9013a1a08807649311d3672886d72d1fe51

什么是非对称加密?

在非对称加密中,将密钥分为加密密钥和解密密钥,也就是我们常说的公钥和私钥。公钥和私钥一一对应,由公钥加密的密文,必须使用公钥配对的私钥才可以解密。

当我们调用 secp256k1.publicKeyCreate 获得公钥时,实际使用的是非对称加密中的椭圆曲线算法。通过该算法可以从私钥推导出公钥,这是一个不可逆的过程:K = k * G。给出常数点 G 时,使用已知私钥 k 求公钥 K 的问题并不困难,但反过来,已知公钥 K 求私钥 k,则非常困难。这就是椭圆曲线算法上的离散对数问题,也是为什么你可以分享地址(或公钥)给别人,但不能暴露自己的私钥。

const publicKey = secp256k1.publicKeyCreate(privateKey, false).slice(1) 
publicKey.toString('hex'):  
1e3f1532e3285b02...45d91a36a8d78cb6bef8

为了形象的表现椭圆曲线算法如何将私钥推导出公钥,我们将使用简单的整数作为私钥 k,找到公钥 K = k * G,也就是 G 相加 k 次(数学原理一致)。在椭圆曲线中, 点的相加等同于从该点画切线找到与曲线相交的另⼀点, 然后映射到 x 轴。下图展示了从曲线上获得 G、2G、4G、8G 的几何操作。

什么是哈希算法?

密码学技术,也称散列函数,原理是把任意长度的输入通过哈希算法,变换成固定长度的由字母和数字组成的输出,如:钱包的地址、交易地址都是通过哈希算法运算出来的。

作为加密算法的一种,散列函数是一种单向密码体制,对于给定的哈希值,无法推倒输入的原始数据,具有不可逆性,这也是哈希算法安全性的重要基础。

目前,哈希算法主要有两类:MD系列和SHA系列。MD(Message Digest,消息摘要)系列包含MD4、MD5、HAVAL等,SHA(Secure Hash Algorithm,安全散列算法)系列包含SHA1、SHA256等。其中MD5是密码学专家R.L.Rivest设计,SHA是美国算法制定机构设计。

当我们调用 createKeccakHash("keccak256") 方法时,Keccak 使用海绵函数,对公钥与初始的内部状态做 XOR 运算得到 32 字节散列值,取其后 20 字节,转成 40 位的 16 进制字符,即为地址。

const address = 
createKeccakHash("keccak256").update(publicKey).digest().slice(-20) 
address.toString("hex"): 
7a48ac1bf3943b2ca7a4ca4999cbcbb0e999950c 

什么是区块链哈希?

在区块链系统中,构建交易数据对应的Merkle树,计算得到Merkle树根节点的区块链哈希值,区块链的哈希值能够唯一而精准地标识一个区块,区块链中任意节点通过简单的哈希计算都接获得这个区块的哈希值,计算出的哈希值没有变化也就意味着区块链中的信息没有被篡改。

Merkle树在数字货币、零知识证明、文件完整性校验等领域有广泛的应用,如:比特币以太坊系统利用Merkle proofs来存储每个区块的交易,Git也是通过Merkle树来进行完整性校验。比特币简化支付验证SPV(Simplified Payment Verification)也是使用此方式进行验证支付。

Merkle树是Ralph Merkle于1979提出,是一种哈希二叉树,在计算机科学中,二叉树是每个节点最多有两个子树的树结构,每个节点代表一条结构化数据。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现数据快速查询,是散列列表和散列链的泛化。

在线体验哈希算法:http://www.kjson.com/encrypt/hash/?fm=map

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券