RSA使用簡述
RSA協議我不再描述,大家可以看http://www.di-mgt.com.au/rsa_alg.html。
RSA的密鑰對生成時間依賴于兩個因素,
第一,密鑰的長度
第二,素數的篩選質量
在整個密鑰對生成過程中,RSA會隨機選擇兩個大素數,事實上,計算機的聰明
程度還不足以判斷某個隨機選擇的大素數是否真的不可分解,因此,你只能夠通過
計算機程序來盡量將這個大隨機數不是素數的幾率降到某個界限值(如0.0001)以下。
RSA KeyPair分為公鑰和私鑰,你應該這樣使用KeyPair:
1,你使用私鑰來簽名,別人用你的公鑰來驗證簽名
2,別人用你的公鑰加密信息M->M',你用私鑰來解密信息M'->M
雖然RSA經受過多年深入的密碼分析,但大家在使用RSA的時候還是要注意以下事項,
否則RSA的安全性會大打折扣:
1,合理的密鑰長度(setKeyLength)
RSA1024至今是安全的,按照目前密碼分析和計算機硬件條件的發展,估計在未來5-10年,
仍以難以破解。
2,素數確定性選擇(setCertaintyOfPrime)
實際應用中,選擇100就行了。
3,選擇合理的padding(setRSAMode)
RSA有三種模式,RAW, PKCS和OAEP,日常應用中,我本人只使用PKCS(PKCS#1 v1.5)
和OAEP(PKCS#1 v2.0)這兩種padding模式。
padding跟安全性其實是緊密掛鉤的,有興趣的朋友可以看看PKCS#1標準討論。
我編寫了一個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就是私鑰中最重要的部分,它就是私鑰區別于公鑰的地方!
接著,我們看看RSA的加密,解密過程。
通常,不要隨便對某一個別人發過來的東西進行簽名(有潛在危險),即使有這樣的必要,請先將它的文件進行Digest或者HMAC
處理后,再做簽名。
為了說明RSA是如何加密信息的,我先讓大家脫離MD5/SHA1等輔助算法(沒有人會單獨使用RSA,RSAwithMD5,RSAwithSHA1才是常用的使用方法),來單獨看看RSA本身:
大家習慣了DES/IDEA,再看RSA的加密,可能會有一些不習慣,因為RSA雖然也可以看成是基于Block的加密,但是,RSA的輸入和輸出的Block的大小是不一樣的,Block的大小依賴于你所使用的RSA Key的長度和RSA的padding模式。
在RSAUtils測試用例中,分別對RSA設置三種長度的Key(768,1024,2048)和2種padding模式(PKCS 1.5和OAEP),結果如下:
RSA InBlock大小 OutBlock大小 (單位,字節)
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更安全(事實上,為何提出OAEP代替PKCS,大家可以到RSA網站看看OAEP文檔 http://www.rsasecurity.com/rsalabs/node.asp?id=2125)。
下面,RSAUtils是我寫的針對BouncyCastle的一個工具類,它封裝了BouncyCastle的crypto中的RSAEngine,基本上,我很少單獨使用RSAUtils,我更多的是結合DiegestUtils來使用。
posted on 2006-01-11 11:24 david.turing 閱讀(10486) 評論(4) 編輯 收藏 所屬分類: Security領域