區(qū)塊鏈科普:非對(duì)稱加密、橢圓曲線加密算法
區(qū)塊鏈加密介紹
區(qū)塊鏈加密技術(shù)
區(qū)塊鏈技術(shù)的應(yīng)用和開發(fā),數(shù)字加密技術(shù)是關(guān)鍵。一旦加密方法遭到破解,區(qū)塊鏈的數(shù)據(jù)安全將受到挑戰(zhàn),區(qū)塊鏈的不可篡改性將不復(fù)存在。
加密算法一般分為對(duì)稱加密和非對(duì)稱加密,區(qū)塊鏈中主要應(yīng)用非對(duì)稱加密算法。非對(duì)稱加密指為滿足安全性需求和所有權(quán)驗(yàn)證需求而集成到區(qū)塊鏈中的加密技術(shù)。非對(duì)稱加密通常在加密和解密過程中使用兩個(gè)非對(duì)稱的密碼,分別稱為公鑰和私鑰。非對(duì)稱密鑰對(duì)具有兩個(gè)特點(diǎn):一是用其中一個(gè)密鑰(公鑰或私鑰)加密信息后,只有另一個(gè)對(duì)應(yīng)的密鑰才能解開。二是公鑰可向其他人公開,私鑰則保密,其他人無法通過該公鑰推算出相應(yīng)的私鑰。
非對(duì)稱加密應(yīng)用場景
非對(duì)稱加密技術(shù)在區(qū)塊鏈的應(yīng)用場景主要包括信息加密、數(shù)字簽名和登錄認(rèn)證等,其中信息加密場景主要是由信息發(fā)送者(記為A)使用接受者(記為B)的公鑰對(duì)信息加密后再發(fā)送給B,B利用自己的私鑰對(duì)信息解密。比特幣交易的加密即屬于此場景。數(shù)字簽名場景則是由發(fā)送者A 采用自己的私鑰加密信息后發(fā)送給B,B使用A 的公鑰對(duì)信息解密、從而可確保信息是由A發(fā)送的。登錄認(rèn)證場景則是由客戶端使用私鑰加密登錄信息后發(fā)送給服務(wù)器,后者接收后采用該客戶端的公鑰解密并認(rèn)證登錄信息。
非對(duì)稱加密科普
密鑰配送問題
我們?cè)谄綍r(shí)生活中對(duì)我們的賬號(hào)、文件進(jìn)行加密的時(shí)候,通常都用的都是對(duì)稱密碼。所謂對(duì)稱密碼就是加密和解密用的是同一個(gè)密碼。比如我們?cè)谧?cè)自己的微信賬號(hào)時(shí),會(huì)輸入一個(gè)密碼防止別人來登錄。以后如果因?yàn)槟闶謩?dòng)退出,或者換了臺(tái)手機(jī)需要再次登錄微信的時(shí)候,只要再把這個(gè)密碼輸一遍就可以了。
對(duì)稱密碼在大多數(shù)情況下使用起來都沒有問題。但是在一些特定場合,就不那么好用了。舉個(gè)例子,如果小明想通過電子郵件給小紅寫一份情書,作為一個(gè)害羞而謹(jǐn)慎的人,他不想讓任何其他人偷看到,于是他在這封郵件中設(shè)置了一個(gè)密碼,收件人只有輸入了這個(gè)密碼才能看到郵件的內(nèi)容。假設(shè)小紅的爸爸有經(jīng)常檢查(tou kan)小紅郵件的習(xí)慣,但如果他不知道密碼,也就只能作罷?;蛘咝∶饔幸粋€(gè)情敵小強(qiáng),他是個(gè)計(jì)算機(jī)高手,能夠利用黑客手段截獲小明和小紅之間發(fā)送的郵件,但是如果郵件加了密(并且密碼強(qiáng)度足夠的話),他也只能望洋興嘆了。
但問題來了,小明怎么才能把這個(gè)密碼告訴小紅呢。如果小明在和小紅見面的時(shí)候,直接當(dāng)面告訴小紅密碼,并且約定以后兩個(gè)人的郵件往來都會(huì)用這個(gè)密碼加密,那自然是沒有問題。但是如果小明和小紅是異地戀呢。要是小明把密碼也通過一份郵件發(fā)給小紅,這個(gè)密碼就同樣有泄漏的可能,那加密郵件也就沒有任何意義了。當(dāng)然通過電話、寄信、放鴿子等等方式傳遞密碼,在理論上都有可能被手段高明的小強(qiáng)截獲。所以這就是所謂的密鑰配送難題。

非對(duì)稱加密機(jī)制
針對(duì)密鑰配送這一難題,密碼學(xué)歷史上最偉大的發(fā)明——非對(duì)稱加密(公鑰加密)出現(xiàn)了。它解決了密鑰的發(fā)布和管理問題,是目前商業(yè)密碼的核心。在公鑰加密體制中,沒有公開的是私鑰,公開的是公鑰。
和對(duì)稱密碼不同,公鑰密碼體系由加密和解密兩組密鑰構(gòu)成,他們之間是不同的。信息的發(fā)送者可以通過加密密鑰將信息進(jìn)行加密,而接收者則會(huì)用解密密鑰來進(jìn)行解密。
回到之前的那個(gè)例子,小紅同時(shí)擁有一對(duì)加密密鑰和解密密鑰。小紅把加密密鑰發(fā)送給小明,讓小明用這個(gè)密鑰把他想發(fā)的郵件進(jìn)行加密后發(fā)給小紅自己。這個(gè)加密密鑰可以通過任何方式發(fā)送,郵件、電話、微信、信鴿都沒問題,甚至可以把它貼在家門口(當(dāng)然,也沒必要這么張揚(yáng))。之所以膽子這么大,是因?yàn)檫@封被加密的郵件只有小紅通過自己手里掌握著的解密密鑰才能進(jìn)行解密讀取。也就是說,即使小強(qiáng)通過黑客手段拿到了加密郵件,并且也知道了加密密鑰,只要他不知道解密密鑰,他還是沒有辦法讀到郵件。而這個(gè)關(guān)鍵的解密密鑰是被小紅自己保管的,它不會(huì)也不需要被發(fā)送給任何其他人,甚至包括小明。
由于加密密鑰通常是可以被公開的,所以它又被稱為公鑰;而解密密鑰是不能公開的,只能由自己來使用,所以又被稱為私鑰。公鑰和私鑰是永遠(yuǎn)是成雙成對(duì)的,它們是不能分開生成的。

RSA算法
知道公鑰密碼的大致概念后,再來對(duì)它的實(shí)現(xiàn)方法作一下說明,好讓我們有一個(gè)更加直觀的認(rèn)識(shí)。公鑰密碼有很多不同的實(shí)現(xiàn)方法,其中RSA算法是最為知名的一種,也可以說是現(xiàn)在公鑰密碼的事實(shí)標(biāo)準(zhǔn),
RSA中的明文和密鑰都是數(shù)字。首先,RSA的加密公式為:
- 密文=明文^a % b
密文是將明文的a次方對(duì)b求余數(shù)的結(jié)果。任何人只要知道了a和b兩個(gè)數(shù)字,就可以通過這個(gè)公式把明文進(jìn)行加密。換句話說,a和b共同構(gòu)成了RSA加密算法的公鑰。
而RSA的解密公式
- 明文=密文^c % b
這個(gè)公式與之前唯一不同的就是把a(bǔ)換成了另一個(gè)數(shù)字c,而c和b則共同構(gòu)成了RSA的私鑰。
把數(shù)字代進(jìn)去舉個(gè)更加具體的例子,
比如,小明有一個(gè)明文數(shù)字123,想要把它加密后傳送給小紅。同時(shí)小紅手頭有一組密鑰對(duì),其中公鑰是(a=5,b=323),私鑰是(c=29,b=323)。于是小紅把公鑰發(fā)給了小明。小明通過公鑰來對(duì)明文123進(jìn)行加密計(jì)算后,得到了密文數(shù)字225,并把它發(fā)給了小紅:
- 密文=123^5 % 323=225
小紅拿到密文之后,用自己手中的私鑰進(jìn)行了解密:
- 明文=225^29 % 323=123
這樣小紅就得到了原來的明文數(shù)字123,這里有很多細(xì)節(jié)被省去了,比如其中公鑰和私鑰中的數(shù)字5,29,323不是隨便取的,而是由特定算法生成的。

