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

rsa前段加密

准备工作:其实鄙人也没那么强啦,第三方包是必须的

                            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

//关键工具类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
package com.web.utils;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.Provider;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidParameterException;
import java.security.interfaces.RSAPublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Date;
 
import javax.crypto.Cipher;
 
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
 
/**
  * RSA算法加密/解密工具类。
  *
  * @author fuchun
  * @version 1.0.0, 2010-05-05
  */
public abstract class RSAUtils {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils. class );
 
     /** 算法名称 */
     private static final String ALGORITHOM = "RSA" ;
     /**保存生成的密钥对的文件名称。 */
     private static final String RSA_PAIR_FILENAME = "/__RSA_PAIR.txt" ;
     /** 密钥大小 */
     private static final int KEY_SIZE = 1024 ;
     /** 默认的安全服务提供者 */
     private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();
 
     private static KeyPairGenerator keyPairGen = null ;
     private static KeyFactory keyFactory = null ;
     /** 缓存的密钥对。 */
     private static KeyPair oneKeyPair = null ;
 
     private static File rsaPairFile = null ;
 
     static {
         try {
             keyPairGen = KeyPairGenerator.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
             keyFactory = KeyFactory.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
         } catch (NoSuchAlgorithmException ex) {
             LOGGER.error(ex.getMessage());
         }
         rsaPairFile = new File(getRSAPairFilePath());
     }
 
     private RSAUtils() {
     }
 
     /**
      * 生成并返回RSA密钥对。
      */
     private static synchronized KeyPair generateKeyPair() {
         try {
             keyPairGen.initialize(KEY_SIZE, new SecureRandom(DateFormatUtils.format( new Date(), "yyyyMMdd" ).getBytes()));
             oneKeyPair = keyPairGen.generateKeyPair();
             saveKeyPair(oneKeyPair);
             return oneKeyPair;
         } catch (InvalidParameterException ex) {
             LOGGER.error( "KeyPairGenerator does not support a key length of " + KEY_SIZE + "." , ex);
         } catch (NullPointerException ex) {
             LOGGER.error( "RSAUtils#KEY_PAIR_GEN is null, can not generate KeyPairGenerator instance." ,
                     ex);
         }
         return null ;
     }
 
     /**
      * 返回生成/读取的密钥对文件的路径。
      */
     private static String getRSAPairFilePath() {
         String urlPath = RSAUtils. class .getResource( "/" ).getPath();
         return ( new File(urlPath).getParent() + RSA_PAIR_FILENAME);
     }
 
     /**
      * 若需要创建新的密钥对文件,则返回 {@code true},否则 {@code false}。
      */
     private static boolean isCreateKeyPairFile() {
         // 是否创建新的密钥对文件
         boolean createNewKeyPair = false ;
         if (!rsaPairFile.exists() || rsaPairFile.isDirectory()) {
             createNewKeyPair = true ;
         }
         return createNewKeyPair;
     }
 
     /**
      * 将指定的RSA密钥对以文件形式保存。
      *
      * @param keyPair 要保存的密钥对。
      */
     private static void saveKeyPair(KeyPair keyPair) {
         FileOutputStream fos = null ;
         ObjectOutputStream oos = null ;
         try {
             fos = FileUtils.openOutputStream(rsaPairFile);
             oos = new ObjectOutputStream(fos);
             oos.writeObject(keyPair);
         } catch (Exception ex) {
             ex.printStackTrace();
         } finally {
             IOUtils.closeQuietly(oos);
             IOUtils.closeQuietly(fos);
         }
     }
 
     /**
      * 返回RSA密钥对。
      */
     public static KeyPair getKeyPair() {
         // 首先判断是否需要重新生成新的密钥对文件
         if (isCreateKeyPairFile()) {
             // 直接强制生成密钥对文件,并存入缓存。
             return generateKeyPair();
         }
         if (oneKeyPair != null ) {
             return oneKeyPair;
         }
         return readKeyPair();
     }
     
     // 同步读出保存的密钥对
     private static KeyPair readKeyPair() {
         FileInputStream fis = null ;
         ObjectInputStream ois = null ;
         try {
             fis = FileUtils.openInputStream(rsaPairFile);
             ois = new ObjectInputStream(fis);
             oneKeyPair = (KeyPair) ois.readObject();
             return oneKeyPair;
         } catch (Exception ex) {
             ex.printStackTrace();
         } finally {
             IOUtils.closeQuietly(ois);
             IOUtils.closeQuietly(fis);
         }
         return null ;
     }
 
     /**
      * 根据给定的系数和专用指数构造一个RSA专用的公钥对象。
      *
      * @param modulus 系数。
      * @param publicExponent 专用指数。
      * @return RSA专用公钥对象。
      */
     public static RSAPublicKey generateRSAPublicKey( byte [] modulus, byte [] publicExponent) {
         RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec( new BigInteger(modulus),
                 new BigInteger(publicExponent));
         try {
             return (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
         } catch (InvalidKeySpecException ex) {
             LOGGER.error( "RSAPublicKeySpec is unavailable." , ex);
         } catch (NullPointerException ex) {
             LOGGER.error( "RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance." , ex);
         }
         return null ;
     }
 
     /**
      * 根据给定的系数和专用指数构造一个RSA专用的私钥对象。
      *
      * @param modulus 系数。
      * @param privateExponent 专用指数。
      * @return RSA专用私钥对象。
      */
     public static RSAPrivateKey generateRSAPrivateKey( byte [] modulus, byte [] privateExponent) {
         RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec( new BigInteger(modulus),
                 new BigInteger(privateExponent));
         try {
             return (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
         } catch (InvalidKeySpecException ex) {
             LOGGER.error( "RSAPrivateKeySpec is unavailable." , ex);
         } catch (NullPointerException ex) {
             LOGGER.error( "RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance." , ex);
         }
         return null ;
     }
     
     /**
      * 根据给定的16进制系数和专用指数字符串构造一个RSA专用的私钥对象。
      *
      * @param modulus 系数。
      * @param privateExponent 专用指数。
      * @return RSA专用私钥对象。
      */
     public static RSAPrivateKey getRSAPrivateKey(String hexModulus, String hexPrivateExponent) {
         if (StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPrivateExponent)) {
             if (LOGGER.isDebugEnabled()) {
                 LOGGER.debug( "hexModulus and hexPrivateExponent cannot be empty. RSAPrivateKey value is null to return." );
             }
             return null ;
         }
         byte [] modulus = null ;
         byte [] privateExponent = null ;
         try {
             modulus = Hex.decodeHex(hexModulus.toCharArray());
             privateExponent = Hex.decodeHex(hexPrivateExponent.toCharArray());
         } catch (DecoderException ex) {
             LOGGER.error( "hexModulus or hexPrivateExponent value is invalid. return null(RSAPrivateKey)." );
         }
         if (modulus != null && privateExponent != null ) {
             return generateRSAPrivateKey(modulus, privateExponent);
         }
         return null ;
     }
     
     /**
      * 根据给定的16进制系数和专用指数字符串构造一个RSA专用的公钥对象。
      *
      * @param modulus 系数。
      * @param publicExponent 专用指数。
      * @return RSA专用公钥对象。
      */
     public static RSAPublicKey getRSAPublidKey(String hexModulus, String hexPublicExponent) {
         if (StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPublicExponent)) {
             if (LOGGER.isDebugEnabled()) {
                 LOGGER.debug( "hexModulus and hexPublicExponent cannot be empty. return null(RSAPublicKey)." );
             }
             return null ;
         }
         byte [] modulus = null ;
         byte [] publicExponent = null ;
         try {
             modulus = Hex.decodeHex(hexModulus.toCharArray());
             publicExponent = Hex.decodeHex(hexPublicExponent.toCharArray());
         } catch (DecoderException ex) {
             LOGGER.error( "hexModulus or hexPublicExponent value is invalid. return null(RSAPublicKey)." );
         }
         if (modulus != null && publicExponent != null ) {
             return generateRSAPublicKey(modulus, publicExponent);
         }
         return null ;
     }
 
     /**
      * 使用指定的公钥加密数据。
      *
      * @param publicKey 给定的公钥。
      * @param data 要加密的数据。
      * @return 加密后的数据。
      */
     public static byte [] encrypt(PublicKey publicKey, byte [] data) throws Exception {
         Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
         ci.init(Cipher.ENCRYPT_MODE, publicKey);
         return ci.doFinal(data);
     }
 
     /**
      * 使用指定的私钥解密数据。
      *
      * @param privateKey 给定的私钥。
      * @param data 要解密的数据。
      * @return 原数据。
      */
     public static byte [] decrypt(PrivateKey privateKey, byte [] data) throws Exception {
         Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
         ci.init(Cipher.DECRYPT_MODE, privateKey);
         return ci.doFinal(data);
     }
 
     /**
      * 使用给定的公钥加密给定的字符串。
      * <p />
      * 若 {@code publicKey} 为 {@code null},或者 {@code plaintext} 为 {@code null} 则返回 {@code
      * null}。
      *
      * @param publicKey 给定的公钥。
      * @param plaintext 字符串。
      * @return 给定字符串的密文。
      */
     public static String encryptString(PublicKey publicKey, String plaintext) {
         if (publicKey == null || plaintext == null ) {
             return null ;
         }
         byte [] data = plaintext.getBytes();
         try {
             byte [] en_data = encrypt(publicKey, data);
             return new String(Hex.encodeHex(en_data));
         } catch (Exception ex) {
             LOGGER.error(ex.getCause().getMessage());
         }
         return null ;
     }
     
     /**
      * 使用默认的公钥加密给定的字符串。
      * <p />
      * 若{@code plaintext} 为 {@code null} 则返回 {@code null}。
      *
      * @param plaintext 字符串。
      * @return 给定字符串的密文。
      */
     public static String encryptString(String plaintext) {
         if (plaintext == null ) {
             return null ;
         }
         byte [] data = plaintext.getBytes();
         KeyPair keyPair = getKeyPair();
         try {
             byte [] en_data = encrypt((RSAPublicKey)keyPair.getPublic(), data);
             return new String(Hex.encodeHex(en_data));
         } catch (NullPointerException ex) {
             LOGGER.error( "keyPair cannot be null." );
         } catch (Exception ex) {
             LOGGER.error(ex.getCause().getMessage());
         }
         return null ;
     }
 
     /**
      * 使用给定的私钥解密给定的字符串。
      * <p />
      * 若私钥为 {@code null},或者 {@code encrypttext} 为 {@code null}或空字符串则返回 {@code null}。
      * 私钥不匹配时,返回 {@code null}。
      *
      * @param privateKey 给定的私钥。
      * @param encrypttext 密文。
      * @return 原文字符串。
      */
     public static String decryptString(PrivateKey privateKey, String encrypttext) {
         if (privateKey == null || StringUtils.isBlank(encrypttext)) {
             return null ;
         }
         try {
             byte [] en_data = Hex.decodeHex(encrypttext.toCharArray());
             byte [] data = decrypt(privateKey, en_data);
             return new String(data);
         } catch (Exception ex) {
             LOGGER.error(String.format( "\"%s\" Decryption failed. Cause: %s" , encrypttext, ex.getCause().getMessage()));
         }
         return null ;
     }
     
     /**
      * 使用默认的私钥解密给定的字符串。
      * <p />
      * 若{@code encrypttext} 为 {@code null}或空字符串则返回 {@code null}。
      * 私钥不匹配时,返回 {@code null}。
      *
      * @param encrypttext 密文。
      * @return 原文字符串。
      */
     public static String decryptString(String encrypttext) {
         if (StringUtils.isBlank(encrypttext)) {
             return null ;
         }
         KeyPair keyPair = getKeyPair();
         try {
             byte [] en_data = Hex.decodeHex(encrypttext.toCharArray());
             byte [] data = decrypt((RSAPrivateKey)keyPair.getPrivate(), en_data);
             return new String(data);
         } catch (NullPointerException ex) {
             LOGGER.error( "keyPair cannot be null." );
         } catch (Exception ex) {
             LOGGER.error(String.format( "\"%s\" Decryption failed. Cause: %s" , encrypttext, ex.getMessage()));
         }
         return null ;
     }
     
     /**
      * 使用默认的私钥解密由JS加密(使用此类提供的公钥加密)的字符串。
      *
      * @param encrypttext 密文。
      * @return {@code encrypttext} 的原文字符串。
      */
     public static String decryptStringByJs(String encrypttext) {
         String text = decryptString(encrypttext);
         if (text == null ) {
             return null ;
         }
         return StringUtils.reverse(text);
     }
     
     /** 返回已初始化的默认的公钥。*/
     public static RSAPublicKey getDefaultPublicKey() {
         KeyPair keyPair = getKeyPair();
         if (keyPair != null ) {
             return (RSAPublicKey)keyPair.getPublic();
         }
         return null ;
     }
     
     /** 返回已初始化的默认的私钥。*/
     public static RSAPrivateKey getDefaultPrivateKey() {
         KeyPair keyPair = getKeyPair();
         if (keyPair != null ) {
             return (RSAPrivateKey)keyPair.getPrivate();
         }
         return null ;
     }
     
     public static PublicKeyMap getPublicKeyMap() {
         PublicKeyMap publicKeyMap = new PublicKeyMap();
         RSAPublicKey rsaPublicKey = getDefaultPublicKey();
         publicKeyMap.setModulus( new String(Hex.encodeHex(rsaPublicKey.getModulus().toByteArray())));
         publicKeyMap.setExponent( new String(Hex.encodeHex(rsaPublicKey.getPublicExponent().toByteArray())));
         return publicKeyMap;
     }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.web.utils; public class PublicKeyMap {
  private String modulus;
  private String exponent;
  public String getModulus() {
   return modulus;
  }
  public void setModulus(String modulus) {
   this .modulus = modulus;
  }
  public String getExponent() {
   return exponent;
  }
  public void setExponent(String exponent) {
   this .exponent = exponent;
  }
  @Override
  public String toString() {
   return "PublicKeyMap [modulus=" + modulus + ", exponent=" + exponent
     + "]" ;
  }
}
//测试action
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.web.actions;
 
 
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.web.utils.PublicKeyMap;
import com.web.utils.RSAUtils;
 
public class UserAction extends ActionSupport{
 
     private static final long serialVersionUID = 3859457733764601693L;
 
     private String password;
     private Object json;
     public String getPassword() {
         return password;
     }
 
     public void setPassword(String password) {
         this .password = password;
     }
     
     public Object getJson() {
         return json;
     }
 
     public void setJson(Object json) {
         this .json = json;
     }
 
     /**
      * 获取系数和指数
      * @return
      * @throws Exception
      */
     public String keyPair() throws Exception{
         PublicKeyMap publicKeyMap = RSAUtils.getPublicKeyMap();
         System.out.println(publicKeyMap);
         setJson(publicKeyMap);
         return SUCCESS;
     }
     
     /**
      * 登录
      * @return
      * @throws Exception
      */
     public String login() throws Exception{
             String pwd  = RSAUtils.decryptStringByJs(getPassword());
             System.out.println(pwd);
             ActionContext.getContext().put( "pwd" , pwd);
             return SUCCESS;
     }
}


//struts.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE stru<span></ span >ts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
     "http://struts.apache.org/dtds/struts-2.3.dtd">
< struts >
     < package name = "default" namespace = "/user" extends = "json-default" >
         < action name = "login" class = "com.web.actions.UserAction" method = "login" >
             < result >/success.jsp</ result >
         </ action >
         < action name = "keyPair" class = "com.web.actions.UserAction" method = "keyPair" >
             < result type = "json" >
                 < param name = "root" >json</ param >
             </ result >
         </ action >
     </ package >
</ struts >

//前台显示index.jsp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
< html >
   < head >
     < title >RSA</ title >
     < script type = "text/javascript" src = "<s:url value=" js/jquery-1.8.0.min.js" />"></ script >
     < script type = "text/javascript" src = "<s:url value=" js/security.js" />"></ script >
     < script type = "text/javascript" >
         $(function(){
             $("#btn").click(function(){
             $.getJSON('< s:url namespace = "/user" action = "keyPair" />',function(data) {
                         var modulus = data.modulus, exponent = data.exponent;
                         var epwd = $('#password').val();
                         if (epwd.length != 256) {
                             var publicKey = RSAUtils.getKeyPair(exponent, '', modulus);
                             $('#password').val(RSAUtils.encryptedString(publicKey, epwd));
                         }
                         $("#login").submit();
                     });
             });
         });
     </ script >
   </ head >
   
   < body >
     < form id = "login" name = "login" action = "<s:url namespace=" /user" action = "login" />" method="post">
          密码:< input type = "password" id = "password" name = "password" />
         < input id = "btn" type = "button" value = "提 交" />
     </ form >
   </ body >
</ html >

//success.jsp成功 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
< span ></ span ><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
< html >
   < head >
     < title >成功!</ title >
   </ head >
   
   < body >
     < h1 >密码是:</ h1 >
     < h1 >< s:property value = "#request.pwd" /></ h1 >
   </ body >
</ html >

以上是实现代码,希望能给各位朋友带来帮助

 结果图如下:

index.jsp

success.js

控制台


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值