关于使用JS前台加密、JAVA后台解密的RSA实现,RSA加密和签名

需求环境:

西安项目中,客户要求保护用户的密码信息,不允许在http中传递明文的密码信息。

实现:

用RSA非对称加密方式实现。后台生成rsa密钥对,然后在登陆页面设置rsa公钥,提交时用公钥加密密码,生成的密文传到后台,用私钥解密,获取密码明文。

这样客户端只需要知道rsa加密方式和公钥,前台不知道私钥是无法解密的,此解决方案还是相对比较安全的。

附件是参照网友资料的java+JS的实现,放在这里供大家下载。访问方式/RSA/login.jsp。

需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar文件。

因为后台要转换成bigint,所以对明文长度有些限制:

总长度不超过126(1汉字长度为9),如下两个字符串:

阿送大法散得阿送大法散得阿送

1232132131231231232131232K1232132131231231232131232K1232132131231231232131232K1232132131231231232131232K1234567890123456789012

RSA速度

* 由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论 是软件还是硬件实现。

* 速度一直是RSA的缺陷。一般来说只用于少量数据 加密。

Util.java

Java代码  

  1. package RSA;
  2. /**
  3. *
  4. */
  5. import java.io.ByteArrayOutputStream;
  6. import java.io.FileInputStream;
  7. import java.io.FileOutputStream;
  8. import java.io.ObjectInputStream;
  9. import java.io.ObjectOutputStream;
  10. import java.math.BigInteger;
  11. import java.security.KeyFactory;
  12. import java.security.KeyPair;
  13. import java.security.KeyPairGenerator;
  14. import java.security.NoSuchAlgorithmException;
  15. import java.security.PrivateKey;
  16. import java.security.PublicKey;
  17. import java.security.SecureRandom;
  18. import java.security.interfaces.RSAPrivateKey;
  19. import java.security.interfaces.RSAPublicKey;
  20. import java.security.spec.InvalidKeySpecException;
  21. import java.security.spec.RSAPrivateKeySpec;
  22. import java.security.spec.RSAPublicKeySpec;
  23. import javax.crypto.Cipher;
  24. /**
  25. * RSA 工具类。提供加密,解密,生成密钥对等方法。
  26. * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
  27. *
  28. */
  29. public class RSAUtil {
  30. private static String RSAKeyStore = "C:/RSAKey.txt";
  31. /**
  32. * * 生成密钥对 *
  33. *
  34. * @return KeyPair *
  35. * @throws EncryptException
  36. */
  37. public static KeyPair generateKeyPair() throws Exception {
  38. try {
  39. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
  40. new org.bouncycastle.jce.provider.BouncyCastleProvider());
  41. final int KEY_SIZE = 1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
  42. keyPairGen.initialize(KEY_SIZE, new SecureRandom());
  43. KeyPair keyPair = keyPairGen.generateKeyPair();
  44. System.out.println(keyPair.getPrivate());
  45. System.out.println(keyPair.getPublic());
  46. saveKeyPair(keyPair);
  47. return keyPair;
  48. } catch (Exception e) {
  49. throw new Exception(e.getMessage());
  50. }
  51. }
  52. public static KeyPair getKeyPair() throws Exception {
  53. FileInputStream fis = new FileInputStream(RSAKeyStore);
  54. ObjectInputStream oos = new ObjectInputStream(fis);
  55. KeyPair kp = (KeyPair) oos.readObject();
  56. oos.close();
  57. fis.close();
  58. return kp;
  59. }
  60. public static void saveKeyPair(KeyPair kp) throws Exception {
  61. FileOutputStream fos = new FileOutputStream(RSAKeyStore);
  62. ObjectOutputStream oos = new ObjectOutputStream(fos);
  63. // 生成密钥
  64. oos.writeObject(kp);
  65. oos.close();
  66. fos.close();
  67. }
  68. /**
  69. * * 生成公钥 *
  70. *
  71. * @param modulus *
  72. * @param publicExponent *
  73. * @return RSAPublicKey *
  74. * @throws Exception
  75. */
  76. public static RSAPublicKey generateRSAPublicKey(byte[] modulus,
  77. byte[] publicExponent) throws Exception {
  78. KeyFactory keyFac = null;
  79. try {
  80. keyFac = KeyFactory.getInstance("RSA",
  81. new org.bouncycastle.jce.provider.BouncyCastleProvider());
  82. } catch (NoSuchAlgorithmException ex) {
  83. throw new Exception(ex.getMessage());
  84. }
  85. RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
  86. modulus), new BigInteger(publicExponent));
  87. try {
  88. return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
  89. } catch (InvalidKeySpecException ex) {
  90. throw new Exception(ex.getMessage());
  91. }
  92. }
  93. /**
  94. * * 生成私钥 *
  95. *
  96. * @param modulus *
  97. * @param privateExponent *
  98. * @return RSAPrivateKey *
  99. * @throws Exception
  100. */
  101. public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,
  102. byte[] privateExponent) throws Exception {
  103. KeyFactory keyFac = null;
  104. try {
  105. keyFac = KeyFactory.getInstance("RSA",
  106. new org.bouncycastle.jce.provider.BouncyCastleProvider());
  107. } catch (NoSuchAlgorithmException ex) {
  108. throw new Exception(ex.getMessage());
  109. }
  110. RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(
  111. modulus), new BigInteger(privateExponent));
  112. try {
  113. return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
  114. } catch (InvalidKeySpecException ex) {
  115. throw new Exception(ex.getMessage());
  116. }
  117. }
  118. /**
  119. * * 加密 *
  120. *
  121. * @param key
  122. *            加密的密钥 *
  123. * @param data
  124. *            待加密的明文数据 *
  125. * @return 加密后的数据 *
  126. * @throws Exception
  127. */
  128. public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {
  129. try {
  130. Cipher cipher = Cipher.getInstance("RSA",
  131. new org.bouncycastle.jce.provider.BouncyCastleProvider());
  132. cipher.init(Cipher.ENCRYPT_MODE, pk);
  133. int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024
  134. // 加密块大小为127
  135. // byte,加密后为128个byte;因此共有2个加密块,第一个127
  136. // byte第二个为1个byte
  137. int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小
  138. int leavedSize = data.length % blockSize;
  139. int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
  140. : data.length / blockSize;
  141. byte[] raw = new byte[outputSize * blocksSize];
  142. int i = 0;
  143. while (data.length - i * blockSize > 0) {
  144. if (data.length - i * blockSize > blockSize)
  145. cipher.doFinal(data, i * blockSize, blockSize, raw, i
  146. * outputSize);
  147. else
  148. cipher.doFinal(data, i * blockSize, data.length - i
  149. * blockSize, raw, i * outputSize);
  150. // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到
  151. // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了
  152. // OutputSize所以只好用dofinal方法。
  153. i++;
  154. }
  155. return raw;
  156. } catch (Exception e) {
  157. throw new Exception(e.getMessage());
  158. }
  159. }
  160. /**
  161. * * 解密 *
  162. *
  163. * @param key
  164. *            解密的密钥 *
  165. * @param raw
  166. *            已经加密的数据 *
  167. * @return 解密后的明文 *
  168. * @throws Exception
  169. */
  170. public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {
  171. try {
  172. Cipher cipher = Cipher.getInstance("RSA",
  173. new org.bouncycastle.jce.provider.BouncyCastleProvider());
  174. cipher.init(cipher.DECRYPT_MODE, pk);
  175. int blockSize = cipher.getBlockSize();
  176. ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
  177. int j = 0;
  178. while (raw.length - j * blockSize > 0) {
  179. bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
  180. j++;
  181. }
  182. return bout.toByteArray();
  183. } catch (Exception e) {
  184. throw new Exception(e.getMessage());
  185. }
  186. }
  187. /**
  188. * * *
  189. *
  190. * @param args *
  191. * @throws Exception
  192. */
  193. public static void main(String[] args) throws Exception {
  194. RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair().getPublic();
  195. String test = "hello world";
  196. byte[] en_test = encrypt(getKeyPair().getPublic(), test.getBytes());
  197. byte[] de_test = decrypt(getKeyPair().getPrivate(), en_test);
  198. System.out.println(new String(de_test));
  199. }
  200. }

LoginAction.java

Java代码  

  1. package RSA;
  2. //login
  3. /*
  4. * Generated by MyEclipse Struts
  5. * Template path: templates/java/JavaClass.vtl
  6. */
  7. import java.math.BigInteger;
  8. import java.net.URLDecoder;
  9. import java.net.URLEncoder;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import RSA.RSAUtil;
  13. /**
  14. * MyEclipse Struts Creation date: 06-28-2008
  15. *
  16. * XDoclet definition:
  17. *
  18. * @struts.action path="/login" name="loginForm" input="/login.jsp"
  19. *                scope="request" validate="true"
  20. * @struts.action-forward name="error" path="/error.jsp"
  21. * @struts.action-forward name="success" path="/success.jsp"
  22. */
  23. public class LoginAction {
  24. /*
  25. * Generated Methods
  26. */
  27. /**
  28. * Method execute
  29. *
  30. * @param mapping
  31. * @param form
  32. * @param request
  33. * @param response
  34. * @return ActionForward
  35. */
  36. public boolean execute(HttpServletRequest request,
  37. HttpServletResponse response) throws Exception {
  38. String pwd ;
  39. String result = request.getParameter("result");
  40. System.out.println("原文加密后为:");
  41. System.out.println(result);
  42. byte[] en_result = new BigInteger(result, 16).toByteArray();
  43. //System.out.println("转成byte[]" + new String(en_result));
  44. byte[] de_result = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),
  45. en_result);
  46. System.out.println("还原密文:");
  47. System.out.println(new String(de_result));
  48. StringBuffer sb = new StringBuffer();
  49. sb.append(new String(de_result));
  50. pwd = sb.reverse().toString();
  51. System.out.println(sb);
  52. System.out.println("=================================");
  53. pwd = URLDecoder.decode(pwd,"UTF-8");//
  54. System.out.println(pwd);
  55. request.setAttribute("pwd", pwd);
  56. return true;
  57. }
  58. }

