Java中的RSA加密解密实现

该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar

下载地址:http://download.csdn.net/detail/centralperk/5025595

注意:
RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。
RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下
异常:

[java] view plain copy
  1. Exceptioninthread"main"javax.crypto.IllegalBlockSizeException:Datamustnotbelongerthan117bytes
  2. atcom.sun.crypto.provider.RSACipher.a(DashoA13*..)
  3. atcom.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
  4. atjavax.crypto.Cipher.doFinal(DashoA13*..)

RSAUtils.java
[java] view plain copy
  1. packagesecurity;
  2. importjava.io.ByteArrayOutputStream;
  3. importjava.security.Key;
  4. importjava.security.KeyFactory;
  5. importjava.security.KeyPair;
  6. importjava.security.KeyPairGenerator;
  7. importjava.security.PrivateKey;
  8. importjava.security.PublicKey;
  9. importjava.security.Signature;
  10. importjava.security.interfaces.RSAPrivateKey;
  11. importjava.security.interfaces.RSAPublicKey;
  12. importjava.security.spec.PKCS8EncodedKeySpec;
  13. importjava.security.spec.X509EncodedKeySpec;
  14. importjava.util.HashMap;
  15. importjava.util.Map;
  16. importjavax.crypto.Cipher;
  17. /***//**
  18. *<p>
  19. *RSA公钥/私钥/签名工具包
  20. *</p>
  21. *<p>
  22. *罗纳德·李维斯特(Ron[R]ivest)、阿迪·萨莫尔(Adi[S]hamir)和伦纳德·阿德曼(Leonard[A]dleman)
  23. *</p>
  24. *<p>
  25. *字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
  26. *由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
  27. *非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
  28. *</p>
  29. *
  30. *@authorIceWee
  31. *@date2012-4-26
  32. *@version1.0
  33. */
  34. publicclassRSAUtils{
  35. /***//**
  36. *加密算法RSA
  37. */
  38. publicstaticfinalStringKEY_ALGORITHM="RSA";
  39. /***//**
  40. *签名算法
  41. */
  42. publicstaticfinalStringSIGNATURE_ALGORITHM="MD5withRSA";
  43. /***//**
  44. *获取公钥的key
  45. */
  46. privatestaticfinalStringPUBLIC_KEY="RSAPublicKey";
  47. /***//**
  48. *获取私钥的key
  49. */
  50. privatestaticfinalStringPRIVATE_KEY="RSAPrivateKey";
  51. /***//**
  52. *RSA最大加密明文大小
  53. */
  54. privatestaticfinalintMAX_ENCRYPT_BLOCK=117;
  55. /***//**
  56. *RSA最大解密密文大小
  57. */
  58. privatestaticfinalintMAX_DECRYPT_BLOCK=128;
  59. /***//**
  60. *<p>
  61. *生成密钥对(公钥和私钥)
  62. *</p>
  63. *
  64. *@return
  65. *@throwsException
  66. */
  67. publicstaticMap<String,Object>genKeyPair()throwsException{
  68. KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance(KEY_ALGORITHM);
  69. keyPairGen.initialize(1024);
  70. KeyPairkeyPair=keyPairGen.generateKeyPair();
  71. RSAPublicKeypublicKey=(RSAPublicKey)keyPair.getPublic();
  72. RSAPrivateKeyprivateKey=(RSAPrivateKey)keyPair.getPrivate();
  73. Map<String,Object>keyMap=newHashMap<String,Object>(2);
  74. keyMap.put(PUBLIC_KEY,publicKey);
  75. keyMap.put(PRIVATE_KEY,privateKey);
  76. returnkeyMap;
  77. }
  78. /***//**
  79. *<p>
  80. *用私钥对信息生成数字签名
  81. *</p>
  82. *
  83. *@paramdata已加密数据
  84. *@paramprivateKey私钥(BASE64编码)
  85. *
  86. *@return
  87. *@throwsException
  88. */
  89. publicstaticStringsign(byte[]data,StringprivateKey)throwsException{
  90. byte[]keyBytes=Base64Utils.decode(privateKey);
  91. PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);
  92. KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
  93. PrivateKeyprivateK=keyFactory.generatePrivate(pkcs8KeySpec);
  94. Signaturesignature=Signature.getInstance(SIGNATURE_ALGORITHM);
  95. signature.initSign(privateK);
  96. signature.update(data);
  97. returnBase64Utils.encode(signature.sign());
  98. }
  99. /***//**
  100. *<p>
  101. *校验数字签名
  102. *</p>
  103. *
  104. *@paramdata已加密数据
  105. *@parampublicKey公钥(BASE64编码)
  106. *@paramsign数字签名
  107. *
  108. *@return
  109. *@throwsException
  110. *
  111. */
  112. publicstaticbooleanverify(byte[]data,StringpublicKey,Stringsign)
  113. throwsException{
  114. byte[]keyBytes=Base64Utils.decode(publicKey);
  115. X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(keyBytes);
  116. KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
  117. PublicKeypublicK=keyFactory.generatePublic(keySpec);
  118. Signaturesignature=Signature.getInstance(SIGNATURE_ALGORITHM);
  119. signature.initVerify(publicK);
  120. signature.update(data);
  121. returnsignature.verify(Base64Utils.decode(sign));
  122. }
  123. /***//**
  124. *<P>
  125. *私钥解密
  126. *</p>
  127. *
  128. *@paramencryptedData已加密数据
  129. *@paramprivateKey私钥(BASE64编码)
  130. *@return
  131. *@throwsException
  132. */
  133. publicstaticbyte[]decryptByPrivateKey(byte[]encryptedData,StringprivateKey)
  134. throwsException{
  135. byte[]keyBytes=Base64Utils.decode(privateKey);
  136. PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);
  137. KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
  138. KeyprivateK=keyFactory.generatePrivate(pkcs8KeySpec);
  139. Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
  140. cipher.init(Cipher.DECRYPT_MODE,privateK);
  141. intinputLen=encryptedData.length;
  142. ByteArrayOutputStreamout=newByteArrayOutputStream();
  143. intoffSet=0;
  144. byte[]cache;
  145. inti=0;
  146. //对数据分段解密
  147. while(inputLen-offSet>0){
  148. if(inputLen-offSet>MAX_DECRYPT_BLOCK){
  149. cache=cipher.doFinal(encryptedData,offSet,MAX_DECRYPT_BLOCK);
  150. }else{
  151. cache=cipher.doFinal(encryptedData,offSet,inputLen-offSet);
  152. }
  153. out.write(cache,0,cache.length);
  154. i++;
  155. offSet=i*MAX_DECRYPT_BLOCK;
  156. }
  157. byte[]decryptedData=out.toByteArray();
  158. out.close();
  159. returndecryptedData;
  160. }
  161. /***//**
  162. *<p>
  163. *公钥解密
  164. *</p>
  165. *
  166. *@paramencryptedData已加密数据
  167. *@parampublicKey公钥(BASE64编码)
  168. *@return
  169. *@throwsException
  170. */
  171. publicstaticbyte[]decryptByPublicKey(byte[]encryptedData,StringpublicKey)
  172. throwsException{
  173. byte[]keyBytes=Base64Utils.decode(publicKey);
  174. X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);
  175. KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
  176. KeypublicK=keyFactory.generatePublic(x509KeySpec);
  177. Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
  178. cipher.init(Cipher.DECRYPT_MODE,publicK);
  179. intinputLen=encryptedData.length;
  180. ByteArrayOutputStreamout=newByteArrayOutputStream();
  181. intoffSet=0;
  182. byte[]cache;
  183. inti=0;
  184. //对数据分段解密
  185. while(inputLen-offSet>0){
  186. if(inputLen-offSet>MAX_DECRYPT_BLOCK){
  187. cache=cipher.doFinal(encryptedData,offSet,MAX_DECRYPT_BLOCK);
  188. }else{
  189. cache=cipher.doFinal(encryptedData,offSet,inputLen-offSet);
  190. }
  191. out.write(cache,0,cache.length);
  192. i++;
  193. offSet=i*MAX_DECRYPT_BLOCK;
  194. }
  195. byte[]decryptedData=out.toByteArray();
  196. out.close();
  197. returndecryptedData;
  198. }
  199. /***//**
  200. *<p>
  201. *公钥加密
  202. *</p>
  203. *
  204. *@paramdata源数据
  205. *@parampublicKey公钥(BASE64编码)
  206. *@return
  207. *@throwsException
  208. */
  209. publicstaticbyte[]encryptByPublicKey(byte[]data,StringpublicKey)
  210. throwsException{
  211. byte[]keyBytes=Base64Utils.decode(publicKey);
  212. X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);
  213. KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
  214. KeypublicK=keyFactory.generatePublic(x509KeySpec);
  215. //对数据加密
  216. Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
  217. cipher.init(Cipher.ENCRYPT_MODE,publicK);
  218. intinputLen=data.length;
  219. ByteArrayOutputStreamout=newByteArrayOutputStream();
  220. intoffSet=0;
  221. byte[]cache;
  222. inti=0;
  223. //对数据分段加密
  224. while(inputLen-offSet>0){
  225. if(inputLen-offSet>MAX_ENCRYPT_BLOCK){
  226. cache=cipher.doFinal(data,offSet,MAX_ENCRYPT_BLOCK);
  227. }else{
  228. cache=cipher.doFinal(data,offSet,inputLen-offSet);
  229. }
  230. out.write(cache,0,cache.length);
  231. i++;
  232. offSet=i*MAX_ENCRYPT_BLOCK;
  233. }
  234. byte[]encryptedData=out.toByteArray();
  235. out.close();
  236. returnencryptedData;
  237. }
  238. /***//**
  239. *<p>
  240. *私钥加密
  241. *</p>
  242. *
  243. *@paramdata源数据
  244. *@paramprivateKey私钥(BASE64编码)
  245. *@return
  246. *@throwsException
  247. */
  248. publicstaticbyte[]encryptByPrivateKey(byte[]data,StringprivateKey)
  249. throwsException{
  250. byte[]keyBytes=Base64Utils.decode(privateKey);
  251. PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);
  252. KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
  253. KeyprivateK=keyFactory.generatePrivate(pkcs8KeySpec);
  254. Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
  255. cipher.init(Cipher.ENCRYPT_MODE,privateK);
  256. intinputLen=data.length;
  257. ByteArrayOutputStreamout=newByteArrayOutputStream();
  258. intoffSet=0;
  259. byte[]cache;
  260. inti=0;
  261. //对数据分段加密
  262. while(inputLen-offSet>0){
  263. if(inputLen-offSet>MAX_ENCRYPT_BLOCK){
  264. cache=cipher.doFinal(data,offSet,MAX_ENCRYPT_BLOCK);
  265. }else{
  266. cache=cipher.doFinal(data,offSet,inputLen-offSet);
  267. }
  268. out.write(cache,0,cache.length);
  269. i++;
  270. offSet=i*MAX_ENCRYPT_BLOCK;
  271. }
  272. byte[]encryptedData=out.toByteArray();
  273. out.close();
  274. returnencryptedData;
  275. }
  276. /***//**
  277. *<p>
  278. *获取私钥
  279. *</p>
  280. *
  281. *@paramkeyMap密钥对
  282. *@return
  283. *@throwsException
  284. */
  285. publicstaticStringgetPrivateKey(Map<String,Object>keyMap)
  286. throwsException{
  287. Keykey=(Key)keyMap.get(PRIVATE_KEY);
  288. returnBase64Utils.encode(key.getEncoded());
  289. }
  290. /***//**
  291. *<p>
  292. *获取公钥
  293. *</p>
  294. *
  295. *@paramkeyMap密钥对
  296. *@return
  297. *@throwsException
  298. */
  299. publicstaticStringgetPublicKey(Map<String,Object>keyMap)
  300. throwsException{
  301. Keykey=(Key)keyMap.get(PUBLIC_KEY);
  302. returnBase64Utils.encode(key.getEncoded());
  303. }
  304. }