區(qū)塊鏈加密算法
加密簡單而言就是通過一種算法手段將對(duì)原始信息進(jìn)行轉(zhuǎn)換,信息的接收者能夠通過秘鑰對(duì)密文進(jìn)行解密從而得到原文的過程。按照加密方和解密方秘鑰相同與否可以將加密算法大致分為三種子類型:
- 對(duì)稱加密,加密解密方使用相同的秘鑰,這種方式的好處在于加解密的速度快但是秘鑰的安全分發(fā)比較困難,常見對(duì)稱加密算法有DES,AES。
- 非對(duì)稱加密,加解密時(shí)加密方擁有公鑰和私鑰,加密方可以將公鑰發(fā)送給其他相關(guān)方,私鑰嚴(yán)格自己保留。例如銀行的頒發(fā)給個(gè)人用戶的私鑰就存儲(chǔ)在個(gè)人的U盾里;非對(duì)稱加密中可以通過私鑰加密,他人能夠使用公鑰進(jìn)行解密,反之亦然;非對(duì)稱加密算法一般比較復(fù)雜執(zhí)行時(shí)間相對(duì)對(duì)稱加密較長;好處在于無秘鑰分發(fā)問題。常見的其他非對(duì)稱加密算法有RSA,ECC。
- 對(duì)稱加密與非對(duì)稱加密的結(jié)合,這種方式將加密過程分為兩個(gè)階段,階段一使用非對(duì)稱加密進(jìn)行秘鑰的分發(fā)使得對(duì)方安全地得到對(duì)稱加密的秘鑰,階段二使用對(duì)稱加密對(duì)原文進(jìn)行加解密。

區(qū)塊鏈中主要使用非對(duì)稱加密的ECC橢圓曲線算法。
橢圓曲線加密算法
橢圓曲線長什么樣
橢圓曲線如果用公式表示的話,可以寫成下面這樣:
- y^2 = x^3 + ax + b
其中,a和b取不同的值時(shí),曲線的樣子也有所不同,比如說:

是不是感覺樣子有些怪,不管a和b取什么值,看上去都不像是橢圓形。據(jù)說橢圓曲線的名字來源于它的表達(dá)式有點(diǎn)像計(jì)算橢圓周長的積分公式,而不是說這個(gè)曲線畫出來是橢圓形~
橢圓曲線的加法和乘法
橢圓曲線的世界里,定義了一種奇怪的加法法則:任意取橢圓曲線上的兩點(diǎn)P、Q 畫一條直線,這條直線與曲線上的另個(gè)一交點(diǎn)為R',而R'關(guān)于x軸的鏡像點(diǎn)為R,那么P、Q、R這三個(gè)點(diǎn)相互之間就會(huì)形成這樣的關(guān)系:P+Q=R(其中R'=-R)。是不是有點(diǎn)特別,這個(gè)加法法則和我們平常理解的1+2=3是不同的,它建立了一種橢圓曲線上點(diǎn)和點(diǎn)之間的關(guān)系。

如果P和Q是同一個(gè)點(diǎn),姑且都叫P吧,那么我們過P點(diǎn)畫一條橢圓曲線的切線,也可以得到一個(gè)它和曲線的另一個(gè)交點(diǎn)R',而R'同樣有一個(gè)相對(duì)于x軸的鏡像點(diǎn)R,這時(shí)候的加法就變成了P+P=2P=R,也就是變成了一個(gè)乘法運(yùn)算。

再延伸一步,如果以R為起點(diǎn),還可以畫出一個(gè)新的點(diǎn)用來表示2R,也就是4P,然后再以這個(gè)新的點(diǎn)為起點(diǎn)還可以繼續(xù)畫下去……下面這個(gè)圖就是以G為起點(diǎn),畫出了2G,4G,8G的樣子。

離散橢圓曲線
上面的講解中,我們看到橢圓曲線是條連續(xù)的曲線,之所以連續(xù),是因?yàn)槲覀兪窃趯?shí)數(shù)范圍內(nèi)取值的,也就是說曲線上各個(gè)點(diǎn)的橫坐標(biāo)和縱坐標(biāo)都是實(shí)數(shù)。
可是,如果要把橢圓曲線應(yīng)用于加密,是不能用實(shí)數(shù)的。因?yàn)閷?shí)數(shù)包括了整數(shù)和小數(shù),而小數(shù)不僅會(huì)讓計(jì)算速度大幅降低,計(jì)算結(jié)果還會(huì)涉及到四舍五入的問題,從而使計(jì)算精度受到影響。由于密碼學(xué)對(duì)于速度和精度都有嚴(yán)格的要求,所以我們是沒法用實(shí)數(shù)來對(duì)信息進(jìn)行加密的。
為了讓橢圓曲線應(yīng)用于加密,必須對(duì)其離散化,說白了也就是曲線上各個(gè)點(diǎn)的橫坐標(biāo)和縱坐標(biāo)都必須是整數(shù),而且這些點(diǎn)的數(shù)量還得是有限的。讓我們舉個(gè)例子看看吧。
假設(shè)我們把橢圓曲線y^2= x^3 + x(a=1,b=0)離散化,并且規(guī)定只能取23個(gè)點(diǎn),那么這23個(gè)點(diǎn)的橫坐標(biāo)和縱坐標(biāo)必須是0-22之間的整數(shù),且橫縱坐標(biāo)之間必須滿足下面這種關(guān)系(其中%表示取余數(shù)):
- y^2 % 23 = x^3 + x % 23
如果將這23個(gè)點(diǎn)畫出來,將會(huì)變成下圖的樣子。是不是感覺和連續(xù)的橢圓曲線有些不大一樣呢。

