Golang與非對(duì)稱(chēng)加密
目錄
1、非對(duì)稱(chēng)加密介紹
2、DSA
3、RSA
3.1 RSA 的加密過(guò)程
3.2 調(diào)用示例
4、ECC
5、ECC 與 RSA 的比較
6、ECDSA

1、非對(duì)稱(chēng)加密介紹
非對(duì)稱(chēng)加密和對(duì)稱(chēng)加密不同,主要區(qū)別如下
使用公鑰加密,使用私鑰解密
公鑰和私鑰不同
公鑰可以公布給所有人
私鑰只有自己保存
相比于對(duì)稱(chēng)加密,運(yùn)算速度非常慢
加密過(guò)程:明文+公鑰——>密文 解密過(guò)程:密文+私鑰——>明文
非對(duì)稱(chēng)加密算法常用于數(shù)據(jù)加密和身份認(rèn)證, 常見(jiàn)的非對(duì)稱(chēng)加密算法如下
RSA: 由 RSA 公司發(fā)明,是一個(gè)支持變長(zhǎng)密鑰的公共密鑰算法,需要加密的文件塊的長(zhǎng)度也是可變的 DSA(Digital Signature Algorithm): 數(shù)字簽名算法,是一種標(biāo)準(zhǔn)的 DSS(數(shù)字簽名標(biāo)準(zhǔn))ECC(Elliptic Curves Cryptography): 橢圓曲線(xiàn)密碼編碼學(xué) ECDSA(Elliptic Curve Digital Signature Algorithm): 基于橢圓曲線(xiàn)的 DSA簽名算法
2、DSA
DSA是基于整數(shù)有限域離散對(duì)數(shù)難題的,其安全性與RSA相比差不多。DSA的一個(gè)重要特點(diǎn)是兩個(gè)素?cái)?shù)公開(kāi),這樣,當(dāng)使用別人的p和q時(shí),即使不知道私鑰,你也能確認(rèn)它們是否是隨機(jī)產(chǎn)生的,還是作了手腳。RSA算法卻做不到,但是其缺點(diǎn)就是只能用于數(shù)字簽名,不能用于加密
3、RSA
在1976年,由于對(duì)稱(chēng)加密算法已經(jīng)不能滿(mǎn)足需要,Diffie和Hellman發(fā)表了一篇叫《密碼學(xué)新動(dòng)向》的文章,介紹了公匙加密的概念,由Rivet、Shamir、Adelman提出了RSA算法RSA是目前最有影響力的公鑰加密算法,它能夠抵抗到目前為止已知的絕大多數(shù)密碼攻擊,已被ISO推薦為公鑰數(shù)據(jù)加密標(biāo)準(zhǔn)
命名:Ron Rivest、Adi Shamir、Leonard Adleman
密鑰越長(zhǎng),越難破解,目前 768位的密鑰還無(wú)法破解(至少?zèng)]人公開(kāi)宣布),因此可以認(rèn)為1024位的RSA密鑰基本安全,2048位的密鑰極其安全RSA的算法原理主要用到了數(shù)論
3.1 RSA 的加密過(guò)程
1、隨機(jī)選擇兩個(gè)不相等的質(zhì)數(shù)p和q,p=61,q=53
2、計(jì)算p和q的乘積,n=3233
3、計(jì)算n的歐拉函數(shù) ?(n) = (p-1)(q-1),?(n)=3120
4、隨機(jī)選擇一個(gè)整數(shù)e,使得 1?(n)互質(zhì),e=17
5、計(jì)算e對(duì)于?(n)的模反元素 d,即求解 e*d + ?(n)*y =1,d=2753,y=-15
6、將n和e封裝成公鑰,n和d封裝成私鑰,公鑰=(3233, 17),私鑰=(3233, 2753)
3.2 調(diào)用示例
RSA使用示例代碼
package?main
import?(
?"crypto/rand"
?"crypto/rsa"
?"crypto/sha1"
?"crypto/x509"
?"encoding/pem"
?"fmt"
)
//?使用對(duì)方的公鑰的數(shù)據(jù),?只有對(duì)方的私鑰才能解開(kāi)
func?encrypt(plain?string,?publicKey?string)?(cipherByte?[]byte,?err?error)?{
?msg?:=?[]byte(plain)
?//?解碼公鑰
?pubBlock,?_?:=?pem.Decode([]byte(publicKey))
?//?讀取公鑰
?pubKeyValue,?err?:=?x509.ParsePKIXPublicKey(pubBlock.Bytes)
?if?err?!=?nil?{
??panic(err)
?}
?pub?:=?pubKeyValue.(*rsa.PublicKey)
?//?加密數(shù)據(jù)方法:?不用使用EncryptPKCS1v15方法加密,源碼里面推薦使用EncryptOAEP,?因此這里使用安全的方法加密
?encryptOAEP,?err?:=?rsa.EncryptOAEP(sha1.New(),?rand.Reader,?pub,?msg,?nil)
?if?err?!=?nil?{
??panic(err)
?}
?cipherByte?=?encryptOAEP
?return
}
//?使用私鑰解密公鑰加密的數(shù)據(jù)
func?decrypt(cipherByte?[]byte,?privateKey?string)?(plainText?string,?err?error)?{
?//?解析出私鑰
?priBlock,?_?:=?pem.Decode([]byte(privateKey))
?priKey,?err?:=?x509.ParsePKCS1PrivateKey(priBlock.Bytes)
?if?err?!=?nil?{
??panic(err)
?}
?//?解密RSA-OAEP方式加密后的內(nèi)容
?decryptOAEP,?err?:=?rsa.DecryptOAEP(sha1.New(),?rand.Reader,?priKey,?cipherByte,?nil)
?if?err?!=?nil?{
??panic(err)
?}
?plainText?=?string(decryptOAEP)
?return
}
func?test()?{
?msg?:=?"Content?bo?be?encrypted!"
?//?獲取公鑰,?生產(chǎn)環(huán)境往往是文件中讀取,?這里為了測(cè)試方便,?直接生成了.
?publicKeyData?:=?`-----BEGIN?PUBLIC?KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL
AUeJ6PeW+DAkmJWF6QIDAQAB
-----END?PUBLIC?KEY-----
`
?//?獲取私鑰
?privateKeyData?:=?`-----BEGIN?RSA?PRIVATE?KEY-----
MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y
7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7
Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB
AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM
ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1
XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB
/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40
IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG
4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9
DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8
9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw
DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO
AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O
-----END?RSA?PRIVATE?KEY-----
`
?cipherData,?err?:=?encrypt(msg,?publicKeyData)
?if?err?!=?nil?{
??panic(err)
?}
?fmt.Printf("encrypt?message:?%x\n",?cipherData)
?plainData,?err?:=?decrypt(cipherData,?privateKeyData)
?if?err?!=?nil?{
??panic(err)
?}
?fmt.Printf("decrypt?message:%s\n",?plainData)
}
func?main()?{
?test()
}
4、ECC
ECC又稱(chēng)橢圓曲線(xiàn)加密
ECC(Elliptic Curve Cryptography)橢圓曲線(xiàn)加密算法,相比RSA,ECC可以使用更短的密鑰,來(lái)實(shí)現(xiàn)與RSA相當(dāng)或更高的安全
定義了橢圓曲線(xiàn)上的加法和二倍運(yùn)算
橢圓曲線(xiàn)依賴(lài)的數(shù)學(xué)難題是:k為正整數(shù),p是橢圓曲線(xiàn)上的點(diǎn)(稱(chēng)為基點(diǎn)),k*p=Q,已知Q和P,很難計(jì)算出 k
ECC是建立在基于橢圓曲線(xiàn)的離散對(duì)數(shù)的難度, 大概過(guò)程如下
給定橢圓曲線(xiàn)上的一個(gè)點(diǎn)P,一個(gè)整數(shù)k,求解Q=kP很容易;給定一個(gè)點(diǎn)P、Q,知道Q=kP,求整數(shù)k確是一個(gè)難題。ECDH即建立在此數(shù)學(xué)難題之上
今天只有短的RSA鑰匙才可能被強(qiáng)力方式解破。到2008年為止,世界上還沒(méi)有任何可靠的攻擊 RSA 算法的方式。只要其鑰匙的長(zhǎng)度足夠長(zhǎng),用RSA加密的信息實(shí)際上是不能被解破的。但在分布式計(jì)算和量子計(jì)算機(jī)理論日趨成熟的今天,RSA加密安全性受到了挑戰(zhàn)
隨著分解大整數(shù)方法的進(jìn)步及完善、計(jì)算機(jī)速度的提高以及計(jì)算機(jī)網(wǎng)絡(luò)的發(fā)展,為了保障數(shù)據(jù)的安全,RSA的密鑰需要不斷增加,但是,密鑰長(zhǎng)度的增加導(dǎo)致了其加解密的速度大為降低,硬件實(shí)現(xiàn)也變得越來(lái)越難以忍受,這對(duì)使用RSA的應(yīng)用帶來(lái)了很重的負(fù)擔(dān),因此需要一種新的算法來(lái)代替RSA
1985年N.Koblitz和Miller提出將橢圓曲線(xiàn)用于密碼算法,根據(jù)是有限域上的橢圓曲線(xiàn)上的點(diǎn)群中的離散對(duì)數(shù)問(wèn)題ECDLP。ECDLP是比因子分解問(wèn)題更難的問(wèn)題,它是指數(shù)級(jí)的難度
橢圓曲線(xiàn)算法因參數(shù)不同有多種類(lèi)型, 這個(gè)網(wǎng)站列出了現(xiàn)階段那些ECC是相對(duì)安全的:橢圓曲線(xiàn)算法安全列表, 而curve25519便是其中的佼佼者
Curve25519/Ed25519/X25519是著名密碼學(xué)家Daniel J. Bernstein在2006年獨(dú)立設(shè)計(jì)的橢圓曲線(xiàn)加密/簽名/密鑰交換算法, 和現(xiàn)有的任何橢圓曲線(xiàn)算法都完全獨(dú)立
特點(diǎn)是:
完全開(kāi)放設(shè)計(jì): 算法各參數(shù)的選擇直截了當(dāng),非常明確,沒(méi)有任何可疑之處,相比之下目前廣泛使用的橢圓曲線(xiàn)是 NIST 系列標(biāo)準(zhǔn),方程的系數(shù)是使用來(lái)歷不明的隨機(jī)種子 c49d3608 86e70493 6a6678e1 139d26b7 819f7e90 生成的,非??梢?,疑似后門(mén); 高安全性:一個(gè)橢圓曲線(xiàn)加密算法就算在數(shù)學(xué)上是安全的,在實(shí)用上也并不一定安全,有很大的概率通過(guò)緩存、時(shí)間、惡意輸入摧毀安全性,而 25519 系列橢圓曲線(xiàn)經(jīng)過(guò)特別設(shè)計(jì),盡可能的將出錯(cuò)的概率降到了最低,可以說(shuō)是實(shí)踐上最安全的加密算法。例如,任何一個(gè) 32 位隨機(jī)數(shù)都是一個(gè)合法的 X25519 公鑰,因此通過(guò)惡意數(shù)值攻擊是不可能的,算法在設(shè)計(jì)的時(shí)候刻意避免的某些分支操作,這樣在編程的時(shí)候可以不使用 if ,減少了不同 if 分支代碼執(zhí)行時(shí)間不同的時(shí)序攻擊概率,相反, NIST 系列橢圓曲線(xiàn)算法在實(shí)際應(yīng)用中出錯(cuò)的可能性非常大,而且對(duì)于某些理論攻擊的免疫能力不高, Bernstein 對(duì)市面上所有的加密算法使用 12 個(gè)標(biāo)準(zhǔn)進(jìn)行了考察, 25519 是幾乎唯一滿(mǎn)足這些標(biāo)準(zhǔn)的; 速度快: 25519 系列曲線(xiàn)是目前最快的橢圓曲線(xiàn)加密算法,性能遠(yuǎn)遠(yuǎn)超過(guò) NIST 系列,而且具有比 P-256 更高的安全性; 作者功底深厚: Daniel J. Bernstein 是世界著名的密碼學(xué)家,他在大學(xué)曾經(jīng)開(kāi)設(shè)過(guò)一門(mén) UNIX 系統(tǒng)安全的課程給學(xué)生,結(jié)果一學(xué)期下來(lái),發(fā)現(xiàn)了 UNIX 程序中的 91 個(gè)安全漏洞;他早年在美國(guó)依然禁止出口加密算法時(shí),曾因?yàn)榘炎约涸O(shè)計(jì)的加密算法發(fā)布到網(wǎng)上遭到了美國(guó)政府的起訴,他本人抗?fàn)幜辏詈竺绹?guó)政府撤銷(xiāo)所有指控,目前另一個(gè)非?;鸬母咝阅馨踩髅艽a ChaCha20 也是出自 Bernstein 之手; 下一代的標(biāo)準(zhǔn): 25519 系列曲線(xiàn)自 2006 年發(fā)表以來(lái),除了學(xué)術(shù)界無(wú)人問(wèn)津, 2013 年愛(ài)德華·斯諾登曝光棱鏡計(jì)劃后,該算法突然大火,大量軟件,如 OpenSSH 都迅速增加了對(duì) 25519 系列的支持,如今 25519 已經(jīng)是大勢(shì)所趨,可疑的 NIST 曲線(xiàn)遲早要退出橢圓曲線(xiàn)的歷史舞臺(tái),目前, RFC 增加了 SSL/TLS 對(duì) X25519 密鑰交換協(xié)議的支持,OpenSSL 1.1 也加入支持,是擺脫老大哥的第一步,下一步是將 Ed25519 做為可選的 TLS 證書(shū)簽名算法,徹底擺脫 NIST
5、ECC 與 RSA 的比較
ECC和RSA相比,在許多方面都有對(duì)絕對(duì)的優(yōu)勢(shì),主要體現(xiàn)在以下方面:
抗攻擊性強(qiáng)。相同的密鑰長(zhǎng)度,其抗攻擊性要強(qiáng)很多倍 計(jì)算量小,處理速度快。 ECC總的速度比RSA、DSA要快得多存儲(chǔ)空間占用小。 ECC的密鑰尺寸和系統(tǒng)參數(shù)與RSA、DSA相比要小得多,意味著它所占的存貯空間要小得多。這對(duì)于加密算法在IC卡上的應(yīng)用具有特別重要的意義帶寬要求低。當(dāng)對(duì)長(zhǎng)消息進(jìn)行加解密時(shí),三類(lèi)密碼系統(tǒng)有相同的帶寬要求,但應(yīng)用于短消息時(shí) ECC帶寬要求卻低得多。帶寬要求低使ECC在無(wú)線(xiàn)網(wǎng)絡(luò)領(lǐng)域具有廣泛的應(yīng)用前景
ECC的這些特點(diǎn)使它必將取代RSA,成為通用的公鑰加密算法。比如SET協(xié)議的制定者已把它作為下一代SET協(xié)議中缺省的公鑰密碼算法
6、ECDSA
因?yàn)樵跀?shù)字簽名的安全性高, 基于ECC的DSA更高, 所以非常適合數(shù)字簽名使用場(chǎng)景, 在SSH TLS有廣泛使用, ECC把離散對(duì)數(shù)安全性高很少,所以ECC在安全領(lǐng)域會(huì)成為下一個(gè)標(biāo)準(zhǔn)
在golang的ssh庫(kù)中就是使用這個(gè)算法來(lái)簽名的:A使用自己的私鑰簽名一段數(shù)據(jù),然后將公鑰發(fā)放出去。用戶(hù)拿到公鑰后,驗(yàn)證數(shù)據(jù)的簽名,如果通過(guò)則證明數(shù)據(jù)來(lái)源是A,從而達(dá)到身份認(rèn)證的作用
package?main
import?(
?"crypto/ecdsa"
?"crypto/elliptic"
?"crypto/md5"
?"crypto/rand"
?"fmt"
?"hash"
?"io"
?"math/big"
)
//?SignData?用于保存簽名的數(shù)據(jù)
type?SignData?struct?{
?r?????????*big.Int
?s?????????*big.Int
?signhash??*[]byte
?signature?*[]byte
}
//?使用私鑰簽名一段數(shù)據(jù)
func?sign(message?string,?privateKey?*ecdsa.PrivateKey)?(signData?*SignData,?err?error)?{
?//?簽名數(shù)據(jù)
?var?h?hash.Hash
?h?=?md5.New()
?r?:=?big.NewInt(0)
?s?:=?big.NewInt(0)
?io.WriteString(h,?message)
?signhash?:=?h.Sum(nil)
?r,?s,?serr?:=?ecdsa.Sign(rand.Reader,?privateKey,?signhash)
?if?serr?!=?nil?{
??return?nil,?serr
?}
?signature?:=?r.Bytes()
?signature?=?append(signature,?s.Bytes()...)
?signData?=?&SignData{
??r:?????????r,
??s:?????????s,
??signhash:??&signhash,
??signature:?&signature,
?}
?return
}
//?校驗(yàn)數(shù)字簽名
func?verifySign(signData?*SignData,?publicKey?*ecdsa.PublicKey)?(status?bool)?{
?status?=?ecdsa.Verify(publicKey,?*signData.signhash,?signData.r,?signData.s)
?return
}
func?test()?{
?//使用橢圓曲線(xiàn)的P256算法,現(xiàn)在一共也就實(shí)現(xiàn)了4種,我們使用折中一種,具體見(jiàn)http://golang.org/pkg/crypto/elliptic/#P256
?pubkeyCurve?:=?elliptic.P256()
?privateKey?:=?new(ecdsa.PrivateKey)
?//?生成秘鑰對(duì)
?privateKey,?err?:=?ecdsa.GenerateKey(pubkeyCurve,?rand.Reader)
?if?err?!=?nil?{
??panic(err)
?}
?var?publicKey?ecdsa.PublicKey
?publicKey?=?privateKey.PublicKey
?//?簽名
?signData,?err?:=?sign("This?is?a?message?to?be?signed?and?verified?by?ECDSA!",?privateKey)
?if?err?!=?nil?{
??panic(err)
?}
?fmt.Printf("The?signhash:?%x\nThe?signature:?%x\n",?*signData.signhash,?*signData.signature)
?//?驗(yàn)證
?status?:=?verifySign(signData,?&publicKey)
?fmt.Printf("The?verify?result?is:?%v\n",?status)
}
func?main()?{
?test()
}
See you ~
歡迎進(jìn)群一起進(jìn)行技術(shù)交流
加群方式:公眾號(hào)消息私信“加群”或加我好友再加群均可
