高深的密碼學+複雜的區塊鏈,其實也能夠通俗易懂

密碼學,在不少人看來是極爲高深、只有數學家才能玩轉的技術科學,不清楚如何才能應用於實際開發的過程當中。本文將結合應用密碼學比較深刻的區塊鏈,從掃盲、實戰,再到實驗、提升,一層層剝開密碼學的「神祕面紗」。java

 

【掃盲班—密碼算法解析】

若是您仍是密碼學小白,那你須要先簡單瞭解一下經常使用的密碼算法:對稱加密、非對稱加密、數字簽名和摘要算法。

<對稱加密>
對稱加密又叫傳統密碼算法,就是加密和解密使用同一個密鑰。潛伏裏面孫紅雷經過電臺收聽到一堆數字,而後拿出一本書(密碼本)比對,找到數字對應的漢字,就明白上級傳達的是什麼指令了。而軍統的監聽臺沒有密碼本,只看到一堆沒有意義的數字。

用數學公示表示就是:
▲加密:Ek(P) = C
▲解密: Dk(C) = P

這裏E表示加密算法,D表示解密算法,P表示明文, C表示密文。留意之後會常常看到。常見的對稱加密方法有DES、3DES、Blowfish、RC二、AES以及國密的SM4。

有同窗會問,什麼是國密啊?很機密麼?沒那麼誇張,其實它的全稱叫「國家商用密碼」,是爲了保障商用密碼安全,國家商用密碼管理辦公室制定了一系列密碼標準。


<非對稱加密>
對稱加密又快又方便,可是有個很大的坑——密碼本容易被偷或被破解。從紅軍到二戰,勝利的最大貢獻其實就是破解密碼。紅軍在數十倍的包圍圈裏面自由跳來跳去,那兩臺大功率電臺功勞莫大。
 
怎麼可以防止這種狀況呢?1977年三位數學家Rivest、Shamir 和 Adleman 設計了一種算法(因此叫RSA),把密鑰分紅兩個,一個本身持有叫私鑰(Private Key),另外一個發給對方,還能夠公開,叫公鑰(Public Key),實現用公鑰加密的數據只能用私鑰解開:
▲加密: E公鑰(P) = C
▲解密: D私鑰(C) = P

這下就不用再頭痛如何把密碼本給對方或被破解了,私鑰由本身保管,敵方攔截到密文也沒有辦法。
 
除了RSA以外,常見的非對稱算法還有Elgamal、揹包算法、Rabin、D-H、ECC(橢圓曲線加密算法)以及國家商用密碼SM2算法。

非對稱算法核心原理其實就是設計一個數學難題,使得用公鑰和明文推導密文很容易,可是很難根據公鑰、明文和密文推導私鑰。
 
RSA是基於大整數因式分解難度,也就是兩個質數相乘很容易,可是找一個大數的質因子很是困難,理論上破解RSA-2048(2048-bit)的密鑰可能須要耗費10億年的時間。
 
這兒說點題外話:強烈不建議使用RSA,緣由以下:
▲容易被破解:RSA-768能夠在3個小時內破解,1024在理論上100小時內也能夠破解。因此使用RSA,長度起步要2048。可是數學家彼得·舒爾研究了一個針對整數分解問題的量子算法 (舒爾算法),理論上破解2048的RSA在100秒以內(好在量子機還未投入使用)。
▲慢:密鑰長度加到2048能夠提高安全,可是計算過慢。


<數字簽名>
有了非對稱加密,數字簽名就很容易理解了。
 
乙方收到甲方傳過來的一串信息,怎麼可以肯定確實是甲方而不是有人僞造呢?
 
咱們把非對稱加密反過來作就能夠了,由於只有甲方本身才持有一份祕密的私鑰,他拿這個私鑰對數據進行加密獲得密文 C = EA私(M),乙方持有甲方的公鑰,解密明文P = DA公(C),若是可以解密成功就證實信息確實是甲方所發。

不過一般不須要對發送信息的整個內容都加密,那樣太慢。只須要計算一個信息的惟一信息摘要並對信息摘要加密解密便可,下面就會講到數據摘要算法(俗稱HASH算法),這也是數字簽名的算法名稱,不少時候是一個摘要算法+非對稱算法,例如SHA1RSA, SHA256RSA等。


