比特幣加密算法一共有兩類:非對稱加密算法(橢圓曲線加密算法)和哈希算法(SHA256,RIMPED160算法)。
比特幣私鑰(private key),公鑰(public key),公鑰哈希值(pubkeyhash),比特幣地址(address)
公鑰和私鑰由橢圓曲線加密算法生成,私鑰可推出公鑰而反之不能,這也是這篇文章后半部分要隆重介紹的部分。
有了私鑰,你就可以對文本簽名。別人拿了你的公鑰就可以根據簽名認證你是否擁有私鑰。這就是證明你擁有存款的辦法。
為了安全起見,公鑰應該隱藏起來。所以對公鑰進行哈希加密,生成公鑰哈希值然后計算哈希值的比特幣地址:
公鑰哈希值=RIMPED160(SHA256(公鑰))
比特幣地址=*1*+Base58(0+公鑰哈希值+校驗碼)
校驗碼=前四字節(SHA256(SHA256(0+公鑰哈希值)))
可以看出,地址和公鑰哈希值是等價的(可以互推)但公鑰哈希值只能由公鑰算出(不能逆推)。
驗證的時候需要提供簽名和公鑰,算出公鑰哈希值並和比特幣支出腳本的公鑰哈希值對比,最后再驗證簽名。這樣就保證了公鑰不會出現在支出腳本里。
(收入單提供簽名,支出單提供公鑰,或者收入單提供簽名和公鑰,支出單提供公鑰哈希值,這兩種驗證辦法是比特幣的標准腳本)
哈希(Hash)算法
哈希算法(又稱散列算法)不是加密解密算法,因為其加密的過程是不可逆的(你只能加密不能解密),也沒有所謂的公鑰私鑰的概念。
哈希算法原理是將一段信息轉換成一個固定長度的字符串。這個串字符串有兩個特點:
1、如果某兩段信息是相同的,那么字符串也是相同的。
2、即使兩段信息十分相似,但只要是不同的,那么字符串將會十分雜亂隨機並且兩個字符串之間完全沒有關聯。
信息可以是一串數字,一個文件,一本書。。。。。。只要能編碼成一串數字即可。
顯然,信息有無數多種而字符串的種類是有限的(因為是固定長度),所以這種加密是不可逆的。
哈希算法的用途
1、驗證兩段信息是否相同。
A使用QQ給B傳了一個文件,這個文件會在QQ的服務器上保存下來。如果C也傳了這個文件給D,QQ會對比這個文件的哈希值和A傳給B的文件的哈希值是否相同,如果相同則說明是同一個文件,C就不需要再一次上傳文件給服務器。這就是所謂的秒傳。
一個壓縮包在傳輸的時候可能會有損壞。在壓縮之前計算原文件的哈希值並放入壓縮包中,待解壓后再次計算解壓文件的哈希值。對比壓縮包中的哈希值則可以知道文件是否損壞。BT和迅雷下載中所謂的哈希驗證也是同一道理。
2、驗證某人是否信息持有者。
在一個論壇注冊帳號,如果論壇把密碼保存起來,因為無論壇多么安全都可能會被破解,所以密碼總會有泄漏的可能性。
如果不保存密碼而保存密碼的哈希加密值。當你下次登陸論壇的時候,將你輸入的密碼的哈希值和你注冊時密碼的哈希值比對,如果相同則可以證明你就是密碼持有者了。這樣既保證了密碼泄露的可能,又保證了驗證持有者的功能。
哈希算法的破解
假如論壇被破解了,黑客獲得了哈希值,但黑客只有哈希值依舊是不能登陸論壇的,他得算出用戶的密碼。
他可以隨機產生密碼一個一個試,如果算出的哈希值正好和這個哈希值相同,則說明這個密碼可用。這就是所謂的猜密碼。
顯然,密碼長度越長,密碼越復雜,猜到的可能性就越低。如果有一種辦法能增加這種猜到可能性,使其大到能夠容忍的范圍,則該哈希算法被破解了。
例如原本猜中的概率是1/10000000000000,現在增加到了1/1000。如果每猜一個密碼需要1秒,按照之前的概率猜知道太陽毀滅都可能沒猜中,但后者只需要1小時就足夠了。
另外,由於信息的種類是無限的,所以你猜中的密碼未必就是原先的密碼,它們可能是碰巧哈希值相同而已,這就是所謂的碰撞。
如同增加猜中概率一樣,如果能增加碰撞的概率,那么同樣可以輕易登陸論壇(因為論壇也不知道原本的密碼是什么,所以猜的密碼和原密碼不同也沒關系,只要哈希值相同即可)。
一旦碰撞容易輕易產生,那么哈希算法就被破解了。前幾年鬧得沸沸揚揚的哈希算法破解就是這么回事,數學家通過一定辦法增加了碰撞的概率。
哈希算法的大致加密流程
1、對原文進行補充和分割處理(一般分給為多個512位的文本,並進一步分割為16個32位的整數)。
2、初始化哈希值(一般分割為多個32位整數,例如SHA256就是256位的哈希值分解成8個32位整數)。
3、對哈希值進行計算(依賴於不同算法進行不同輪數的計算,每個512位文本都要經過這些輪數的計算)。
經過這樣處理以后,哈希值就顯得十分雜亂隨機了。
非對稱加密算法
非對稱加密算法是世界上最重要的加密解密算法。
所謂非對稱,是指加密和解密用到的公鑰和私鑰是不同的。
非對稱加密算法依賴於求解一數學問題困難而驗證一數學問題簡單。
RSA算法
著名的RSA加密算法就是利用了對一個大整數進行因數分解困難,驗證因子組成某個大整數容易的原理而編寫的。
具體說,比如求143的因子,你可能需要進行11次除法才能得到143=11*13的結果。但是要驗證11*13=143,則只需要一次乘法就夠了。
如要破解RSA,只需要能夠快速分解大整數即可,顯然這是破解RSA最簡單最快速的辦法。但要分解大整數是極不容易的(數學上叫做NP-Hard問題),這也就是RSA能保證其不能被破解的原因。
反之,如果人類某天找到了快速分解大整數的辦法(例如利用量子計算機進行計算),則RSA算法就立即被破解了。
RSA算法的大致原理
生成公鑰和私鑰:
1、生成一對大質數p,q,求出n=p*q和f=(p-1)*(q-1)。
2、生成一個隨機數e,滿足e<f且e,f互質。
3、求出e關於f的模逆d,即求出e*d=1 mod f。
設明文為m,密文為g。
用公鑰n,e加密:m^e=g mod n
用私鑰n,d解密:g^d=m mod n
證明解密后的明文就是原先的明文:
根據加密解密規則,將g=m^e mod n代入g^d=m mod n后,發現只要證明m^(e*d)=m mod n即可(同余運算的原理)。
由於e*d=1 mod f,所以只需證明m^(f+1)=m mod n即可。根據歐拉定理,f是歐拉函數所以得證。(具體的數學原理這里不再贅述)
顯然,如果知道了f,就可以根據公鑰n,e計算出d破解明文。要知道f,必須得知道p和q。要知道p和q,必須將n分解。所以RSA的破解依賴於整數分解。
如果對RSA算法感興趣,可以看這兩篇文章。
http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
橢圓曲線加密算法
試想有一種乘法,可以在已知a,b的情況下計算出c=a*b,但已知c,a不能計算出b。
我們可以利用這種乘法進行加密解密。
設明文m,密文g1,g2。
用公鑰a,c=a*b,r(隨機數)加密:
g1=m+r*c
g2=r*a
用私鑰a,b解密:m=g1-b*g2
證明:
g1-b*g2
=m+r*c-b*r*a
=m+r*c-r*c
=m
我們還可以利用這種乘法進行簽名認證。
設原文m,簽名g1,g2。
用私鑰a,b,r(隨機數)簽名:
x=r*a
g1=SHA(m,x)
g2=r-g1*b
用公鑰驗證:
g2*a+g1*c
=(r-g1*b)*a+g1*c
=r*a-g1*b*a+g1*c
=r*a-g1*c+g1*c
=r*a
=x
計算SHA(m,x)是否和g1相等。
這就是加密解密層面上的橢圓曲線加密算法。
橢圓曲線加密算法的點乘運算
如何找到這樣一種乘法是橢圓曲線加密算法的關鍵。通常的整數乘法是沒法滿足這樣的要求的。乘法來源於加法,我們必須定義新的運算規則。
例如定義a!+b=a*b,a!*b=b^a,這里的!+和!*是新定義的加法和數量乘法,於是我們得到這樣的結論:
加法交換律:a!+b=b!+a
加法結合律:(a!+b!)+c=a!+(b!+c)
加法零元素存在:a!+1=a*1=a,這里的1相當於普通加法中的0。
加法負元素存在:a!+b=a!+(1/a)=a*(1/a)=1
數量乘法單位元素存在:1!*b=b^1=b
數量乘法結合律:(a*b)!*c=c^(a*b)=c^(b*a)=c^b^a=a!*(c^b)=a!*(b!*c)
加乘法分配率:(k+l)!*a=k!*a+l!*a
加乘法分配率:k!*(a!+b)=k!*a!+k!*b
這樣的加法和乘法滿足了很多普通加法和乘法中的性質,但是卻滿足了一些特定條件,例如比原本的乘法更難根據a和c=a!*b=a^b求出b(需要對數運算)。
我們的目標是找到這樣一種加法和乘法,使其滿足前文所說的條件。數學家通過研究橢圓曲線找到了這一辦法:
設平面上兩點P(x1,y1),Q(x2,y2),則P+Q=R(x3,y3),滿足x3=k^2-2x1,y3=k(x1-x3)-y1,k=(3*x1)/(2y1)。定義k*P=P+P+P+....+P。
這樣的一套(關於平面上點的)運算法則(加法和點乘)就滿足這樣的需求。
這和橢圓曲線有什么關系呢?事實上,如果P和Q都是曲線y^2=x^3+7上的點,那么P+Q=R也是橢圓曲線y^2=x^3+7上的點並且這三個點位於一條直線上。
這並不是巧合,而是逆推出來的。亦即當P和Q是曲線上的點的時候,那么直線PQ和曲線的交點是R,求出R的坐標為(x3,y3)。
使用橢圓曲線加密算法是因為它比RSA算法更快,並且能夠實現和RSA算法類似的功能。
實際使用的時候,還需要將曲線和點離散化,並且把坐標系擴展。這涉及更多數學知識,如有興趣可參考這篇文章:
http://www.pediy.com/kssd/pediy06/pediy6014.htm
關於比特幣中橢圓曲線用到的參數,可參看這個:
https://en.bitcoin.it/wiki/Secp256k1