目录算法
简介数据库
私钥和公钥安全
公钥函数
椭圆曲线密码学解释区块链
须知概念字体
算法解释编码
生成公钥加密
简介
比特币的全部权是经过数字密钥(私钥、公钥)、比特币地址和数字签名来确立的。
数字密钥不存储在网络中,而是由用户生成并存储在一个文件或简单数据库中,称为钱包。
存储在用户钱包中的数字密钥彻底独立于比特币协议,可由用户的钱包软件生成并管理,而无需区块链或网络链接。
密钥实现了比特币的许多特性:去中心化信任和控制、全部权认证和基于密码学证实的安全模型。
每笔比特币交易都须要一个有效的签名才会被鵆在区块链。只有有效的数字密钥才能产生有效的数字签名,拥有了比特币的密钥副本就拥有了该帐户的比特币控制权。密钥成对出现:公钥、私钥。
在比特币交易的支付环节,收件人的公钥是经过其数字指纹标识的,称为比特币地址,通常状况下,比特币地址由一个公钥生成并对应于这个公钥。然而,并不是全部比特币地址都是公钥。
公钥加密和加密货币
公钥加密发明与20世纪70年代。自此,一些合适的数学函数被提出。譬如:素数幂和椭圆曲线乘法。这些数学函数是不可逆的。基于这些数学函数的密码学,使得生成数字密钥和不可伪造的数字签名成为可能。
比特币正是使用椭圆曲线乘法做为其公钥加密的基础算法。
在比特币系统中,咱们用公钥加密建立一个密钥对,用于控制比特币的获取。密钥对包括一个私钥,和由其衍生出的惟一的公钥。公钥用于接收比特币,而私钥用户比特币支付时的交易签名。
支付比特币时,比特币的当前全部者须要在交易中提交其公钥和签名(每次的签名都不一样,但均从同一个私钥生成)。比特币网络中的全部人均可以经过所提交的公钥和签名进行验证,并确认该消息是否有效,即确认支付者在该时刻对所交易的比特币拥有全部权。
私钥和公钥
私钥(k)是一个数字,一般是随机选出的。有了私钥,就可使用椭圆曲线乘法这个单向加密函数产生一个公钥(K)。
有了公钥,咱们就可使用一个单向加密哈希函数生成比特币地址(A)。
●私钥(k):一个数字,随机选出。
●公钥(K):私钥使用椭圆曲线乘法算法生成。
●比特币地址(A):公钥经过单向加密哈希函数生成。
从一个随机数生成私钥
生成密钥的第一步也是最重要的一步,就是找到足够安全的熵源,即随机性来源。生成一个比特币私钥在本质上与“在1和2^256之间选一个数字”无异。比特币软件使用操做系统底层的随机数生成器来生成256位的熵(随机性)。一般,操做系统随机数生成器由人工的随机源进行初始化,也可能须要经过几秒钟内不停晃动鼠标等方式进行初始化。
更准确的说,私钥能够是1和n-1之间的任何数字,其中n是一个常数(n=1.158*10^77,略小于2^256),并由比特币所使用的椭圆曲线的阶所定义。要生成这样一个私钥,咱们随机选择一个256位的数字,并检查它是否小于n-1。从编程角度看,通常是经过在一个密码学安全的随机源中取出一长串随机字节,对其使用SHA256哈希算法进行运算,这样就能够方便产生一个256位的数字。若是运算结果小于n-1,咱们就有了一个合适的私钥。不然,就用另外一个随机数再重复一次。
比特币私钥空间大小是2^256,用十进制表示大约是10^77。而可见宇宙被估计只含有10^80个原子。
公钥
经过椭圆曲线乘法能够从私钥计算获得公钥,这是不可逆转的过程: K = k * G。
k是私钥,G是被称为生成点的常数点,而K是所得公钥。
其反向运算,被称为“寻找离散对数”--已知公钥K来求出私钥k很是困难。
椭圆曲线密码学解释
椭圆曲线加密算法是一种基于离散对数问题的非对称(或公钥)加密法,能够用对椭圆曲线上的点进行加法或乘法运算来表达。
须知概念
天然数:天然数是大于或等于0的整数,也就是非负整数,正整数.(如:0、100)
整数:任意天然数(如1,2,3,4,5)以及它们的负数或0.(如3,0,-5)
有理数:有理数是整数和分数(如2/3)的统称.(能精确地表示为两个整数之比的数)
无理数:也称为无限不循环小数,不能写做两整数之比。若将它写成小数形式,小数点以后的数字有无限多个,而且不会循环。 常见的无理数有非彻底平方数的平方根、π和e(其中后二者均为超越数)等。
实数:实数是是有理数和无理数的总称(不存在虚数部分的数).
虚数:在数学中,虚数就是形如a+b*i的数,其中a,b是实数,且b≠0,i² = - 1。虚数这个名词是17世纪著名数学家笛卡尔创立,由于当时的观念认为这是真实不存在的数字。后来发现虚数a+b*i的实部a可对应平面上的横轴,虚部b与对应平面上的纵轴,这样虚数a+b*i可与平面内的点(a,b)对应。
质数(素数):质数定义为在大于1的天然数中,除了1和它自己之外再也不有其余因数。
质数又称素数。一个大于1的天然数,除了1和它自身外,不能整除其余天然数的数叫作质数;不然称为合数。
合数:除1,0之外不是质数的正整数就是合数。
互质:互质是公约数只有1的两个整数,叫作互质整数。公约数只有1的两个天然数,叫作互质天然数,后者是前者的特殊情形。
对数:在数学中,对数是对求幂的逆运算。
若是a的x次方等于N(a>0,且a不等于1),那么数x叫作以a为底N的对数(logarithm),记做x=logaN。其中,a叫作对数的底数,N叫作真数。
同余运算:若是 a 和 b 除以 p 的余数相同,则说 a 和 b 关于模 p 同余。
a≡b(mod p) ÍÎ a mod p = b mod p
参考:https://blog.csdn.net/qq_35546304/article/details/53025685,http://www.matrix67.com/blog/archives/236
原根:原根是一种数学符号,设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数)
假设一个数g是P的原根,那么g^i mod P的结果两两不一样,且有 1
g^(P-1) 和1是关于P的同余。
g^i mod p ≠ g^j mod p (p为素数),其中i≠j且i, j介于1至(p-1)之间,则g为p的原根。
同阶:等价商为一,同阶商为一个常数。
阶:
设 (a,m)=1, 知足 ax≡1(mod m) 的最小的 x,称为a对m的阶,记为ordm(a)。
当 ordm(a)=ϕ(m) 时称为a为m的原根。
离散对数:在整数中,离散对数(英语:Discrete logarithm)是一种基于同余运算和原根的一种对数运算。而在实数中对数的定义 logba是指对于给定的a和b,有一个数x,使得bx=a。相同地在任何群G中可为全部整数k定义一个幂数为bx,而离散对数logba是指使得bx=a的整数k。
离散对数和原根:参考:https://blog.csdn.net/dylan_frank/article/details/70249110
算法解释
上图是一个椭圆曲线示例,相似于比特币所用的曲线。
比特币使用了secp256k1标准所定义的一条特殊的椭圆曲线和一些列数字常数。该标准由国美国家标准与技术研究院(NIST)设立。secp256k1曲线由下述函数定义,该函数可产生一条椭圆曲线:
由于这条曲线被定义在一个素数介的有限域内,而不是定义在实数范围,它的函数图形看起来像分散在两个维度上的散点图,所以很难画图表示。不过其中的数学原理与实数范围的椭圆曲线类似。做为一个例子,下图显示了在一个小了不少的素数阶17的有限域内的椭圆曲线,其形式为网络上的一系列散点。而specp256k1的比特币椭圆曲线能够被想象成一个极大的网格上一系列更为复杂的散点。
图为:椭圆曲线密码学F(p)上的椭圆曲线,其中p=17。
在椭圆曲线的数学原理中,有一个点被称为“无穷远点”,这大体对应于0在加法中的做用。计算机中,它有时表示为X=Y=0(虽然这不知足椭圆曲线方程,但可做为特殊状况进行校验)。还有一个+运算符,被称为“加法”,就像实数相加。给定椭圆曲线上的两个点P1和P2,则椭圆曲线上一定有第三个点P3=P1+P2。
几何图形中,该第三点P3能够在P1和P2之间画一条线来肯定。这条直线刚好与椭圆曲线上的一点相交,此点记为P3'=(x,y)。而后,在x轴作映射得到P3 = (x,-y)。
能够解释“无穷远点”之存在须要的特殊状况:
- 若P1和P2是同一点,P1和P2间的连线则为P1的切线。曲线上有且只有一个新的点与该切线相交。该切线的斜率可用微分求得。即便限制曲线点为两个整数坐标也可求得斜率!
- 在某些状况下(即,若是P1和P2具备相同x值,但不一样y值),则切线彻底垂直,在这种状况改下,P3=“无穷远点”。
- 若P1就是“无穷远点”,那么P1+P2=P2。相似P2是无穷远点,则P1+P2 = P1。这是把无穷远点相似于0的做用。
事实证实,在这里+运算复合结合律,这意味着(A+B)C = A (B+C).这就是说咱们能够直接不加括号书写A+B+C,而不至于混淆。
咱们已经定义了椭圆加法,为了扩展加法,咱们对乘法进行标准定义。给定椭圆曲线上的点P,若是k是整数,则kP = P+P+...+P(k次)。注意,k有时被混淆而称为“指数”。
生成公钥
以一个随机生成的私钥k为起点,咱们将其与曲线上已定义的生成点G相乘已得到曲线上的另外一点,也就是相应的公钥K。生成点是secp256k1标准的一部分,比特币密钥的生成点都是相同的:
K = k * G
全部比特币用户的生成点是相同的,一个私钥k乘以G将获得相同的公钥K。k和K之间的关系是固定的,但只能单向运算,即从k获得K。这就是能够吧比特币地址(k的衍生)与任何人共享而不会泄露私钥(k)的缘由。
为实现椭圆曲线乘法,咱们将以前生成的私钥k和与生成点G相乘获得公钥K:
K = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD * G
公钥K被定义为一个点K = (x,y):
K = (x, y)
其中:
x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB
为了展现整数点的乘法,咱们将使用较为简单的实数范围的椭圆曲线。目标是找到生成点G的倍数kG。也就是将G相加k次。
在椭圆曲线中,点的相加等同于从该点画切线找到与曲线相交的另外一点,而后映射到x轴。
上图显示了在曲线上获得G、2G、4G的几何操做。
大多数比特币程序使用OpenSSL加密库进行椭圆曲线计算。例如,调用EC_POINT_mul()函数,能够计算获得公钥。
比特币地址
比特币地址是一个由数字和字母组成的字符串。由公钥(一个一样由数字和字母组成的字符串)生成的比特币地址以数字“1”开头。例如:
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
比特币地址可由公钥通过单向的加密哈希算法获得。哈希算法是一种单向函数,接收任意长度的输入产生指纹摘要。
加密哈希函数在比特币中被普遍使用:比特币地址、脚本地址以及在挖矿中的工做量证实算法。(私钥、地址均是使用SHA256生成,而公钥是私钥经过椭圆算法生成)
由公钥生成比特币地址时使用的算法是(SHA)和(RIPEMD),别特是SHA256和RIPEMD160。
以公钥K为输入,计算其SHA256哈希值,并以此结果计算RIPEMD160哈希值,获得一个长度为160比特(20字节)的数字:
A = RIPEMD160(SHA256(K))
比特币地址与公钥不一样,比特币地址时由公钥通过单向的哈希函数生成的。
一般用户看到的比特币地址是通过Base58Check编码的,这种编码使用了58个字符(一种Base58数字系统)和校验码,提升了可读性、避免歧义并有效防止了在地址转录和输入中产生的错误。
Base58和Base58Check编码
Base64
使用了26个小写字母、26个大写字母、10个数字以及两个符号(例如“+”和"/"),用于在电子邮件这样的基于文本的没接找那个传递二进制数据。Base64一般用于编码邮件中的附件。
Base58
是一种基于文本的二进制编码格式,用在比特币和其余的加密货币中。
这种编码格式不只实现了数据压缩,保证了易读性,还具备错误诊断功能。
Base58是Base64的子集,一样使用大小写字母和10个数字,但舍弃了一些容易错读和在特定字体中容易混淆的字符。
具体的,Base58不含Base64中的0(数字0)、O(大写字母O)、l(小写字母L)、I(大写字母i)、以及"+"和"/"两个字符。简而言之,Base58就是不包括(0,O,l,I)的大小写字母和数字组成。
例:比特币的Base58字母表:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
Base58Check
一种Base58格式的、有版本的、通过校验的格式,能够明确的对比特币数据编码的编码格式。
是一种经常使用在比特币中的Base58编码格式,增长了错误校验码来检查数据在转录中出现的错误。
检验码长4个字节,添加到须要编码的数据以后。校验码是从须要编码的数据的哈希值中获得的,因此能够用来检测并避免转录和输入中产生的错误。
使用Base58check编码格式时,编码软件会计算原始数据的校验码并和结果数据中自带的检验码进行对比。两者不匹配则代表有错误产生,那么这个Base58Check格式的数据就是无效的。
实现是:在encode前,在输入流尾部加入输入内容的hash值(4个字节)。而后再对输入流进行 Base58Encode。
在 decode 时候:先 Base58Decode, 而后拆成两部分(内容和校验值),判断对内容计算的校验值和校验值字段是否一致。
为了使用Base58Check编码格式对数据(数字)进行编码,首先咱们要对数据添加一个称做“版本字节”的前缀,这个前缀用来明确须要编码的数据的类型。例如,比特币地址的前缀是0(十六进制0x00),而对私钥编码时前缀是128(十六进制是0x80)。
接下来,咱们计算“双哈希”校验码,意味着要对以前的结果(前缀和数据)进行两次SHA256哈希算法:
checksum = SHA256(SHA256(prefix+data))
在产生的长32个字节的哈希值(两次哈希运算)中,咱们只取前4个字节。这4个字节就做为校验码。校验码会添加到数据以后。
结果由三部分组成:前缀、数据和校验码。这个结果采用以前描述的Base58字母表编码。
下图描述了Base58Check编码的过程:
在比特币中,大多数须要向用户展现的数据都是用Base58Check编码,能够实现数据压缩,易读并且有错误校验。
Base58Check编码中的版本前缀是数据的格式易于辨别,编码以后的数据头包含了明确的属性。这些属性使用户能够轻松明确被编码的数据的类型以及如何使用它们。
Base58Check编码的比特币地址时1开头的;
Baase58Check编码的私钥WIF是以5开头的。
Base58Check版本前缀和编码后的结果:
私钥(SHA256)-> 公钥(椭圆曲线上的某个点)-> 两次哈希(SHA256)的校验码+Base58Check格式的比特币地址。
密钥的格式
私钥的格式
私钥能够以许多不一样的格式表示,全部这些都对应于相同的256位的数字。以下有三种常见格式:
以下展现了上面三种格式所生成的私钥:Hex是16进制的32位=16*32=256位
每种格式之间能够相互转换。
公钥的格式
公钥格式分为非压缩格式或压缩格式公钥两种。
公钥是椭圆曲线上的一个点,由一对坐标(x,y)组成。
公钥一般为前缀04紧接着两个256比特(位)的数字。其中一个256比特数字是公钥的x坐标,另外一个是y坐标。前缀04用来区分非压缩格式,02或03开头是压缩格式。
压缩格式公钥
引入压缩格式公钥是为了减小比特币交易的字节数,从而能够节省那些运行区块链数据库的节点磁盘空间。
大部分比特币交易包含了公钥,用于验证用户的凭据和支付比特币。
每一个公钥有520比特(包括前缀、x坐标,y坐标)。
一个公钥是一个椭圆曲线的的点(x,y)。而椭圆去选实际是一个数学方程,曲线上的点实际是该方程的解。
所以,若是咱们知道x坐标,就能够经过方程:
获得y坐标。这种方案可让咱们只存储公钥的x坐标,略去y坐标。从而将公钥的大小和存储空间减小了256比特。每一个交易所需的字节数减小了近一半。
未压缩格式公钥使用04座位前缀,压缩格式公钥是以02或03做为前缀。
须要两种不一样前缀的缘由:由于椭圆曲线加密的共识左边是y^2,也就是说y的解来自一个平方根,多是正值也多是负值。更形象说,y坐标可能在x坐标轴上面或者下面。当给定x,咱们须要知道y值在x轴上仍是下,由于它们表明椭圆曲线上不一样的点,即不一样的公钥。当咱们在素数(质数)P阶的有限域上使用二进制算术计算椭圆曲线时,y坐标多是奇数或者偶数,分别对应y的正负符号。所以,为了区分y坐标两种可能值,在生成压缩格式公钥时,若是y是偶数,就用02做为前缀;若是是奇数,就用03 做为前缀。
下图阐述了公钥压缩:
压缩格式公钥和非压缩格式公钥对应同一个私钥。可是使用双哈希函数(RIPEMD160(SHA256(K)))将压缩格式公钥转化为比特币地址获得的值和非压缩格式公钥转化出的比特币地址不一样。两个地址都合法。
压缩格式公钥逐渐成为大部分比特币客户端的默认格式。可是若是出现新老客户端兼容问题(有的支持压缩,有的不支持压缩,那么同一个私钥对应两个不一样的比特币地址,并且两个地址都合法)。
为了解决这个问题,当私钥从钱包中被导出时,较新的比特币客户端将使用一种不一样的钱包导入格式(Wallet import Format)。这种新的钱包导入格式能够用来表名该私钥已经被用来生成压缩的公钥,同时生成比特币地址也是基于该压缩公钥。
压缩格式私钥
“压缩格式私钥”是一种名称上的误导,由于当一个私钥被使用WIF压缩格式导出,不但没有压缩,并且比“非压缩格式私钥”长一个字节。这个多出来的一个字节是私钥被加了后缀01,用以表示该私钥是来自一个较新的钱包,只能被用来生成压缩的公钥。私钥是非压缩的,也不能被压缩。“压缩的私钥”实际上只是表示“用于生成压缩格式公钥的私钥”。
另外,这些格式并非刻意互换使用的。在较新的实现了压缩格式公钥的钱包中,私钥只能且永远被导出为WIF压缩格式(以K或L为前缀)。对于较老的没有实现压缩格式公钥的钱包,私钥将只能被导出为WIF格式(以5为前缀)导出。
若是一个比特币钱包实现了压缩格式公钥,那么它将会在全部交易中使用该压缩格式公钥。钱包中的私钥将会被用来生成压缩格式公钥,压缩格式公钥而后被用来生成交易中的比特币地址。当一个实现了压缩格式公钥的比特币钱包导出私钥时,钱包导入格式(WIF)将会被改成WIF压缩格式,该格式将会在私钥后面附加一个字节大小的后缀01。
最终的Base58Check编码格式的私钥被称做WIF(“压缩”)私钥,以字母“K”或“L”开头。
一样的私钥,不一样的格式: