解析 非對(duì)稱加密之RSA (go語(yǔ)言實(shí)現(xiàn))

堅(jiān)持原創(chuàng),如有錯(cuò)誤請(qǐng)指正

非對(duì)稱加密是區(qū)塊鏈常用的一類加密方式,比如說(shuō)有下面幾種:

RSA

secp256k1 (橢圓曲線)

ElGamal等等

接下來(lái)我會(huì)嘗試用明白易懂的語(yǔ)言講解

講解RSA之前,很多同學(xué)可能跟比特幣的簽名方式搞混,所以我就先簡(jiǎn)單的說(shuō)下比特幣轉(zhuǎn)賬簽名.比特幣采用UTXO模型(例子,我有5btc,我要給你轉(zhuǎn)1btc. 實(shí)際操作是5個(gè)btc全轉(zhuǎn)出,1btc給你,剩下4個(gè)btc再轉(zhuǎn)給我自己,每次交易等式都要配平),扯遠(yuǎn)了.

每次的轉(zhuǎn)賬記錄可以簡(jiǎn)單地看為

{
"付款地址":A
"收款地址":B
"轉(zhuǎn)賬數(shù)量":1btc
}  ==>計(jì)算其hash為H

接下來(lái)我要把該交易發(fā)送到其他節(jié)點(diǎn),其他節(jié)點(diǎn)接收到廣播信息,會(huì)首先進(jìn)行驗(yàn)證,如果驗(yàn)證通過(guò)則會(huì)再次轉(zhuǎn)發(fā)到其他節(jié)點(diǎn)中, 最終交易池會(huì)選取該交易,等待礦工打包入?yún)^(qū)塊中(等待時(shí)間由網(wǎng)絡(luò)擁堵?tīng)顩r和手續(xù)費(fèi)等因素決定).

轉(zhuǎn)賬第一步,對(duì)這筆交易進(jìn)行消息摘要,也就是計(jì)算其hash,唯一的交易交易記錄有唯一的hash值,碰撞的概率接近于零.假設(shè)hash為H.
第二步,對(duì)這個(gè)hash進(jìn)行簽名,其實(shí)這里就是一個(gè)非對(duì)稱加密了.
使用我的賬戶的私鑰對(duì) H 進(jìn)行加密,得到一段密文.其他節(jié)點(diǎn)使用我的公鑰對(duì)其解密,得到一段代碼H2 . 如果H2與通過(guò)轉(zhuǎn)賬記錄計(jì)算得到的H相等,驗(yàn)證通過(guò).
簽名過(guò)程即為用私鑰對(duì)交易摘要的加密過(guò)程苛吱,驗(yàn)證過(guò)程為用公鑰解密的過(guò)程(實(shí)際上規(guī)則要更復(fù)雜一些,這里只是方便大家理解).

接下來(lái)初步的講下RSA
RSA也分為公鑰和私鑰
密文=明文(待加密) ^E(E次方) 再取N的余數(shù) ==>加密
明文(待加密)=密文 ^D(D次方) 再取N的余數(shù) ==>解密
與比特幣簽名不同的是,這里是公鑰加密,私鑰解密(加密快,解密慢)
比特幣簽名(加密)慢,驗(yàn)證(解密)快.

D 21616157824859089947467865763905877208766194802261304393547211764767872553922733033101317695599363434608856645166753
N 26861170560633109174956418630434195575102580750015151802056322369493708310600722979313108414200817132792257978619899
E 65537

將公鑰私鑰進(jìn)行打印,發(fā)現(xiàn)
公鑰格式{N E}
私鑰格式{{N E} D [..........]}

可以發(fā)現(xiàn),公鑰長(zhǎng)度較短, 私鑰長(zhǎng)度較長(zhǎng),私鑰中包含了 公鑰

接下來(lái)計(jì)算創(chuàng)建私鑰花費(fèi)的時(shí)間,直觀的讓你明白R(shí)SA的效率
func main() {
    var timeSum time.Duration
    i := 0
    bits := 2304//創(chuàng)造自定義位數(shù)的key
    for ; i < 60; {
        now1 := time.Now()
        
        test.GenerateRsaKey(bits)//調(diào)用test包下的方法
        now2 := time.Now()
        timeSub := now2.Sub(now1)
        timeSum += timeSub
        i++
        fmt.Println("第", i, "次任務(wù),耗時(shí)毫秒數(shù)", timeSub.Nanoseconds()/1000000)
    }
    fmt.Println("平均毫秒數(shù)為", int64(timeSum.Nanoseconds())/int64(1000000)/int64(i), ",運(yùn)行次數(shù)為", i, ",位數(shù)為", bits)
}
func GenerateRsaKey(bits int) {

   privateKey, _ := rsa.GenerateKey(rand.Reader, bits)
   fmt.Println("D",privateKey.D) 
   fmt.Println("N",privateKey.N)
   fmt.Println("E",privateKey.E)
}

