区块链
区块链简介
说到比特币,就不得不提区块链。那什么是区块链呢?
区块链本质是一个数据集,只不过数据的组织采用了比较特殊的方式,就是把数据拆分为一块一块的小数据集。
为什么要进行数据拆分呢?因为区块链的作用是做为开放式的分布式的人人都可以修改的账本。这就需要防止恶意修改。
分成小的数据块之后,我们可以给每一个数据块加一个锁,要修改数据就得先找到钥匙,找钥匙的过程是一个需要大量计算过程,比特币使用的是工作量证明机制(PoW)。
区块链的链体现在什么地方呢?在于每一个小的数据库的钥匙都依赖于前一个块的钥匙,这样就形成了一个链式结构。这样做的目的是增加篡改数据的难度,降低篡改数据的可能性,因为篡改一个块的数据,就得修改这个块数据后的所有数据。
打包区块的计算
找钥匙的过程比较复杂,这里我们简化一下,首先看一下区块链的每一个块中包含的属性:
- Index:第几区块(创世区块的索引为0)。
- Hash:当前区块的Hash值。
- Previous Hash:上一个区块的Hash值。
- Timestamp:当前区块创建时的时间戳。
- Data:存储在当前区块上的交易信息。
- Nonce:参与hash运算的数值,使区块的hash值满足指定条件
function isValidHash(hash, difficulty) { for (var i = 0, b = hash.length; i < b; i ++) { if (hash[i] !== '0') { break; } } return i >= difficulty;}let nonce = 0;let hash;let input;let difficulty=4;while(!isValidHash(hash,difficulty)) { nonce = nonce + 1; input = index + previousHash + timestamp + data + nonce; hash = SHA256(input)}
钥匙就是使得就算结果满足特定条件的nonce值,难度difficuty一般值的是前缀有多少个0,比如说difficulty等于4,就是要求调整nonce的值,一般算法是从0递增,使得通过sha256之类的hash算法的结果的前缀至少包含4个0。
根据hash算法不可逆的特性我们知道不可能通过一个值来逆向计算nonce,所以大家都只能老实的做搬砖式的迭代计算。
有很多同学可能会有疑问:既然大家都只能搬砖,那肯定是力气大的先搬完啊!也就是计算能力强的计算节点会先计算出结果。
主要2点:
- 算法可以不同,比如有的人喜欢nonce每次加1,也可以每次增加其他的值,比如2
- data不同,data一般是交易,一般会有一个交易池,每一个人选取不同的交易构成data数据
通过地址逆向计算比特币私钥
椭圆曲线算法
要逆向计算比特币私钥,首先得知道什么是比特币私钥,什么是比特币的公钥。说到公钥私钥那肯定得涉及到非对称加密算法,比如RSA,椭圆曲线算法等。
比特币选择的是椭圆曲线算法:
y^2=x^3+ax+b4a^3+27b^2!=0
比特币选用的是Secp256K1参数:
a=0b=7p=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FX: 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798Y: 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
其中X\Y是生成点的横纵坐标。
椭圆曲线算法不是通过坐标解方程这么简单,而是利用椭圆曲线定义了一个群,椭圆曲线方程的作用是把几何运算转换为代数运算。
这里没有图不太好说,椭圆曲线算法这里就不详细的介绍了,可以自己搜索引擎搜索相关资料,后面介绍了一本书里面详细的介绍了椭圆曲线算法,有兴趣可以看一下。
当然页可以直接下载《以太坊智能合约开发实战》这本书的比特币章节的pdf文件,下载链接为:
提取码为:wb7k
这里简单的说一些就是使用CSPRNG生成一个随机数做为私钥,私钥做椭圆曲线乘法运算乘以生成点,转换为椭圆曲线方程的代数运算,计算得到一个椭圆曲线上的点为公钥。
私钥是一个随机的大整数,而公钥是一个点
私钥到地址
要想暴力逆向计算私钥,当然首先得了解私钥是怎么来的。
比特币的使用可以通过CSPRNG生成,当然也可以自定义,只要范围在1到n-1之间就可以了,其中n是椭圆曲线参数secp256k1中的n值。有了私钥privateKey,计算公钥就非常容易了,使用椭圆曲线乘法:
publicKey(px,py) = privateKey * G(x,y)
其中*表示椭圆曲线乘法,G是椭圆曲线参数secp256k1中指定的生成点G。
那么怎样计算地址呢?这个过程就要稍微复杂一点了,如上图所示,首先通过CSPRNG生成一个随机数作为私钥,然后通过私钥计算公钥,我们知道公钥是一个点,不好计算Hash值,所以需要做一点转换,怎样转换呢,首先拼接上一个04前缀,然后拼接公钥的横坐标,再拼接上公钥的纵坐标得到data。
然后计算data的sha256的值得到R,计算R的ripemd160得到一个extendR,extendR拼接上00前缀,然后对extendR进行2次sha256哈希计算取前4个字节,然后用extendR拼接上前面计算得到的4个字节得到data,最后对data做一次base58check编码就得到了最后的地址了。
公钥的压缩
压缩公钥是为了减少比特币交易的字节数,从而可以节省那些运行区块链数据库的节点磁盘空间。公钥是椭圆曲线上的一个点,把点转换为数字使用的方式是加上04前缀,拼接上点的横坐标x,然后再拼接上点的纵坐标y,所以公钥转换为数字有520位,其中十六进制前缀04占一个字节8位,x坐标256位,y坐标256位。 公钥是怎样压缩的呢?对于比特币来说,椭圆曲线的参数确定了,也就意味着了椭圆曲线,所以我们可以通过横坐标x就算得到纵坐标的值y。我们只需要存储点x的值就可以了,当需要纵坐标y的值的时候做一次计算就可以了。如图3.8所示,是公钥的格式获取流程图,非压缩格式加上04前缀主要是为了区分公钥有没有被压缩。
判断纵坐标的奇偶性,是因为椭圆曲线的y值计算有开方运算,所以要区分y的正负值,如果y是正数则添加02前缀,如果y是负数则添加03前缀。奇偶性判断和正负判断有什么关联呢?我们知道椭圆曲线的运算都是被限定在有限域内的,在p阶有限域内,奇偶性和正负性相关。其中p是椭圆曲线参数中指定的,比特币使用secp256k1的p值为: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F 2^256 − 2^32 − 2^9 − 2^8 − 2^7 − 2^6 − 2^4 − 1
私钥的格式
私钥有多种格式,最常见的就是十六进制格式,例如: 18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 私钥还有两种格式,一种是WIF(Wallet import format),另一种是WIF-compressed。WIF格式和WIF-compressed格式差不多,我们先来看怎样通过私钥计算WIF,相比于从私钥到地址,私钥转换为WIF格式就平易近人的多了。
首先私钥添加一个十六进制前缀80,然后计算2次sha256作为一个中间值H,再在data的最后拼接上H的前4个字节作为校验码,得到data,然后对data计算base58check就获取到了地址的WIF格式了。WIF-compressed格式和WIF格式的计算流程基本一致,只是先为私钥添加01后缀在计算。例如要把私钥: 18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 转换为WIF-compressed格式,首先添加一个01后缀,变为: 18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A20632172501 然后再执行和WIF同样的流程,获取到的就是WIF-compressed格式。因为基本和WIF流程一样,这里就不给流程图了。
逆向计算私钥示例
const bitcoin = require('bitcoinjs-lib')//找几个比特币较多的地址constrichAddrs=['16ftSEQ4ctQFDtVZiUBusQUjRrGhM3JYwe','16rCmCmbuWDhPjWTrpQGaU3EPdZF7MTdUk','183hmJGRuTEi2YDCWy5iozY8rZtFwVgahM']const N = 1000// 使用prototype方式给Array对象添加一个contains函数,用于检查是否包含指定元素Array.prototype.contains = function (obj) { var index = this.length while (index--) { if (this[index] === obj) { return true } } return false}function conclusion(){ for(let i=0;i
书籍推荐
这里推荐一本书《以太坊智能合约开发实战》,对区块链、智能合约感兴趣的同学可以看一下,书中有很多原理性的知识还是值得一看的。
书中介绍了很多东西比如P2P网络、椭圆曲线算法、智能合约等,了解P2P网络就能理解区块链的数据传递,了解椭圆曲线算法就能理解为什么计算私钥基本是不可能的。
当然也包括很多智能合约的知识,智能合约是比特币中没有的,以太坊基本是参考比特币实现的,但是最大的进步就体现在智能合约上,了解智能合约就会发现区块链真的会有很多有前景的使用场景,只需要等待技术更加成熟了就可以更好落地。