比特币原理整理(一)

随声附和 提交于 2019-11-28 19:35:56

        前几天研究了一下比特币,对这几天的研究结果做一个总结,里面有些内容是我自己的一些理解,如果有错误望指正,谢谢。

        现在比特币这个词有多种含义,可能指代的是一种数字货币,也可能指代的是其底层的存储方式-区块链。本文中也不做区分,根据上下文文意,比特币可能表示数字货币,也可能表示区块链。

        比特币是由中本聪发明的,中本聪这个名字可能是一个化名,其发表了一篇关于比特币的论文:《⽐特币:⼀个点对点的电⼦现⾦系统》,从此比特币正式进入人们的视野。2009年,开发人员将比特币进行了实现。

        比特币使用分布式账簿记录网络中出现的每一笔交易。既然是分布式的账簿,也就意味着这个账簿会在网络中的很多机器上存储,网络中的机器使用P2P协议进行通信,将各自存储的账簿进行统一。网络中发生的交易也是通过P2P协议发送到网络中的其他机器上。比特币网络中没有所谓的中央管理机构,各个机器都是自主验证交易合法性,并将合法交易记录到分布式账簿中。

        比特币中还涉及到公钥、私钥和地址的概念。每一个比特币交易都必须含有比特币持有人的私钥数字签名,否则比特币网络是不会接收该交易的。公钥在比特币网络中是公开的,用于对交易的合法性进行验证。地址用于表示收款人的地址。

        上面这些是一些基础内容,我觉得有了上面这些基础知识就足够了。

        我们作为一个普通用户使用比特币时,首先需要申请一个比特币的私钥。私钥是其实就是一个随机数,它是位于1--1.158*10^77-1之间的一个数,1.158*10^77略小于2^256(为什么选取小于2^256的一个数字作为上限,没有从网上找到答案)。所以私钥占256bit的空间。私钥是由比特币的客户端完成的,不要我们去干预。下面是私钥的一个例子:1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD,这个私钥按16进制显示。

        通过私钥使用椭圆曲线算法可以得到公钥。椭圆曲线算法是在一个曲线上找到一个点,这个点的坐标就是公钥(本人数学功底so so,想知道这个算法的可以网上搜)。依据上面的私钥可以得到公钥:

       x =F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A

       y =07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB

    但是这个算法有一个很奇妙的地方就是通过公钥无法得出私钥。我觉的这就是数学很奇妙的地方,由A可以得到B,但是B无法得出A。当得到了公钥之后,下面就要生成比特

币的地址了。比特币的地址是由数字和字母组成的,但是密钥完全是由数字(上面有字母是因为使用16进制编码的原因)组成的,记住这点不同。比特币地址的例子如下:

1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy

    比特币地址有一个特点:地址都是“1”开头的。这可能和下面的哈希计算有关。下面这个公式中我们以公钥作为输入,输出结果就是比特币地址:

    A =RIPEMD160(SHA256(K))

    上面这个公式涉及到两个不同的哈希算法:SHA256和RIPEMD160,英文全称是Secure Hash Algorithm (SHA)和the RACEIntegrity Primitives Evaluation Message Digest(RIPEMD)。

    但是A并不是我们最后见到的比特币地址,下面还需要使用Base58Check对A进行编码,编码之后和上面的地址一样了。Base58Check是从Base58变化而来的,只不过在Base58的基础上添加一个校验码。要生成最后的比特币地址,还需要两样东西:版本前缀,校验码。在比特币中,有下列数据使用Base58Check编码前需要添加版本前缀:


       上图中的第一行就是比特币地址,版本前缀为0x00。校验码是根据下面的式子得到的:

checksum= SHA256(SHA256(0x00+A))

       上述公式中两次使用SHA256进行哈希。然后区checksum的前四个字节作为校验码,添加到A的后面。然后在使用Base58编码,编码后的结果就是比特币地址。

 

 

       还有一点需要注意:通过比特币地址是无法推算出公钥的。

       下面来看一下由私钥生成比特币地址的流程:

 

 

上述流程反过来不成立,也就是后者无法计算得出前者。

名称

长度

私钥

256bit

公钥

非压缩:520bit(前缀占8比特,两个坐标各256bit)

压缩:264bit(前缀占8比特,x坐标占256bit)

地址

Base58Check编码前,A长度是160bit,编码后长度不固定

       上表中提到公钥的前缀占8个字节。公钥有三个前缀,分别是0x02、0x03、0x04,其中0x04是一般公钥,也就是非压缩公钥添加的前缀,其他两个前缀下面会介绍。

公钥占据的空间特别大,所以需要对公钥进行压缩。压缩前的公钥添加前缀后表示为0x04xy,其中x、y代表了公钥的两个坐标。因为公钥其实是某一个椭圆曲线上的一个点,当知道其中一个坐标时,完全可以计算得出另一个坐标。所以我们可以对公钥进行压缩,在公钥中只包含一个坐标即可。由椭圆的特性,我们可以知道通过x可以计算得到一正一负两个y,所以我们就需要添加一个标志用于区分y值的正负。上面提到的前缀0x02、0x03就是用于区分正负的。正负是我自己的理解,算法中并不是这样描述的,算法中说的是用0x02、0x03区分y的奇偶性。但是意思是一个意思。压缩之后的公钥就变成了:

0x02x或者0x03x

除了公钥压缩之外,还有私钥压缩这种说法。注意私钥压缩只是一种误传,其实只是私钥的一种表示方式。私钥被比特币客户端导出时,只能以WIF格式或者WIF压缩格式导出。我理解的导出其实就是我们可以直接在客户端看到的格式或者导出到一个文件中。上面提到了两种不同的公钥表示方法:压缩公钥和非压缩公钥。对于这两种公钥,我们都可以生成对应的比特币地址,但是两个地址是不一样的。对于一些比较新的客户端使用的是压缩公钥,对于一些旧的客户端使用的是非压缩公钥。这就带来了一个问题:如果一个客户端使用的是非压缩公钥,从该客户端将私钥导出在导入到一个新的使用压缩公钥的客户端中时,该新的客户端从私钥计算出公钥然后再计算出地址就与旧客户端上的地址不一致了,这就会导致用户资金损失。为了解决这个问题,我们在私钥上加了后缀0x01。当客户端看到后缀为0x01的私钥时,就知道这个需要使用压缩公钥导出地址。但是使用0x01又会出现另一个问题:如果当前私钥中正好有0x01,但是这个0x01就是私钥中本来就有的,需要使用非压缩公钥导出地址。对于这个问题我想的解决办法是:通过判断私钥的长度即可解决。回到本段开始说的问题,人们误传的压缩私钥指的就是加了后缀0x01的私钥。

下面介绍一下导出WIF格式私钥的流程(其实就是Base58Check编码过程):

 

       WIF压缩格式的私钥是在私钥PK上加上后缀0x01然后重复上述流程。因为有固定的前缀和后缀,所以WIF格式的私钥和WIF压缩格式的私钥都有相同的开头:

种类

开头内容

WIF

5

WIF压缩

K或者L

 

       下一篇介绍交易的编码方式。

 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!