Base64Utils.java
[java] view plain copy
  1. packagesecurity;
  2. importjava.io.ByteArrayInputStream;
  3. importjava.io.ByteArrayOutputStream;
  4. importjava.io.File;
  5. importjava.io.FileInputStream;
  6. importjava.io.FileOutputStream;
  7. importjava.io.InputStream;
  8. importjava.io.OutputStream;
  9. importit.sauronsoftware.base64.Base64;
  10. /***//**
  11. *<p>
  12. *BASE64编码解码工具包
  13. *</p>
  14. *<p>
  15. *依赖javabase64-1.3.1.jar
  16. *</p>
  17. *
  18. *@authorIceWee
  19. *@date2012-5-19
  20. *@version1.0
  21. */
  22. publicclassBase64Utils{
  23. /***//**
  24. *文件读取缓冲区大小
  25. */
  26. privatestaticfinalintCACHE_SIZE=1024;
  27. /***//**
  28. *<p>
  29. *BASE64字符串解码为二进制数据
  30. *</p>
  31. *
  32. *@parambase64
  33. *@return
  34. *@throwsException
  35. */
  36. publicstaticbyte[]decode(Stringbase64)throwsException{
  37. returnBase64.decode(base64.getBytes());
  38. }
  39. /***//**
  40. *<p>
  41. *二进制数据编码为BASE64字符串
  42. *</p>
  43. *
  44. *@parambytes
  45. *@return
  46. *@throwsException
  47. */
  48. publicstaticStringencode(byte[]bytes)throwsException{
  49. returnnewString(Base64.encode(bytes));
  50. }
  51. /***//**
  52. *<p>
  53. *将文件编码为BASE64字符串
  54. *</p>
  55. *<p>
  56. *大文件慎用,可能会导致内存溢出
  57. *</p>
  58. *
  59. *@paramfilePath文件绝对路径
  60. *@return
  61. *@throwsException
  62. */
  63. publicstaticStringencodeFile(StringfilePath)throwsException{
  64. byte[]bytes=fileToByte(filePath);
  65. returnencode(bytes);
  66. }
  67. /***//**
  68. *<p>
  69. *BASE64字符串转回文件
  70. *</p>
  71. *
  72. *@paramfilePath文件绝对路径
  73. *@parambase64编码字符串
  74. *@throwsException
  75. */
  76. publicstaticvoiddecodeToFile(StringfilePath,Stringbase64)throwsException{
  77. byte[]bytes=decode(base64);
  78. byteArrayToFile(bytes,filePath);
  79. }
  80. /***//**
  81. *<p>
  82. *文件转换为二进制数组
  83. *</p>
  84. *
  85. *@paramfilePath文件路径
  86. *@return
  87. *@throwsException
  88. */
  89. publicstaticbyte[]fileToByte(StringfilePath)throwsException{
  90. byte[]data=newbyte[0];
  91. Filefile=newFile(filePath);
  92. if(file.exists()){
  93. FileInputStreamin=newFileInputStream(file);
  94. ByteArrayOutputStreamout=newByteArrayOutputStream(2048);
  95. byte[]cache=newbyte[CACHE_SIZE];
  96. intnRead=0;
  97. while((nRead=in.read(cache))!=-1){
  98. out.write(cache,0,nRead);
  99. out.flush();
  100. }
  101. out.close();
  102. in.close();
  103. data=out.toByteArray();
  104. }
  105. returndata;
  106. }
  107. /***//**
  108. *<p>
  109. *二进制数据写文件
  110. *</p>
  111. *
  112. *@parambytes二进制数据
  113. *@paramfilePath文件生成目录
  114. */
  115. publicstaticvoidbyteArrayToFile(byte[]bytes,StringfilePath)throwsException{
  116. InputStreamin=newByteArrayInputStream(bytes);
  117. FiledestFile=newFile(filePath);
  118. if(!destFile.getParentFile().exists()){
  119. destFile.getParentFile().mkdirs();
  120. }
  121. destFile.createNewFile();
  122. OutputStreamout=newFileOutputStream(destFile);
  123. byte[]cache=newbyte[CACHE_SIZE];
  124. intnRead=0;
  125. while((nRead=in.read(cache))!=-1){
  126. out.write(cache,0,nRead);
  127. out.flush();
  128. }
  129. out.close();
  130. in.close();
  131. }
  132. }

