原貼地址:
http://www.aygfsteel.com/security/archive/2006/01/11/27547.aspx
RSA協(xié)議我不再描述,大家可以看http://www.di-mgt.com.au/rsa_alg.html。
RSA的密鑰對(duì)生成時(shí)間依賴于兩個(gè)因素,
第一,密鑰的長度
第二,素?cái)?shù)的篩選質(zhì)量
在整個(gè)密鑰對(duì)生成過程中,RSA會(huì)隨機(jī)選擇兩個(gè)大素?cái)?shù),事實(shí)上,計(jì)算機(jī)的聰明
程度還不足以判斷某個(gè)隨機(jī)選擇的大素?cái)?shù)是否真的不可分解,因此,你只能夠通過
計(jì)算機(jī)程序來盡量將這個(gè)大隨機(jī)數(shù)不是素?cái)?shù)的幾率降到某個(gè)界限值(如0.0001)以下。
RSA KeyPair分為公鑰和私鑰,你應(yīng)該這樣使用KeyPair:
1,你使用私鑰來簽名,別人用你的公鑰來驗(yàn)證簽名
2,別人用你的公鑰加密信息M->M',你用私鑰來解密信息M'->M
雖然RSA經(jīng)受過多年深入的密碼分析,但大家在使用RSA的時(shí)候還是要注意以下事項(xiàng),
否則RSA的安全性會(huì)大打折扣:
1,合理的密鑰長度(setKeyLength)
RSA1024至今是安全的,按照目前密碼分析和計(jì)算機(jī)硬件條件的發(fā)展,估計(jì)在未來5-10年,
仍以難以破解。
2,素?cái)?shù)確定性選擇(setCertaintyOfPrime)
實(shí)際應(yīng)用中,選擇100就行了。
3,選擇合理的padding(setRSAMode)
RSA有三種模式,RAW, PKCS和OAEP,日常應(yīng)用中,我本人只使用PKCS(PKCS#1 v1.5)
和OAEP(PKCS#1 v2.0)這兩種padding模式。
padding跟安全性其實(shí)是緊密掛鉤的,有興趣的朋友可以看看PKCS#1標(biāo)準(zhǔn)討論。
我編寫了一個(gè)RSAUtils的工具類,下面的該類的測試代碼的一部分。
程序如下:
??RSAUtils utils =new RSAUtils();
??utils.setKeyLength(1024);
??utils.setCertaintyOfPrime(100);
??utils.setRSAMode(PKCS_RSA_MODE);?? //RAW =1? PKCS=2? OAEP=3
??utils.initRSAKeyPair();
??
??//查看公鑰
??RSAKeyParameters mypubkey=utils.getPublicKey();
??BigInteger mypubkey_modulus=mypubkey.getModulus();??
??BigInteger mypubkey_exponent=mypubkey.getExponent();
??System.out.println("##mypubkey的modulus長度="+mypubkey_modulus.bitLength());
??System.out.println("##mypubkey_modulus值="+mypubkey_modulus.toString());
??System.out.println("##mypubkey的exponent長度="+mypubkey.getExponent().bitLength());
??System.out.println("##mypubkey_exponent值="+mypubkey_exponent.toString());
??//查看私鑰
??RSAKeyParameters myprivkey=utils.getPrivateKey();
??BigInteger myprivkey_modulus=myprivkey.getModulus();
??System.out.println("##myprivkey的modulus長度="+myprivkey_modulus.bitLength());
??System.out.println("##myprivkey的modulus值="+myprivkey_modulus.toString());
??System.out.println("##myprivkey.getExponent()長度="+myprivkey.getExponent().bitLength());
??System.out.println("##myprivkey.getExponent()值="+myprivkey.getExponent());
以下是輸出:
##mypubkey的modulus長度=1024
##mypubkey_modulus值=93806062666699782638132820491933031482836826566660997927543724649365705443512121003172409185855121369631538039111403612211728268332662414248776212969019881724066055080327735965218365399595323200109436472147258110417469825748181131149217613806780318374365617984326523029965066348377550281908277056378455106547
##mypubkey的exponent長度=2
##mypubkey_exponent值=3
##myprivkey的modulus長度=1024
##myprivkey的modulus值=93806062666699782638132820491933031482836826566660997927543724649365705443512121003172409185855121369631538039111403612211728268332662414248776212969019881724066055080327735965218365399595323200109436472147258110417469825748181131149217613806780318374365617984326523029965066348377550281908277056378455106547
##myprivkey.getExponent()長度=1023
##myprivkey.getExponent()值=62537375111133188425421880327955354321891217711107331951695816432910470295674747335448272790570080913087692026074269074807818845555108276165850808646013241363962278455328383552959397735977285649455021534046301135296075808377308404258909132811288204167107604525033796313576612747649866739561523887875979483707
其中,要記住,公鑰的exponent即RSA算法中的e, e通常是3,17和65537
X.509建議使用65537,PEM建議使用3,PKCS#1建議使用3或65537,一般來說,都是選擇3。
私鑰的Exponent就是私鑰中最重要的部分,它就是私鑰區(qū)別于公鑰的地方!
接著,我們看看RSA的加密,解密過程。
通常,不要隨便對(duì)某一個(gè)別人發(fā)過來的東西進(jìn)行簽名(有潛在危險(xiǎn)),即使有這樣的必要,請(qǐng)先將它的文件進(jìn)行Digest或者HMAC
處理后,再做簽名。
為了說明RSA是如何加密信息的,我先讓大家脫離MD5/SHA1等輔助算法(沒有人會(huì)單獨(dú)使用RSA,RSAwithMD5,RSAwithSHA1才是常用的使用方法),來單獨(dú)看看RSA本身:
大家習(xí)慣了DES/IDEA,再看RSA的加密,可能會(huì)有一些不習(xí)慣,因?yàn)镽SA雖然也可以看成是基于Block的加密,但是,RSA的輸入和輸出的Block的大小是不一樣的,Block的大小依賴于你所使用的RSA Key的長度和RSA的padding模式。
在RSAUtils測試用例中,分別對(duì)RSA設(shè)置三種長度的Key(768,1024,2048)和2種padding模式(PKCS 1.5和OAEP),結(jié)果如下:
RSA??????????????? InBlock大小?? OutBlock大小? (單位,字節(jié))
768bit/PKCS??????? 85??????????????? 96
1024bit/PKCS???? 117?????????????? 128
2048bit/PKCS???? 245?????????????? 256
768bit/OAEP??????? 54??????????????? 96
1024bit/OAEP???? 86?????????????? 128
2048bit/OAEP???? 214?????????????? 256
大家可以看到,相同密鑰長度, 加密出來的密文長度要比明文要長,且OAEP的InBlock/OutBlock要比PKCS的InBlock/OutBlock要小,單從熵的角度,意味著OAEP padding模式引入更多的熵,OAEP要比PKCS更安全(事實(shí)上,為何提出OAEP代替PKCS,大家可以到RSA網(wǎng)站看看OAEP文檔 http://www.rsasecurity.com/rsalabs/node.asp?id=2125)。
下面,RSAUtils是我寫的針對(duì)BouncyCastle的一個(gè)工具類,它封裝了BouncyCastle的crypto中的RSAEngine,基本上,我很少單獨(dú)使用RSAUtils,我更多的是結(jié)合DiegestUtils來使用。