不同長(zhǎng)度密鑰(單位bit),創(chuàng)建私鑰任務(wù)耗時(shí)如下
平均毫秒數(shù)為 1699 ,運(yùn)行次數(shù)為 60 ,位數(shù)為 2304
平均毫秒數(shù)為 885 ,運(yùn)行次數(shù)為 60 ,位數(shù)為 2048
平均毫秒數(shù)為 581 ,運(yùn)行次數(shù)為 60 ,位數(shù)為 1792
平均毫秒數(shù)為 79 ,運(yùn)行次數(shù)為 60 ,位數(shù)為 1024
平均毫秒數(shù)為 35 ,運(yùn)行次數(shù)為 60 ,位數(shù)為 768
平均毫秒數(shù)為 11 ,運(yùn)行次數(shù)為 60 ,位數(shù)為 512
平均毫秒數(shù)為 5 ,運(yùn)行次數(shù)為 60 ,位數(shù)為 384

隨著位數(shù)的提高,耗時(shí)指數(shù)性增長(zhǎng).

抗暴力破解能力對(duì)比圖,本圖截取自<應(yīng)用密碼學(xué)>.可以看出相同密鑰長(zhǎng)度,非對(duì)稱加密比不上對(duì)稱加密,而非對(duì)稱加密又是個(gè)極耗資源的算法.


image.png

生成公鑰私鑰

func GenerateRsaKey(bits int) {

    privateKey, _ := rsa.GenerateKey(rand.Reader, bits)
    
    //保存私鑰
    //使用X509規(guī)范,對(duì)公鑰私鑰進(jìn)行格式化
    x509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)

    //pem格式編碼 將所有內(nèi)容替換為0-9 a-z A-Z, 基于base64解碼 末尾=用于補(bǔ)齊,末尾=個(gè)數(shù)為0-2個(gè).

    block := pem.Block{
        Type:  "pem私鑰",
        Bytes: x509PrivateKey,
    }
    fmt.Println(block)
    privateKeyFile, _ := os.Create("private.pem")
    pem.Encode(privateKeyFile, &block)
    privateKeyFile.Close()
    //保存公鑰
    x509publicKey := x509.MarshalPKCS1PublicKey(&privateKey.PublicKey)

    publicBlock := pem.Block{
        Type:  "公鑰",
        Bytes: x509publicKey,
    }
    publicKeyFile, _ := os.Create("public.pem")
    pem.Encode(publicKeyFile, &publicBlock)
    publicKeyFile.Close()

}

接下來(lái)進(jìn)行加密解密操作
代碼千篇一律

func main() {
    
    var timeSum time.Duration
    i := 0
    bits := 2304//設(shè)置密鑰位數(shù)
    for ; i < 100; {
        now1 := time.Now()
        ////創(chuàng)造多長(zhǎng)的rsa
        //test.GenerateRsaKey(bits)
        //明文
         text :=[]byte("我就是明文啦,要對(duì)我進(jìn)行加密")
        rsa_encrypt := test.Rsa_Encrypt(text, "public.pem")
        fmt.Println("密文為", string(rsa_encrypt))
        rsa_decrypt := test.Rsa_Decrypt(rsa_encrypt, "private.pem")
        fmt.Println("原文為", string(rsa_decrypt))
        now2 := time.Now()
        timeSub := now2.Sub(now1)
        timeSum += timeSub
        i++
        fmt.Println("第", i, "次任務(wù),耗時(shí)毫秒數(shù)", timeSub.Nanoseconds()/1000000)
    }
    fmt.Println("平均毫秒數(shù)為", int64(timeSum.Nanoseconds())/int64(1000000)/int64(i), ",運(yùn)行次數(shù)為", i, ",位數(shù)為", bits)
    fmt.Println("總耗時(shí)為", int64(timeSum.Nanoseconds())/int64(1000000), "毫秒")
}

被調(diào)用部分代碼

func Rsa_Encrypt(plainText []byte,path string) []byte{
    //1.讀取文件
    file, _ := os.Open(path)
    // 獲取文件信息
    fileInfo, _ := file.Stat()

    //2.讀取文件的內(nèi)容 pem
    data := make([]byte,fileInfo.Size())
    file.Read(data)
    //3.pem解碼 --- x509編碼的內(nèi)容
    block, _ := pem.Decode(data)
    //4.x509解碼(反序列化)
    publicKey, _ := x509.ParsePKCS1PublicKey(block.Bytes)

    cipherText, _ := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
    return cipherText
}
// 解密操作
func Rsa_Decrypt(cipherText []byte,path string) []byte{
    //1.讀取文件
    file, _ := os.Open(path)
    //2.讀取文件的內(nèi)容
    fileInfo, _ := file.Stat()
    data := make([]byte,fileInfo.Size())
    file.Read(data)

    //3.pem 解碼
    block, _ := pem.Decode(data)
    //4.x509解碼
    privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
    //5. 解密操作
    plainText, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)

    return plainText
}