<摘要算法>
俗稱HASH算法,學名雜湊算法,也就是從明文P生成較短的固定長度的雜湊值,保證不一樣的輸入產生的輸出是惟一的(重複概率很是很是小)。這樣就能夠普遍用於完整性檢查、數字簽名等場景。
 
常見的摘要算法有MD五、RIPEMD、SHA和國密的SM3。MD5不建議使用,已經被爆。

android

【實戰班—區塊鏈應用】git

區塊鏈提供了經過機器算法解決參與人之間的信任問題的全新方案,其核心的核心就是在不徹底信任的各方,經過深度使用密碼學算法來保證數據的不可篡改特性。
 
本節結合實際區塊鏈中的應用,讓你們在瞭解區塊鏈的同時,一塊兒驚歎原來加密算法還能夠這麼用。

<比特幣之誰能動個人錢>
比特幣是公有鏈,帳本分佈在無中心的節點上,任何一個節點均可以發出一個轉讓比特幣的交易。那個人比特幣是如何保證不被別人轉走的呢?
 
假設你擁有100比特幣(好有錢喲),那麼在公開帳本上存有一個數據結構,即所謂的UTXO,其主要內容有:
▲index: 索引
▲value: 金額
▲hash:一個SHA256的數據摘要
▲script: 腳本,這個是重點要講的
 
這個script是一串可執行的二進制代碼,比特幣定義了一個基於堆棧的腳本執行器,能夠執行加減乘除、移位、HASH、驗籤等算法,相似於常見的科學計算器。當你想花費持有的比特幣時,首先須要執行做爲輸入交易對應UTXO的腳本(script),稱之爲「解鎖腳本」,只有執行成功才能繼續。

最經常使用的一個解鎖腳本就是P2PKH腳本:


解鎖時傳入簽名和公鑰組成完整腳本:


翻譯起來就是: 「公鑰的HASH160等於<腳本里面的值>而且用這個公鑰對HASH值驗證簽名可以經過」。計算經過,才能夠花費這筆資金。
 
由於私鑰保存在你本身手上,其餘人沒法計算出一個知足條件的簽名,從而保證了這筆資金只有你本身可使用。

這裏除了數字簽名外,還有一點體現了中本聰真的很聰明,帳本上不會存儲你的公鑰,而是其HASH160(雙HASH,SHA256+RIPEMD160),因爲HASH是單向的,從HASH沒法反向推導公鑰,這樣大大減小將來量子機會帶來的風險。

<區塊鏈-HASH鏈之如何防止篡改>
前面講了數字簽名在比特幣的用法,這裏結合區塊鏈數據結構自己講一下HASH的用法。
 
一個塊只是組織數據的結構,這裏暫不詳述,關鍵是塊裏面有個重要的參數 – 前一塊的HASH,這樣就造成一個鏈式結構。
 
咱們把數據豎起來看,就像是玩積木遊戲,節點你一塊我一塊向上羅,每一塊和前一塊都有個鉤子。若是這個時候有人試圖篡改以前的一筆交易,勢必會致使那個塊的HASH變了,那爲了使得改過的交易被你們承認,他能夠以這個被改過的塊爲起點,從新計算後面全部的塊,關鍵是還得比拼得過全世界其餘的節點,目前還沒人可以作到。

這裏就突出了HASH算法的特色:
▲數據改變一點點,HASH改變很是大。
▲沒法給不一樣的數據計算出相同的HASH(或者說很是難)。

<比特幣和以太坊的公私鑰—ECC算法>
RSA又慢又不安全,因此比特幣和以太坊都不採用,而是使用了更安全的橢圓曲線算法 – ECC來作非對稱加密基礎算法。ECC的210位算法難度就至關於RSA 2048的難度,性能則是數量級的區別。那麼橢圓算法又是何方神聖呢?
 
前面講過非對稱算法無非是設計一個數學難題,使得單向計算很方便,而反向計算很難,如RSA使用因式分解的原理,兩個大質數相乘很容易,但大數分解質因子很難。
 
橢圓算法ECC其實就是利用乘法容易,而除法難的特色,設計一個乘法:K = k * G,其中大K是公鑰,小k是私鑰,G是生成點。由私鑰推導公鑰很容易,只須要k個G相加便可。可是從公鑰推導私鑰很難,也就是沒法計算公鑰K除以G。