我們可以隨便取一個(gè)點(diǎn)(9,5)來看看是不是滿足上面的公式:
- 5^2 % 23 = 9^3 + 9 % 23
- 25 % 23 = 738 % 23
- 2=2
離散橢圓曲線上的加法和乘法也遵循類似于連續(xù)橢圓曲線的規(guī)則,不過因?yàn)槎际且粋€(gè)個(gè)離散點(diǎn),其運(yùn)算過程也就沒有辦法像連續(xù)橢圓曲線中那樣形象地表示出來了。舉兩個(gè)例子感受一下吧,比如
- 加法:P(11,10)+Q(1,5)=R(17,10)
- 乘法:2P(11,10)=R(13,18)
(由于不是在上數(shù)學(xué)課,所以這里相應(yīng)的計(jì)算公式也就不再列出了,我們不去深挖細(xì)節(jié),只要知道大致原理就好)
也就是說,所有的23個(gè)點(diǎn)之間都有一種奇妙的聯(lián)系,任意兩個(gè)點(diǎn)相加,或者任意一個(gè)點(diǎn)的倍數(shù)得到的結(jié)果都會(huì)是這23個(gè)點(diǎn)中的另一個(gè)點(diǎn)。就好像這23個(gè)點(diǎn)之間形成了一套自己的封閉的數(shù)學(xué)體系。
應(yīng)用于比特幣中的橢圓曲線
那么應(yīng)用到區(qū)塊鏈中的橢圓曲線到底是個(gè)什么樣子呢?
事實(shí)上,不是所有的橢圓曲線都能夠保證足夠的安全性從而用于加密,而區(qū)塊鏈技術(shù)的最典型應(yīng)用比特幣中所使用的橢圓曲線遵循了一種叫做secp256k1的標(biāo)準(zhǔn),這個(gè)標(biāo)準(zhǔn)所定義的橢圓曲線方程是這個(gè)樣子的:
- y^2 % p = x^3 + 7 % p
其中p是一個(gè)非常非常大的素?cái)?shù):
- p = 2^256 – 2^32 – 2^9 – 2^8 – 2^7 – 2^6 – 2^4 – 1
也就是說,這是一個(gè)由p個(gè)點(diǎn)構(gòu)成的離散橢圓曲線。
使用橢圓曲線生成公鑰
說了一大堆橢圓曲線的基本原理,那么它到底是怎么應(yīng)用到比特幣中去的呢?
其實(shí),橢圓曲線在比特幣中扮演的角色說起來也很簡單,就是用來生成公鑰。
在上一篇文章中我們講到,公鑰加密體系的機(jī)制是一條信息可以通過公鑰來加密,并且通過私鑰來解密,而公私鑰必須是成對(duì)出現(xiàn)的。事實(shí)上,公鑰是由私鑰通過一定的算法計(jì)算出來的。而在比特幣中,公鑰是通過橢圓曲線算法由私鑰生成的。
具體來說,假設(shè)我們有一個(gè)私鑰k,只要將其與橢圓曲線上的一個(gè)初始點(diǎn)G相乘,就可以獲得曲線上的另一點(diǎn),也就是相應(yīng)的公鑰K。而這個(gè)乘法的計(jì)算方式用的就是我們之前所講到的運(yùn)算法則。
K(公鑰) = k(私鑰) * G(橢圓曲線上的初始點(diǎn))
事實(shí)上,初始點(diǎn)G作為secp256k1標(biāo)準(zhǔn)的一部分,是一個(gè)固定的點(diǎn),相當(dāng)于一個(gè)常數(shù)。所以,私鑰k和公鑰K之間的關(guān)系是固定的。不過,這個(gè)計(jì)算只能單向運(yùn)算,即我們可以從私鑰k得到公鑰K,但反過來就做不到了,而這就是可以把公鑰與任何人共享而不會(huì)泄露私鑰的原因。下面舉個(gè)例子,讓我們看一下比特幣的公私鑰是什么樣子。
比特幣的私鑰是一個(gè)256位的二進(jìn)制數(shù)字,通常用64位的16進(jìn)制數(shù)顯示,就像下面這樣:
- k=1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD
通過把k與橢圓曲線上的初始點(diǎn)G相乘,就會(huì)得到公鑰K(x,y),x和y分別是K的橫縱坐標(biāo),其中:
- x=F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
- y=07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB