rsa协议我不再描述,大家可以看。
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文档 )。
下面,rsautils是我写的针对bouncycastle的一个工具类,它封装了bouncycastle的crypto中的rsaengine,基本上,我很少单独使用rsautils,我更多的是结合diegestutils来使用。