固然這個加法不能用咱們平常的整數加減法,而是利用函數 所定義的一個特殊橢圓曲線上散列點的特性定義的加法。其中p是一個常數。不一樣p能夠設計成不一樣的曲線,比特幣使用的p = 2256 – 232 – 29 – 28 – 27 – 26 – 24 – 1,這個曲線的名稱就叫secp256k1。這是一個很是大的數,曲線上的點是一個複雜散點,爲了方便展現,這裏用小不少的17階曲線表示加法的定義:
github

 

加法定義就是曲線上任意兩個點P1和P2,必有第三個點P3,是P1和P2連線的延長線與曲線相交點的x軸映射的點,定義P1+P2=P3。經過數學算法能夠證實這種點知足加法乘法交換律:
▲A + B +C = A + (B + C)
▲A*(B+C) = A*B + A*C

暫且不進行證實贅述,須要說明的是這裏爲了完善計算還定義了無窮遠點O(至關於0),知足:P1 + O = P1。(思考一下:若是P1 + P2 = O,那麼P1 = -P2了嗎?)

ECC加密過程:
▲K = k * G, 大K是公鑰,小k是私鑰;
▲把明文編碼成曲線上的點M;
▲生成一個隨機數r;
▲計算密文C1=M + r*K, C2 = r*G,其中大K是公鑰;
▲對方收到密文後,能夠計算C1 - kC2 = M,其中小k是私鑰;
▲攻擊者獲得C一、 C2,公鑰K以及基點G,沒有私鑰是沒法計算出M的。
 
ECC算法用很短的密鑰就能達到RSA2048的安全強度,並且計算速度有數量級的提升,因此目前應用很廣泛,國密中的SM2就是基於ECC算法的。算法

 

【實驗班-如何使用算法】

這些算法感受仍是挺複雜的,咱們小白能用起來麼?

不要只說不練,咱們就實際操刀體驗一下。

實際上是別人把框架和算法都寫好的啦,好比JAVA,在JDK裏面就集成了Java密碼學框架 (Java Cryptography Architecture - JCA),直接拿來用就好了,其餘如C#,C++甚至JavaScript都有相似的。安全


<對稱加密>數據結構

把大象關進冰箱須要三步,把明文轉成密文也只須要四步:
▲生成一個密鑰(若是已經有密鑰,這步也省了),如:
框架

▲取一個加密器: ide

▲初始化成加密模式: 函數

▲加密:

怎樣把密文解密呢?初始化成解密模式就能夠了。

SM4是國密4算法,初始化的時候斜槓後面的ECB、PKCS7…是什麼?那是由於SM4是分組算法,在加密的時候會把明文先分紅固定長度段,那就須要定義分組的模式和填充模式,只要加密解密用一樣的模式就好了。固然不一樣的分組和填充模式各自有特色,那超出本文範圍了,有興趣的同窗自學吧。

<非對稱加密>

複習一下非對稱加密和對稱加密有什麼區別啊?密鑰分紅公私鑰對。

 

因此和對稱加密區別只是:

▲在生成密鑰的時候是一對,叫KeyPair。
▲加密的時候用一個如公鑰,解密用另外一個。


<摘要算法>
和加密提供了Cipher幫助類同樣,HASH算法Java提供了MessageDigest幫助類,只須要調用getInstance就能夠獲取一個實例:

其參數是HASH算法,如SHA-256, SM3, MD5等。


調用update方法設置內容,而後調用digest就拿到HASH了。

 

<數字簽名>
簽名:

驗籤:

又比大象多一步。

 

<內參必讀>

有幾個要點在實際使用過程當中必需要注意。

 

▲JDK自帶的JCE實現算法不全

這裏有兩個緣由:
(1)國家安全出口保護規定(美國)
根據美國安全出口規定,不能對某些國家出口RSA204八、AES256等以上安全算法。解決辦法是到JDK的下載站上下載Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy,解壓縮到JRE的lib/security下便可。


(2)國密和擴展算法缺失
免費提供的不能強求,不過仍是有不少開源和商用的加密組件,這裏推薦使用Bouncy Castle,雖然不是最快的,可是徹底開源,支持C#, C++, Java多種語言。