RSATester.java

[java] view plain copy
  1. packagesecurity;
  2. importjava.util.Map;
  3. publicclassRSATester{
  4. staticStringpublicKey;
  5. staticStringprivateKey;
  6. static{
  7. try{
  8. Map<String,Object>keyMap=RSAUtils.genKeyPair();
  9. publicKey=RSAUtils.getPublicKey(keyMap);
  10. privateKey=RSAUtils.getPrivateKey(keyMap);
  11. System.err.println("公钥:\n\r"+publicKey);
  12. System.err.println("私钥:\n\r"+privateKey);
  13. }catch(Exceptione){
  14. e.printStackTrace();
  15. }
  16. }
  17. publicstaticvoidmain(String[]args)throwsException{
  18. test();
  19. testSign();
  20. }
  21. staticvoidtest()throwsException{
  22. System.err.println("公钥加密——私钥解密");
  23. Stringsource="这是一行没有任何意义的文字,你看完了等于没看,不是吗?";
  24. System.out.println("\r加密前文字:\r\n"+source);
  25. byte[]data=source.getBytes();
  26. byte[]encodedData=RSAUtils.encryptByPublicKey(data,publicKey);
  27. System.out.println("加密后文字:\r\n"+newString(encodedData));
  28. byte[]decodedData=RSAUtils.decryptByPrivateKey(encodedData,privateKey);
  29. Stringtarget=newString(decodedData);
  30. System.out.println("解密后文字:\r\n"+target);
  31. }
  32. staticvoidtestSign()throwsException{
  33. System.err.println("私钥加密——公钥解密");
  34. Stringsource="这是一行测试RSA数字签名的无意义文字";
  35. System.out.println("原文字:\r\n"+source);
  36. byte[]data=source.getBytes();
  37. byte[]encodedData=RSAUtils.encryptByPrivateKey(data,privateKey);
  38. System.out.println("加密后:\r\n"+newString(encodedData));
  39. byte[]decodedData=RSAUtils.decryptByPublicKey(encodedData,publicKey);
  40. Stringtarget=newString(decodedData);
  41. System.out.println("解密后:\r\n"+target);
  42. System.err.println("私钥签名——公钥验证签名");
  43. Stringsign=RSAUtils.sign(encodedData,privateKey);
  44. System.err.println("签名:\r"+sign);
  45. booleanstatus=RSAUtils.verify(encodedData,publicKey,sign);
  46. System.err.println("验证结果:\r"+status);
  47. }
  48. }

你可能感兴趣的:(java)