RSA算法Java实现

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 09:33   11   0

Java代码收藏代码
  1. packagecom.hexun.blog.dongliwei.utils;
  2. importjavax.crypto.Cipher;
  3. importjava.security.*;
  4. importjava.security.spec.RSAPublicKeySpec;
  5. importjava.security.spec.RSAPrivateKeySpec;
  6. importjava.security.spec.InvalidKeySpecException;
  7. importjava.security.interfaces.RSAPrivateKey;
  8. importjava.security.interfaces.RSAPublicKey;
  9. importjava.io.*;
  10. importjava.math.BigInteger;
  11. /**
  12. *RSA工具类。提供加密,解密,生成密钥对等方法。
  13. *需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
  14. *RSA加密原理概述
  15. *RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数。
  16. *据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积
  17. *===================================================================
  18. *(该算法的安全性未得到理论的证明)
  19. *===================================================================
  20. *密钥的产生:
  21. *1.选择两个大素数p,q,计算n=p*q;
  22. *2.随机选择加密密钥e,要求e和(p-1)*(q-1)互质
  23. *3.利用Euclid算法计算解密密钥d,使其满足e*d=1(mod(p-1)*(q-1))(其中n,d也要互质)
  24. *4:至此得出公钥为(n,e)私钥为(n,d)
  25. *===================================================================
  26. *加解密方法:
  27. *1.首先将要加密的信息m(二进制表示)分成等长的数据块m1,m2,...,mi块长s(尽可能大),其中2^s<n
  28. *2:对应的密文是:ci=mi^e(modn)
  29. *3:解密时作如下计算:mi=ci^d(modn)
  30. *===================================================================
  31. *RSA速度
  32. *由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论是软件还是硬件实现。
  33. *速度一直是RSA的缺陷。一般来说只用于少量数据加密。
  34. *文件名:RSAUtil.java<br>
  35. *@author董利伟<br>
  36. *版本:<br>
  37. *描述:<br>
  38. *创建时间:2008-9-23下午09:58:16<br>
  39. *文件描述:<br>
  40. *修改者:<br>
  41. *修改日期:<br>
  42. *修改描述:<br>
  43. */
  44. publicclassRSAUtil{
  45. //密钥对
  46. privateKeyPairkeyPair=null;
  47. /**
  48. *初始化密钥对
  49. */
  50. publicRSAUtil(){
  51. try{
  52. this.keyPair=this.generateKeyPair();
  53. }catch(Exceptione){
  54. e.printStackTrace();
  55. }
  56. }
  57. /**
  58. *生成密钥对
  59. *@returnKeyPair
  60. *@throwsException
  61. */
  62. privateKeyPairgenerateKeyPair()throwsException{
  63. try{
  64. KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
  65. //这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
  66. finalintKEY_SIZE=1024;
  67. keyPairGen.initialize(KEY_SIZE,newSecureRandom());
  68. KeyPairkeyPair=keyPairGen.genKeyPair();
  69. returnkeyPair;
  70. }catch(Exceptione){
  71. thrownewException(e.getMessage());
  72. }
  73. }
  74. /**
  75. *生成公钥
  76. *@parammodulus
  77. *@parampublicExponent
  78. *@returnRSAPublicKey
  79. *@throwsException
  80. */
  81. privateRSAPublicKeygenerateRSAPublicKey(byte[]modulus,byte[]publicExponent)throwsException{
  82. KeyFactorykeyFac=null;
  83. try{
  84. keyFac=KeyFactory.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
  85. }catch(NoSuchAlgorithmExceptionex){
  86. thrownewException(ex.getMessage());
  87. }
  88. RSAPublicKeySpecpubKeySpec=newRSAPublicKeySpec(newBigInteger(modulus),newBigInteger(publicExponent));
  89. try{
  90. return(RSAPublicKey)keyFac.generatePublic(pubKeySpec);
  91. }catch(InvalidKeySpecExceptionex){
  92. thrownewException(ex.getMessage());
  93. }
  94. }
  95. /**
  96. *生成私钥
  97. *@parammodulus
  98. *@paramprivateExponent
  99. *@returnRSAPrivateKey
  100. *@throwsException
  101. */
  102. privateRSAPrivateKeygenerateRSAPrivateKey(byte[]modulus,byte[]privateExponent)throwsException{
  103. KeyFactorykeyFac=null;
  104. try{
  105. keyFac=KeyFactory.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
  106. }catch(NoSuchAlgorithmExceptionex){
  107. thrownewException(ex.getMessage());
  108. }
  109. RSAPrivateKeySpecpriKeySpec=newRSAPrivateKeySpec(newBigInteger(modulus),newBigInteger(privateExponent));
  110. try{
  111. return(RSAPrivateKey)keyFac.generatePrivate(priKeySpec);
  112. }catch(InvalidKeySpecExceptionex){
  113. thrownewException(ex.getMessage());
  114. }
  115. }
  116. /**
  117. *加密
  118. *@paramkey加密的密钥
  119. *@paramdata待加密的明文数据
  120. *@return加密后的数据
  121. *@throwsException
  122. */
  123. publicbyte[]encrypt(Keykey,byte[]data)throwsException{
  124. try{
  125. Ciphercipher=Cipher.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
  126. cipher.init(Cipher.ENCRYPT_MODE,key);
  127. //获得加密块大小,如:加密前数据为128个byte,而key_size=1024加密块大小为127byte,加密后为128个byte;
  128. //因此共有2个加密块,第一个127byte第二个为1个byte
  129. intblockSize=cipher.getBlockSize();
  130. intoutputSize=cipher.getOutputSize(data.length);//获得加密块加密后块大小
  131. intleavedSize=data.length%blockSize;
  132. intblocksSize=leavedSize!=0?data.length/blockSize+1:data.length/blockSize;
  133. byte[]raw=newbyte[outputSize*blocksSize];
  134. inti=0;
  135. while(data.length-i*blockSize>0){
  136. if(data.length-i*blockSize>blockSize)
  137. cipher.doFinal(data,i*blockSize,blockSize,raw,i*outputSize);
  138. else
  139. cipher.doFinal(data,i*blockSize,data.length-i*blockSize,raw,i*outputSize);
  140. //这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中
  141. //,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
  142. i++;
  143. }
  144. returnraw;
  145. }catch(Exceptione){
  146. thrownewException(e.getMessage());
  147. }
  148. }
  149. /**
  150. *解密
  151. *@paramkey解密的密钥
  152. *@paramraw已经加密的数据
  153. *@return解密后的明文
  154. *@throwsException
  155. */
  156. publicbyte[]decrypt(Keykey,byte[]raw)throwsException{
  157. try{
  158. Ciphercipher=Cipher.getInstance("RSA",neworg.bouncycastle.jce.provider.BouncyCastleProvider());
  159. cipher.init(cipher.DECRYPT_MODE,key);
  160. intblockSize=cipher.getBlockSize();
  161. ByteArrayOutputStreambout=newByteArrayOutputStream(64);
  162. intj=0;
  163. while(raw.length-j*blockSize>0){
  164. bout.write(cipher.doFinal(raw,j*blockSize,blockSize));
  165. j++;
  166. }
  167. returnbout.toByteArray();
  168. }catch(Exceptione){
  169. thrownewException(e.getMessage());
  170. }
  171. }
  172. /**
  173. *返回公钥
  174. *@return
  175. *@throwsException
  176. */
  177. publicRSAPublicKeygetRSAPublicKey()throwsException{
  178. //获取公钥
  179. RSAPublicKeypubKey=(RSAPublicKey)keyPair.getPublic();
  180. //获取公钥系数(字节数组形式)
  181. byte[]pubModBytes=pubKey.getModulus().toByteArray();
  182. //返回公钥公用指数(字节数组形式)
  183. byte[]pubPubExpBytes=pubKey.getPublicExponent().toByteArray();
  184. //生成公钥
  185. RSAPublicKeyrecoveryPubKey=this.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
  186. returnrecoveryPubKey;
  187. }
  188. /**
  189. *获取私钥
  190. *@return
  191. *@throwsException
  192. */
  193. publicRSAPrivateKeygetRSAPrivateKey()throwsException{
  194. //获取私钥
  195. RSAPrivateKeypriKey=(RSAPrivateKey)keyPair.getPrivate();
  196. //返回私钥系数(字节数组形式)
  197. byte[]priModBytes=priKey.getModulus().toByteArray();
  198. //返回私钥专用指数(字节数组形式)
  199. byte[]priPriExpBytes=priKey.getPrivateExponent().toByteArray();
  200. //生成私钥
  201. RSAPrivateKeyrecoveryPriKey=this.generateRSAPrivateKey(priModBytes,priPriExpBytes);
  202. returnrecoveryPriKey;
  203. }
  204. /**
  205. *测试
  206. *@paramargs
  207. *@throwsException
  208. */
  209. publicstaticvoidmain(String[]args)throwsException{
  210. RSAUtilrsa=newRSAUtil();
  211. Stringstr="董利伟";
  212. RSAPublicKeypubKey=rsa.getRSAPublicKey();
  213. RSAPrivateKeypriKey=rsa.getRSAPrivateKey();
  214. System.out.println("加密后=="+newString(rsa.encrypt(pubKey,str.getBytes())));
  215. System.out.println("解密后=="+newString(rsa.decrypt(priKey,rsa.encrypt(pubKey,str.getBytes()))));
  216. }
  217. }
