大家好, 首先感谢腾讯云提供云社区这样一个让技术人员沟通交流的平台, 其次很高兴入驻到云 + 社区认识到大家, 我是腾讯云 TVP 一员, 专注于云计算, 区块链, web 架构方向, myPagination 作者, GitHub 也开源了很多区块链的项目: https://github.com/linapex , 有需要的朋友可以下载学习, 本文是区块链技术实战系列的第二篇(不定期更新):
《区块链从钱包应用到技术本质》
《区块链核心技术 - 密码学》
《区块链核心技术 - P2P 网络构建》
《区块链核心技术 - 分布式一致性与共识算法》
《区块链核心技术 - 区块设计与存储》
今天我们聊一聊区块链的核心技术密码学, 区块链技术离不开密码学, 可以说密码学是区块链系统的基石之一, 我们先来了解一下.
这是以太坊黄皮书 http://gavwood.com/paper.pdf 关于钱包 (私钥, 公钥, 地址) 的描述, 仅仅 2 行文字. 主要讲解私钥通过 ECDSA(椭圆曲线签名算法)推导出公钥, 继而经过 Keccak 单向散列函数推导出地址. 分解为 3 个步骤:
1. 创建随机私钥 (64 位 16 进制字符 / 256 比特 / 32 字节)
2. 从私钥推导出公钥 (128 位 16 进制字符 / 512 比特 / 64 字节)
3. 从公钥推导出地址 (40 位 16 进制字符 / 160 比特 / 20 字节)
这是从 https://github.com/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
来源: https://www.qcloud.com/developer/article/1406196