平均毫秒數(shù)為 15 ,運(yùn)行次數(shù)為 100 ,位數(shù)為 2304,總耗時(shí)為1506毫秒
平均毫秒數(shù)為 1 ,運(yùn)行次數(shù)為 100 ,位數(shù)為 768,總耗時(shí)為 155 毫秒

由此可見(jiàn),隨著位數(shù)的增加,加密解密操作耗時(shí)指數(shù)型增長(zhǎng),感興趣的可以與對(duì)稱加密進(jìn)行對(duì)比,對(duì)相同明文進(jìn)行加密解密,效率有極大不同. 對(duì)稱加密快很多.

接下來(lái)進(jìn)行一個(gè)實(shí)驗(yàn)
設(shè)置密鑰位數(shù) bits=768
明文為 sdfdsfsdggs1231241412`efwe23efqfeqafqawegeetwt23452346ty24wgesewrwqfsaegvsaedaesd3ear

運(yùn)行程序,輸出結(jié)果
密文為 !???y?m???"cj0!nt??g2cY???YJw@R????C'??&?D*'R0c?NU??^??W?i?????,g?ā???-??z]????"
??\N??

將明文結(jié)尾再添加X(jué)
明文為sdfdsfsdggs1231241412`efwe23efqfeqafqawegeetwt23452346ty24wgesewrwqfsaegvsaedaesd3earX
運(yùn)行程序
發(fā)現(xiàn)密文沒(méi)有輸出,原因是明文長(zhǎng)度超出范圍了.
現(xiàn)在對(duì)bits進(jìn)行操作,將768改為1024
運(yùn)行程序,這次有結(jié)果輸出了.
密文為 "L?????????d??'??U?JP???MT??k??? a??J??\???????\w????"':??qp;??.}_?????]?KF?????? ???(????F,?*??紛+?GA?x????6?N??? ?=???

為什么呢?
文章最上面說(shuō)過(guò)
密文=明文(待加密) ^E(E次方) 再取N的余數(shù)
也就是說(shuō)N限制了明文的最大長(zhǎng)度. 如果明文過(guò)長(zhǎng),就會(huì)發(fā)生碰撞(不同的明文產(chǎn)生了相同的密文,這里可以好好理解下),而N與密鑰長(zhǎng)度有關(guān).

1.可加密明文的最大長(zhǎng)度與密鑰長(zhǎng)度有關(guān),密鑰越長(zhǎng),可加密明文的最大長(zhǎng)度越長(zhǎng).
2.rsa可加密的數(shù)據(jù)仍然很小,傳輸大數(shù)據(jù)不太可能.
假設(shè)用rsa加密一部電影,需要將電影進(jìn)行拆分,分開(kāi)加密解密,按照非對(duì)稱加密的效率,幾十年可能都搞不定.
引申:加密大文件,要用對(duì)稱加密先加密,再將對(duì)稱加密的密鑰進(jìn)行非對(duì)稱加密.這樣就能兼顧效率和安全.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匾效,一起剝皮案震驚了整個(gè)濱河市碧聪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌筐乳,老刑警劉巖歌殃,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蝙云,居然都是意外死亡氓皱,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)波材,“玉大人股淡,你說(shuō)我怎么就攤上這事⊥⑶” “怎么了唯灵?”我有些...
    開(kāi)封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)隙轻。 經(jīng)常有香客問(wèn)我埠帕,道長(zhǎng),這世上最難降的妖魔是什么玖绿? 我笑而不...
    開(kāi)封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任敛瓷,我火速辦了婚禮,結(jié)果婚禮上镰矿,老公的妹妹穿的比我還像新娘琐驴。我一直安慰自己俘种,他們只是感情好秤标,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著宙刘,像睡著了一般苍姜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悬包,一...
    開(kāi)封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天衙猪,我揣著相機(jī)與錄音,去河邊找鬼布近。 笑死垫释,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的撑瞧。 我是一名探鬼主播棵譬,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼预伺!你這毒婦竟也來(lái)了订咸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤酬诀,失蹤者是張志新(化名)和其女友劉穎脏嚷,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瞒御,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡父叙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趾唱。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屿岂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鲸匿,到底是詐尸還是另有隱情爷怀,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布带欢,位于F島的核電站运授,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏乔煞。R本人自食惡果不足惜吁朦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渡贾。 院中可真熱鬧逗宜,春花似錦、人聲如沸空骚。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)囤屹。三九已至熬甚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肋坚,已是汗流浹背乡括。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留智厌,地道東北人诲泌。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像铣鹏,于是被迫代替她去往敵國(guó)和親敷扫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容