把Bouncy Castle集成到JRE有兩種方法,一種是修改JRE的java.security增長一個Provider,另外一種直接在代碼初始化的時候調用Security.addProvider加進去便可:

 

▲Android 使用Bouncy Castle注意

Bouncy Castle(BC)很強大,Google的android內核也集成了。可是,因爲安全要求,這個加密包是閹割過的,本身再集成BC又致使包衝突。


解決辦法是換個包名,到https://rtyley.github.io/spongycastle/能夠獲取。

 

【提升班-隱私保護】

因爲區塊鏈是在非徹底信任的一組參與人之間,經過算法解決信任問題,以前講述的算法保證了數據不可篡改,只有本身才能夠操做本身的數據,可是還欠缺一個很重要的課題 – 隱私。

隱私和不可篡改其實有些相互矛盾,要實現不可篡改,就得讓其餘人來驗證數據,好比公有鏈是全網用戶都來驗證;可是隱私又想只有受權的人才能夠驗證,甚至但願其餘人能驗證可是不知道數據,好比盲簽名、同態算法等。本節講述在非安全環境下處理安全數據的一些方法。

 

<數字信封>
用非對稱算法能夠把機密信息安全傳給指定的接收人,一般咱們會使用對方的公鑰進行加密,同時使用本身的私鑰對數據進行簽名。數字信封提供了一個更方便強大的方法,使得信息只有特定的接收人才能夠閱讀。

數字信封的功能相似於普通訊封,內容被包起來,上面寫了接收人,只有接收人才能拆信。

製做信封方法:
▲準備一個生成器

▲添加接收人:

接收人能夠是公鑰證書、普通公鑰或者密碼,能夠有多個。

▲製做信封

拆信封時,只要憑本身的公鑰找到本身的收件人信息,而後用持有的私鑰抽取內容便可。


<組簽名和環簽名>
一般一個合同是以公司的名義進行簽署的,例如公司A有三個合同經辦人C一、C二、C3,都可以表明公司簽署合同。

這裏有幾個要求:
▲所簽署的合同使用公司的公鑰能夠驗證確實是公司所簽署;
▲可以進一步肯定合同經辦人的身份;
▲經辦人如離職被吊銷我的證書,不影響已有業務數據。

按照孫子定理,n個整數(公鑰)的同餘方程組是有惟一解的,那麼理論上根據組員公鑰集合{K1, K2, ..., Kn}選擇一組模M,能夠求解x作組因子, 實現組員使用本身的私鑰ki和x能夠對密文進行解密 D(ki, x, C) = P。

相似的原理能夠應用到數字簽名,實現:

▲羣組簽名:機構使用羣組公鑰作本身的公鑰,能夠經過驗證簽名肯定簽名屬於指定的機構,而機構管理員能夠進一步肯定是那個成員簽署的。
▲環簽名:對於匿名要求,能夠肯定簽名是來自於一個羣組的成員,可是沒法肯定是具體哪一個成員簽署的。


<同態加密>
私密數據的處理一般是在組內進行,可是使用區塊鏈技術後,私密數據的處理可能會須要在無中心的節點上,甚至是第三方的節點進行處理。這時就須要把要處理的數據在保密狀態下進行。


例如股東A有100股,賣出60股剩餘40股,這是一個減法操做。若是這個過程在智能合約中,智能合約又運行在多個非徹底信任的節點上,若是須要將真實股份數量加密,則須要實現一個減法同態:
C3 = C1 - C2, 其中C1,2,3均是密文,執行減法的節點沒法知道實際餘額和發生額,可是股東A可使用本身的密鑰解密 D(C3) = P = P1-P2, 其中P表示明文,D表示解密算法。

目前已實現的算法主要有:

▲Paillier方案
機率公鑰加密,基於複合剩餘類的困難問題。知足加法和數乘同態。

▲BGV和RLWE方案
BGV和RLWE都是基於LWE(Learning With Errors)難題的同態算法, 支持加法、乘法、減法和移位運算的同態。源碼在github上開源- HElib。

▲基於其餘數學難題的方案如基於決斷問題等。全同態算法雖然實現已經取得很大進展,但其實現效率還遠未達到實用要求。全同態算法是密碼學的聖盃,等待您來奪取!

相關文章
相關標籤/搜索