7
1
分享到:
参考知识库
算法与数据结构知识库18251关注|2320收录
评论
8 楼wx_hello2014-12-06
sinosoft_yj 写道
denglei9018 写道
为什么得到的加密数据是乱码啊,请楼主大人讲解下



确实乱码,楼主讲解下呢!
7 楼sinosoft_yj2014-09-15
denglei9018 写道
为什么得到的加密数据是乱码啊,请楼主大人讲解下

6 楼denglei90182014-06-23
为什么得到的加密数据是乱码啊,请楼主大人讲解下
5 楼zhglhy2011-11-08
写得很好,收藏学习了
4 楼nextw32011-02-11
你好,有个疑问?

在RSAPublicKey、RSAPrivateKey方法中,为什么使用密钥对对象生成密钥后,还要再重新生成一遍?(是否是为了教程演示的需要?)
Java代码收藏代码
  1. RSAPrivateKeypriKey=(RSAPrivateKey)keyPair.getPrivate();
  2. //返回私钥系数(字节数组形式)
  3. byte[]priModBytes=priKey.getModulus().toByteArray();
  4. //返回私钥专用指数(字节数组形式)
  5. byte[]priPriExpBytes=priKey.getPrivateExponent().toByteArray();
  6. //生成私钥
  7. RSAPrivateKeyrecoveryPriKey=this.generateRSAPrivateKey(priModBytes,priPriExpBytes);
3 楼zyy20102010-10-20
如果不引入bcprov-jdk15-140.jar,在运行时改为:
Java代码收藏代码
  1. Ciphercipher=Cipher.getInstance("RSA");

这时
Java代码收藏代码
  1. intblockSize=cipher.getBlockSize();
blockSize 的值为0,楼主能否讲解一下
2 楼7636912010-08-11
注释很好 谢谢了 最近正在做有关加密的项目





80791834 J2EE高级技术群 欢迎来讨论
1 楼wh87662009-03-12
收藏了~

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP