目錄算法
簡介數據庫
私鑰和公鑰安全
公鑰函數
橢圓曲線密碼學解釋區塊鏈
須知概念字體
算法解釋編碼
生成公鑰加密
簡介
比特幣的全部權是經過數字密鑰(私鑰、公鑰)、比特幣地址和數字簽名來確立的。
數字密鑰不存儲在網絡中,而是由用戶生成並存儲在一個文件或簡單數據庫中,稱爲錢包。
存儲在用戶錢包中的數字密鑰徹底獨立於比特幣協議,可由用戶的錢包軟件生成並管理,而無需區塊鏈或網絡鏈接。
密鑰實現了比特幣的許多特性:去中心化信任和控制、全部權認證和基於密碼學證實的安全模型。
每筆比特幣交易都須要一個有效的簽名纔會被鵆在區塊鏈。只有有效的數字密鑰才能產生有效的數字簽名,擁有了比特幣的密鑰副本就擁有了該帳戶的比特幣控制權。密鑰成對出現:公鑰、私鑰。
在比特幣交易的支付環節,收件人的公鑰是經過其數字指紋標識的,稱爲比特幣地址,通常狀況下,比特幣地址由一個公鑰生成並對應於這個公鑰。然而,並不是全部比特幣地址都是公鑰。
公鑰加密和加密貨幣
公鑰加密發明與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」開頭。
一樣的私鑰,不一樣的格式: