相關(guān)文章:
- [區(qū)塊鏈] 密碼學(xué)——橢圓曲線密碼算法(ECC)
- 橢圓曲線算法:入門
- ECC橢圓曲線詳解(有具體實例)
- 誰能最簡單的詳解橢圓曲線算法纫版,secp256k1 是如何生成公鑰和私鑰的胳挎?
加密算法
對稱加密
概念:即加密,解密的密鑰相同迅细。
優(yōu)點:是加解密效率高(速度快巫橄,空間占用小)茵典,加密強度高湘换。
缺點:是參與多方都需要持有密鑰,一旦有人泄露則安全性被破壞;另外如何在不安全通道下分發(fā)密鑰也是個問題彩倚。
代表算法:包括DES筹我、3DES、AES署恍、IDEA等。
非對稱加密
概念:加密密鑰和解密密鑰是不同的蜻直,分別稱為公鑰和私鑰盯质。公鑰一般是公開的,人人可獲取的概而,私鑰一般是個人自己持有呼巷,不能被他人獲取。
優(yōu)點:是公私鑰分開赎瑰,不安全通道也可以使用王悍。
缺點:是加解密速度慢,一般比對稱加解密算法慢2到3個數(shù)量級餐曼;同時加密強度相比對稱加密要差压储。
非對稱加密算法的安全性往往需要基于數(shù)學(xué)問題來保障,目前主要有基于大數(shù)質(zhì)因子分解源譬、離散對數(shù)集惋、橢圓曲線等幾種思路。
代表算法:RSA踩娘、ElGamal刮刑、橢圓曲線(Elliptic Curve Crytosystems,ECC)系列算法。
混合機密機制
既先用計算復(fù)雜度高的非對稱機密協(xié)商一個臨時的加密密鑰(會話密鑰养渴,一般相對內(nèi)容來說要短得多)雷绢,然后雙方再通過對稱加密對傳遞的大量數(shù)據(jù)進行加解密處理。
典型的場景是現(xiàn)在大家常用的HTTPS機制理卑。
即:先用較短的非對稱加密
確認權(quán)限翘紊,再用對稱加密
對傳遞的大量數(shù)據(jù)進行加解密。
區(qū)塊鏈橢圓曲線加密(Elliptic Curve Crytosystems,ECC)簡介
導(dǎo)入
假設(shè)這個世界上所有的人都會乘法藐唠,卻沒有人會除法霞溪。
有一天張三挑出了兩個數(shù)字,123中捆,456鸯匹。
由于張三會乘法,于是乎張三計算出了:
123 * 456 = 56088
于是張三告訴你:
123 * ??? =56088
你是個天資卓絕的人泄伪,但是沒辦法殴蓬,上天不允許你會除法,因此你沒法知道張三說的???是什么。
當(dāng)然了染厅,別人也不知道痘绎,因為張三沒有告訴其他人???是啥。
有一天肖粮,你打算告訴張三一個秘密孤页,67。但是你又不想別人知道涩馆。于是聰明絕頂?shù)哪汶S手選了一個數(shù)字222行施。
計算出:
123 * 222 = 27306
56088 * 222 + 67 = 12451603
然后你對張三說:
123 * ??? = 27306
56088 * ??? + x = 12451603
當(dāng)然,你聰明絕頂魂那,張三聰明禿頂蛾号,于是張三一尋思:
123 * ??? * 456 = 56088 * ???
這上下一減,
x = 12451603 - 27306 * 456 = 67
哎媽呀涯雅,這x就這么被傳遞過來了鲜结。如果我們把上面的過程寫成數(shù)學(xué)公式的話,
G * k = K (G,K公開活逆,k保密)
c1 = G * Mc2 = K * M + x (M隨機選取精刷,x為要加密的數(shù)字,M和x都保密)
x = c2 - c1 * k
= K * M + x - G * M * k = G * M * k + x - G * M * k (消除左右兩側(cè)的G * M * k)
= x
總結(jié):
所以我們想要實現(xiàn)加密容易蔗候,校驗容易贬养,但解密很難,
其實就是要找到一組運算加琴庵,減误算,乘很簡單,除卻很難迷殿,這個事情并不容易儿礼。
因為加,減庆寺,乘就可以實現(xiàn)加密和校驗蚊夫,但除我們希望他很難,難到幾乎無法得到解懦尝。
而這個符合這個條件的運算之一知纷,就是:橢圓曲線方程
,其加減乘除是指域
上的加減乘除陵霉,域的概念是從我們的有理數(shù)琅轧,實數(shù)的運算中抽象出來的,嚴格的定義請參考近世代數(shù)方面的數(shù)踊挠。簡單的說乍桂,域中的元素同有理數(shù)一樣,有自己得加法、乘法睹酌、除法权谁、單位元(1),零元(0),并滿足交換率憋沿、分配率旺芽。
橢圓曲線方程
包括ECC、ECDH或者ECDSA辐啄。ECC是Elliptic Curve Cryptography的縮寫采章,就是橢圓加密算法,ECDH和ECDSA是ECC的不同實現(xiàn)则披。
橢圓加密算法的應(yīng)用范圍很廣共缕,主要的三個技術(shù) TLS洗出、PGP以及SSH都在使用它士复,更別提比特幣以及其他加密數(shù)字貨幣了。
橢圓曲線方程:(可以暫時簡單的理解為描述了特定點的集合的公式)
y2 = x3 + ax + b
橢圓曲線幾何學(xué)上的加法
任意取橢圓曲線上兩點P翩活、Q(若P阱洪、Q兩點重合,則作P點的切線)菠镇,作直線交于橢圓曲線的另一點R'冗荸,過R'做y軸的平行線交于R,定義P+Q=R利耍。這樣蚌本,加法的和也在橢圓曲線上,并同樣具備加法的交換律隘梨、結(jié)合律程癌。
橢圓曲線上的加密/解密
公開密鑰算法總是要基于一個數(shù)學(xué)上的難題。比如RSA 依據(jù)的是:給定兩個素數(shù)p轴猎、q 很容易相乘得到n嵌莉,而對n進行因式分解卻相對困難。那橢圓曲線上有什么難題呢捻脖?
考慮如下等式:
K=kG [其中 K,G為Ep(a,b)上的點锐峭,k為小于n(n是點G的階)的整數(shù)]
不難發(fā)現(xiàn),給定k和G可婶,根據(jù)加法法則沿癞,計算K很容易;但給定K和G矛渴,求k就相對困難了抛寝。
這就是橢圓曲線加密算法采用的難題。
我們把點G稱為基點(base point),
k(k<n盗舰,n為基點g的階)稱為私有密鑰(privte key)晶府,
k稱為公開密鑰(public="" key)。<="" p="">
現(xiàn)在我們描述一個利用橢圓曲線進行加密通信的過程:
1钻趋、用戶A選定一條橢圓曲線Ep(a,b)川陆,并取橢圓曲線上一點,作為基點G蛮位。
2较沪、用戶A選擇一個私有密鑰k,并生成公開密鑰K=kG失仁。
3尸曼、用戶A將Ep(a,b)和點K,G傳給用戶B萄焦。
4控轿、用戶B接到信息后 ,將待傳輸?shù)拿魑木幋a到Ep(a,b)上一點M(編碼方法很多拂封,這里不作討論)茬射,并產(chǎn)生一個隨機整數(shù)r(r<n)。
5冒签、用戶B計算點C1=M+rK在抛;C2=rG。
6萧恕、用戶B將C1刚梭、C2傳給用戶A。
7票唆、用戶A接到信息后朴读,計算C1-kC2,結(jié)果就是點M惰说。
因為C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M再對點M進行解碼就可以得到明文磨德。
在這個加密通信中,如果有一個偷窺者H 吆视,他只能看到Ep(a,b)典挑、K、G啦吧、C1您觉、C2 而通過K、G 求k 或通過C2授滓、G求r 都是相對困難的琳水。因此肆糕,H無法得到A、B間傳送的明文信息在孝。
總結(jié):
設(shè)私鑰诚啃、公鑰分別為k、K私沮,即K = kG始赎,其中G為G點。
公鑰加密:
選擇隨機數(shù)r仔燕,將消息M生成密文C造垛,該密文是一個點對,即:
C = {rG, M+rK}晰搀,其中K為公鑰
私鑰解密:
M + rK - k(rG) = M + r(kG) - k(rG) = M
其中k五辽、K分別為私鑰、公鑰外恕。
橢圓曲線簽名與驗證簽名
橢圓曲線簽名算法杆逗,即ECDSA。
設(shè)私鑰吁讨、公鑰分別為k髓迎、K峦朗,即K = kG建丧,其中G為G點。
私鑰簽名:
1波势、選擇隨機數(shù)r翎朱,計算點rG(x, y)。
2尺铣、根據(jù)隨機數(shù)r拴曲、消息M的哈希h、私鑰k凛忿,計算s = (h + kx)/r澈灼。
3、將消息M店溢、和簽名{rG, s}發(fā)給接收方叁熔。
公鑰驗證簽名:
1、接收方收到消息M床牧、以及簽名{rG=(x,y), s}荣回。
2、根據(jù)消息求哈希h戈咳。
3心软、使用發(fā)送方公鑰K計算:hG/s + xK/s壕吹,并與rG比較,如相等即驗簽成功删铃。
原理如下:
hG/s + xK/s = hG/s + x(kG)/s = (h+xk)G/s = r(h+xk)G / (h+kx) = rG
比特幣私鑰耳贬、公鑰、錢包地址的來歷和關(guān)系
比特幣系統(tǒng)選用的secp256k1
比特幣錢包地址示例:1QCXRuoxWo5Bya9NxHaVBArBQYhatHJrU7
那這個錢包地址是如何生成的猎唁?
從比特幣私鑰得到我們?nèi)粘^D(zhuǎn)賬所用的比特幣錢包地址總共需要9個步驟效拭,中間用到了SHA256加密、RIPEMD160加密和BASE58編碼胖秒。
1. 生成隨機私鑰
私鑰是一個隨機數(shù)缎患,隨機選取一個32字節(jié)的數(shù),這個數(shù)的范圍大小是介于1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之間的一個數(shù)阎肝,為了方便后面的計算挤渔,我們隨機生成一個合法的私鑰:
8F72F6B29E6E225A36B68DFE333C7CE5E55D83249D3D2CD6332671FA445C4DD3
2. 橢圓曲線算公鑰
生成了私鑰之后,我們使用橢圓曲線加密算法(ECDSA-secp256k1)計算私鑰所對應(yīng)的非壓縮公鑰风题,生成的公鑰共65字節(jié)判导, 其中一個字節(jié)是0x04,其中32個字節(jié)是X坐標(biāo)沛硅,另外32個字節(jié)是Y坐標(biāo):
公鑰P.X:06CCAE7536386DA2C5ADD428B099C7658814CA837F94FADE365D0EC6B1519385
公鑰P.Y:FF83EC5F2C0C8F016A32134589F7B9E97ACBFEFD2EF12A91FA622B38A1449EEB
3.計算公鑰的SHA-256哈希值
將上述公鑰地址拼合眼刃,得到標(biāo)準(zhǔn)地址:
0406CCAE7536386DA2C5ADD428B099C7658814CA837F94FADE365D0EC6B1519385FF83EC5F2C0C8F016A32134589F7B9E97ACBFEFD2EF12A91FA622B38A1449EEB
對齊進行SHA-256哈希計算,得到結(jié)果:
2572e5f4a8e77ddf5bb35b9e61c61f66455a4a24bcfd6cb190a8e8ff48fc097d
4.計算 RIPEMD-160哈希值
取上一步結(jié)果摇肌,進行RIPEMD-160計算擂红,得到結(jié)果:
0b14f003d63ab31aef5fedde2b504699547dd1f6
5.加入地址版本號(比特幣主網(wǎng)版本號“0x00”)
取上一步結(jié)果,在前面加上16進制的00围小,即:
000b14f003d63ab31aef5fedde2b504699547dd1f6
6.計算 SHA-256 哈希值
取上一步結(jié)果昵骤,進行SHA-256計算,可得:
ddc2270f93cc84cc6869dd373f3c340bbf5cb9a8f5559297cc9e5d947aab2536
然后肯适,對以上結(jié)果再次計算 SHA-256 哈希值变秦,得到:
869ac57b83ccf75ca9da8895823562fffb611e3c297d9c2d4612aeeb32850078
7.取上一步結(jié)果的前4個字節(jié)(8位十六進制)
869ac57b
8.把這4個字節(jié)加在步驟5的結(jié)果后面
作為校驗位,將這4個字節(jié)加載第五步的結(jié)果后面框舔,這就是比特幣地址的16進制形態(tài)了:
869ac57b000b14f003d63ab31aef5fedde2b504699547dd1f6
9.用Base58編碼變換一下地址
對上一步的結(jié)果進行Base58編碼蹦玫,得到:
1QCXRuoxWo5Bya9NxHaVBArBQYhatHJrU7
這就是我們經(jīng)常看到的傳統(tǒng)意義上的比特幣錢包地址了刘绣。
Delos區(qū)塊鏈?zhǔn)褂玫臋E圓加密
delos區(qū)塊鏈上使用了兩種不同的橢圓加密實現(xiàn)樱溉,都是go語言編寫
ed25519 gitlab.zhonganonline.com/ann/ann-module/lib/ed25519
secp256k1 github.com/btcsuite/btcd/btcec
delos鏈生成私鑰
privkey crypto.PrivKeyEd25519
delos/api項目中調(diào)用的是以太坊
的delos/eth/crypto的ECDSA橢圓加密方法生成私鑰和地址
生成account私鑰和地址
result.Privkey = ethcmn.Bytes2Hex(crypto.FromECDSA(privkey))
result.Address = ethcmn.Bytes2Hex(crypto.FromECDSAPubCompressed(&privkey.PublicKey))
Breadwallet-android使用的橢圓加密
Breadwallet-android使用的是secp256k1,都是c語言編寫
在app/src/main/secp/secp256k1下
生成私鑰
app\src\main\jni\breadwallet-core\Java\root\com\breadwallet\core\BRCoreKey.java
private static native long createJniCoreKey ();
調(diào)用的是 jni c庫
/*
* Class: com_breadwallet_core_BRCoreKey
* Method: createJniCoreKey
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_breadwallet_core_BRCoreKey_createJniCoreKey
(JNIEnv *env, jclass thisClass) {
BRKey *key = (BRKey *) calloc (1, sizeof(BRKey));
return (jlong) key;
}
生成公鑰
可用助記詞或序列
src\main\jni\breadwallet-core\Java\root\com\breadwallet\core\BRCoreMasterPubKey.java
private static native long createJniCoreMasterPubKeyFromPhrase (byte[] phrase);
private static native long createJniCoreMasterPubKeyFromSerialization(byte[] pubKey);
調(diào)用的是 jni c庫
/*
* Class: com_breadwallet_core_BRCoreMasterPubKey
* Method: createJniCoreMasterPubKeyFromPubKey
* Signature: ([B)J
*/
JNIEXPORT jlong JNICALL
Java_com_breadwallet_core_BRCoreMasterPubKey_createJniCoreMasterPubKeyFromSerialization
(JNIEnv *env, jclass thisClass,
jbyteArray serialization) {
jsize serializationLength = (*env)->GetArrayLength (env, serialization);
jbyte *serializationBytes = (*env)->GetByteArrayElements (env, serialization, 0);
assert (serializationLength == sizeof(BRMasterPubKey));
BRMasterPubKey *key = (BRMasterPubKey *) calloc (1, sizeof (BRMasterPubKey));
memcpy(key, serializationBytes, sizeof(BRMasterPubKey));
return (jlong) key;
}