登陆login.jsp

Html代码  

  1. <%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  3. <html:html lang="true">
  4. <head>
  5. <title>login</title>
  6. <script type="text/javascript" src="js/RSA.js"></script>
  7. <script type="text/javascript" src="js/BigInt.js"></script>
  8. <script type="text/javascript" src="js/Barrett.js"></script>
  9. <script type="text/javascript">
  10. function rsalogin(){
  11. var thisPwd = document.getElementById("password").value;
  12. bodyRSA();
  13. var result = encryptedString(key, encodeURIComponent(thisPwd));
  14. //alert(encodeURIComponent(thisPwd)+"\r\n"+result);
  15. loginForm.action="loginCHK.jsp?result="+result;
  16. loginForm.submit();
  17. }
  18. var key ;
  19. function bodyRSA(){
  20. setMaxDigits(130);
  21. key = new RSAKeyPair("10001","","8246a46f44fc4d961e139fd70f4787d272d374532f4d2d9b7cbaad6a15a8c1301319aa6b3f30413b859351c71938aec516fa7147b69168b195e81df46b6bed7950cf3a1c719d42175f73d7c97a85d7d20a9e83688b92f05b3059bb2ff75cd7190a042cd2db97ebc2ab4da366f2a7085556ed613b5a39c9fdd2bb2595d1dc23b5");
  22. }
  23. </script>
  24. </head>
  25. <body>
  26. <form method="post" name="loginForm" target=_blank>
  27. <table border="0">
  28. <tr>
  29. <td>
  30. Password:
  31. </td>
  32. <td>
  33. <input type=‘text‘ name="password" id=password style=‘width:400px‘ value="my passwd"/>
  34. </td>
  35. </tr>
  36. <tr>
  37. <td colspan="2" align="center">
  38. <input type="button" value="SUBMIT" onclick="rsalogin();" />
  39. </td>
  40. </tr>
  41. </table>
  42. </form>
  43. </body>
  44. </html:html>

登陆校验loginCHK.jsp

Html代码  

  1. <%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
  2. <jsp:directive.page import="RSA.LoginAction"/>
  3. <%
  4. LoginAction la = new LoginAction();
  5. la.execute(request ,response);
  6. %>
  7. pwd is [<%=request.getAttribute("pwd")%>]

================================================

另外,通过RSA还可以实现数字签名 :用私钥签名、公钥验证即可。具体可以看代码:

Java代码  

  1. package encode;
  2. import java.security.KeyPair;
  3. import java.security.KeyPairGenerator;
  4. import java.security.Signature;
  5. public class DigitalSignature2Example {
  6. public static void main(String[] args) {
  7. args = new String[] { "中国" };
  8. if (args.length != 1) {
  9. System.err.println("Usage:java DigitalSignature2Example ");
  10. System.exit(1);
  11. }
  12. try {
  13. byte[] plainText = args[0].getBytes("UTF-8");
  14. System.out.println("\nStart generating RSA key.");
  15. // 生成RSA密钥对
  16. KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
  17. // 初始化密钥长度
  18. keyGen.initialize(1024);
  19. // 生成密钥对
  20. KeyPair pair = keyGen.generateKeyPair();
  21. System.out.println("\nFinish generating RSA key.");
  22. // 使用私钥签名
  23. Signature sig = Signature.getInstance("SHA1WithRSA");
  24. // 用指定的私钥进行初始化
  25. sig.initSign(pair.getPrivate());
  26. // 添加要签名的信息
  27. sig.update(plainText);
  28. // 返回签名的字节数组
  29. byte[] signature = sig.sign();
  30. System.out.println(sig.getProvider().getInfo());
  31. System.out.println("\nSignature: ");
  32. System.out.println(new String(signature, "UTF-8"));
  33. // 使用公钥验证
  34. System.out.println("\nStart signature verification.");
  35. sig.initVerify(pair.getPublic());
  36. // 添加要验证的信息
  37. sig.update(plainText);
  38. if (sig.verify(signature)) {
  39. System.out.println("Signature verificated.");
  40. } else {
  41. System.out.println("Signature failed.");
  42. }
  43. } catch (Exception e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. }
时间: 2024-10-11 11:58:16

关于使用JS前台加密、JAVA后台解密的RSA实现,RSA加密和签名的相关文章

rsa实现js前台加密java后台解密

前段时间咱老大吩咐我写一个rsa前台加密到后台用java解密.(说实话这之前我还真没用过) 不过没办法啊,这是任务,于是研究了一下.圆满完成任务了,下面共享下实现思路: 准备工作:其实鄙人也没那么强啦,第三方包是必须的 bcprov-jdk15on-148.jar commons-codec-1.7.jar commons-lang-2.4.jar log4j-1.2.15.jar slf4j-api-1.6.1.jar package com.web.utils; import java.io

JS前台加密,java后台解密实现

因项目需求,需要对用户信息进行加密(以登录为例),前台js中对用户名密码进行加密传输. 然后后台进行解密操作 先看一下效果图 未对其加密传输 对其加密传输 从以上可以看出如果不对其进行加密的话,用户的一些敏感信息将会被捕捉到 1.前台JS <script type="text/javascript"> $(function() { $("#btn").click(function() { var username = encode64($("#

JAVA后台与前端JAVASCRIPT之间AES加密解密互通

调试了一天终于把java后台与javascript之间的AES加密解密成功了,记录一下过程. 后台java解密代码:解码算法及模式为 AES/CBC/PKCS5Padding key与iv要为16位 得到16的字符数组按照16进制编码转化为字符串 public static String encrypt(String content, String key) throws Exception { try { Key keySpec = new SecretKeySpec(key.getBytes

实现ios上传加密nodejs后台解密

今天在做项目的时候遇到一个问题,我需要在ios端把上传数据加密,防止中间代理捕获信息内容并修改数据库的信息.把数据传到后台在解码,实现数据安全. 下面介绍我实现的在nodejs的加密和解密的代码希望对需要解决相同问题的有一定的帮助. var assert = require('assert');    var crypto = require('crypto');     function test_des(param) {     var key = new Buffer(param.key)

删除JS前台校验,后台批量删除

1.功能需求 在一个数据表格中,选中欲删除的记录,点击删除按钮,先触发前台验证,然后调用后台处理逻辑 2.代码实现 HTML代码: <asp:Repeater ID="repInputList" runat="server" DataSourceID="InputsDataSource" EnableViewState="true" > <HeaderTemplate> <table cellpa

9.Java 加解密技术系列之 RSA

Java 加解密技术系列之 RSA 序 概念 工作流程 RSA 代码实现 加解密结果 结束语 序 距 离上一次写博客感觉已经很长时间了,先吐槽一下,这个月以来,公司一直在加班,又是发版.上线,又是新项目太紧,具体的就不多说了,想听我吐槽的小伙伴, 可以私信给我(*^__^*) .上一篇文章,已经把对称加密的算法讲完了.从今天开始,要说说非对称加密了.因为,非对称加密真的是太重要了,我们的日常生活中,都离不开非对称加密. 概念 在说 RSA 之前,首先聊聊什么是非对称加密.在讲对称加密的时候,就曾

Java 加解密技术系列之 RSA

序 距离上一次写博客感觉已经很长时间了,先吐槽一下,这个月以来,公司一直在加班,又是发版.上线,又是新项目太紧,具体的就不多说了,想听我吐槽的小伙伴,可以私信给我(*^__^*) .上一篇文章,已经把对称加密的算法讲完了.从今天开始,要说说非对称加密了.因为,非对称加密真的是太重要了,我们的日常生活中,都离不开非对称加密. 概念 在说 RSA 之前,首先聊聊什么是非对称加密.在讲对称加密的时候,就曾经说过,对称加密算法在加密和解密时使用的是同一个秘钥,加解密双方必须使用同一个密钥才能进行正常的沟

ios下使用RSA算法加密与java后台解密配合demo

首先了解一下几个相关概念,以方便后面遇到的问题的解决: 原网址:http://blog.csdn.net/jinglijun/article/details/7770315RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥.该算法能够抵抗目前已知的所有密码攻击.RSA算法是一种非对称算法,算法需要一对密钥

Java后台URL转码-Js编码和Java后台解码

方法一 String message = java.net.URLEncoder.encode("[西北局信息中心]采油气接口异常", "utf-8"); 前台传的如果是汉字的话,后台就用URLDecoder解码 1.java.将resultMsg 转为utf-8 (1) resultMsg = URLEncoder.encode(resultMsg, "utf-8"); (2) new String(request.getParameter(&