RSA加密算法的简单案例

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
系统运维管理,不限时长
简介:

SA加密算法是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击。

那关于RSA加密算法有哪些应用呢?以下举一个数据库身份验证的案例。

在使用数据集进行身份认证时,密码存在数据库中,认证时用户输入的密码与数据库中密码相同则认证通过,若数据库被破解了则对系统造成威胁,怎样保证系统安全呢?这里就可以应用RSA加密算法,对权限加密。

思路:

就是在url中传用户名密码时,先把用户名进行翻转,然后再进行加密,如输入的密码为12,实际后台进行加密的值为21,再与数据库进行验证,这样就可以避免数据库被破解查看到的是21的加密码,登陆系统时以21是无法登陆成功的。

以报表软件FineReport为例,这是一个能读取各类数据库的报表软件,分客户端和前端展示。

实现方案:

1、把RSA加密使用的第三方包,放到工程web-inf/lib文件夹下即可。

2、调用js文件

RSA文件夹为前端js加密时需要调用js文件,因此需要将Barrett.js、BigInt.js、RSA.js放到工程目录下如:WebReport/js,新建js文件夹放入js文件。

3、定义RSA加密类

定义RSAUtil.java类文件,先运行类中generateKeyPair()方法,会在服务器D盘中生成一个随机的RSAKey.txt文件,保存公钥和密钥,每访问一次这个方法会刷新一次txt文件。

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
package  com.fr.privilege;
 
import  java.io.ByteArrayOutputStream;
import  java.io.FileInputStream;
import  java.io.FileOutputStream;
import  java.io.ObjectInputStream;
import  java.io.ObjectOutputStream;
import  java.math.BigInteger;
import  java.security.KeyFactory;
import  java.security.KeyPair;
import  java.security.KeyPairGenerator;
import  java.security.NoSuchAlgorithmException;
import  java.security.PrivateKey;
import  java.security.PublicKey;
import  java.security.SecureRandom;
import  java.security.interfaces.RSAPrivateKey;
import  java.security.interfaces.RSAPublicKey;
import  java.security.spec.InvalidKeySpecException;
import  java.security.spec.RSAPrivateKeySpec;
import  java.security.spec.RSAPublicKeySpec;
 
import  javax.crypto.Cipher;
 
/**
  * RSA 工具类。提供加密,解密,生成密钥对等方法。
  * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
 
  */
public  class  RSAUtil {
     /**
      * * 生成密钥对 *
     
      * @return KeyPair *
      * @throws EncryptException
      */
     public  static  KeyPair generateKeyPair()  throws  Exception {
         try  {
             KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance( "RSA" ,
                     new  org.bouncycastle.jce.provider.BouncyCastleProvider());
             final  int  KEY_SIZE =  1024 ; // 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
             keyPairGen.initialize(KEY_SIZE,  new  SecureRandom());
             KeyPair keyPair = keyPairGen.generateKeyPair();
             saveKeyPair(keyPair);
             return  keyPair;
         catch  (Exception e) {
             throw  new  Exception(e.getMessage());
         }
     }
 
     public  static  KeyPair getKeyPair()  throws  Exception {
         FileInputStream fis =  new  FileInputStream( "C:/RSAKey.txt" );
         ObjectInputStream oos =  new  ObjectInputStream(fis);
         KeyPair kp = (KeyPair) oos.readObject();
         oos.close();
         fis.close();
         return  kp;
     }
 
     public  static  void  saveKeyPair(KeyPair kp)  throws  Exception {
 
         FileOutputStream fos =  new  FileOutputStream( "C:/RSAKey.txt" );
         ObjectOutputStream oos =  new  ObjectOutputStream(fos);
         // 生成密钥
         oos.writeObject(kp);
         oos.close();
         fos.close();
     }
 
     /**
      * * 生成公钥 *
     
      * @param modulus *
      * @param publicExponent *
      * @return RSAPublicKey *
      * @throws Exception
      */
     public  static  RSAPublicKey generateRSAPublicKey( byte [] modulus,
             byte [] publicExponent)  throws  Exception {
         KeyFactory keyFac =  null ;
         try  {
             keyFac = KeyFactory.getInstance( "RSA" ,
                     new  org.bouncycastle.jce.provider.BouncyCastleProvider());
         catch  (NoSuchAlgorithmException ex) {
             throw  new  Exception(ex.getMessage());
         }
 
         RSAPublicKeySpec pubKeySpec =  new  RSAPublicKeySpec( new  BigInteger(
                 modulus),  new  BigInteger(publicExponent));
         try  {
             return  (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
         catch  (InvalidKeySpecException ex) {
             throw  new  Exception(ex.getMessage());
         }
     }
 
     /**
      * * 生成私钥 *
     
      * @param modulus *
      * @param privateExponent *
      * @return RSAPrivateKey *
      * @throws Exception
      */
     public  static  RSAPrivateKey generateRSAPrivateKey( byte [] modulus,
             byte [] privateExponent)  throws  Exception {
         KeyFactory keyFac =  null ;
         try  {
             keyFac = KeyFactory.getInstance( "RSA" ,
                     new  org.bouncycastle.jce.provider.BouncyCastleProvider());
         catch  (NoSuchAlgorithmException ex) {
             throw  new  Exception(ex.getMessage());
         }
 
         RSAPrivateKeySpec priKeySpec =  new  RSAPrivateKeySpec( new  BigInteger(
                 modulus),  new  BigInteger(privateExponent));
         try  {
             return  (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
         catch  (InvalidKeySpecException ex) {
             throw  new  Exception(ex.getMessage());
         }
     }
 
     /**
      * * 加密 *
     
      * @param key
      *            加密的密钥 *
      * @param data
      *            待加密的明文数据 *
      * @return 加密后的数据 *
      * @throws Exception
      */
     public  static  byte [] encrypt(PublicKey pk,  byte [] data)  throws  Exception {
         try  {
             Cipher cipher = Cipher.getInstance( "RSA" ,
                     new  org.bouncycastle.jce.provider.BouncyCastleProvider());
             cipher.init(Cipher.ENCRYPT_MODE, pk);
             int  blockSize = cipher.getBlockSize(); // 获得加密块大小,如:加密前数据为128个byte,而key_size=1024
             // 加密块大小为127
             // byte,加密后为128个byte;因此共有2个加密块,第一个127
             // byte第二个为1个byte
             int  outputSize = cipher.getOutputSize(data.length); // 获得加密块加密后块大小
             int  leavedSize = data.length % blockSize;
             int  blocksSize = leavedSize !=  0  ? data.length / blockSize +  1
                     : data.length / blockSize;
             byte [] raw =  new  byte [outputSize * blocksSize];
             int  i =  0 ;
             while  (data.length - i * blockSize >  0 ) {
                 if  (data.length - i * blockSize > blockSize)
                     cipher.doFinal(data, i * blockSize, blockSize, raw, i
                             * outputSize);
                 else
                     cipher.doFinal(data, i * blockSize, data.length - i
                             * blockSize, raw, i * outputSize);
                 // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到
                 // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了
                 // OutputSize所以只好用dofinal方法。
 
                 i++;
             }
             return  raw;
         catch  (Exception e) {
             throw  new  Exception(e.getMessage());
         }
     }
 
     /**
      * * 解密 *
     
      * @param key
      *            解密的密钥 *
      * @param raw
      *            已经加密的数据 *
      * @return 解密后的明文 *
      * @throws Exception
      */
     public  static  byte [] decrypt(PrivateKey pk,  byte [] raw)  throws  Exception {
         try  {
             Cipher cipher = Cipher.getInstance( "RSA" ,
                     new  org.bouncycastle.jce.provider.BouncyCastleProvider());
             cipher.init(cipher.DECRYPT_MODE, pk);
             int  blockSize = cipher.getBlockSize();
             ByteArrayOutputStream bout =  new  ByteArrayOutputStream( 64 );
             int  j =  0 ;
 
             while  (raw.length - j * blockSize >  0 ) {
                 bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
                 j++;
             }
             return  bout.toByteArray();
         catch  (Exception e) {
             throw  new  Exception(e.getMessage());
         }
     }
 
     /**
      * * *
     
      * @param args *
      * @throws Exception
      */
     public  static  void  main(String[] args)  throws  Exception {
         RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair()
                 .getPublic();
         String test =  "hello world" ;
         byte [] en_test = encrypt(getKeyPair().getPublic(), test.getBytes());
         System.out.println( "123:"  new  String(en_test));
         byte [] de_test = decrypt(getKeyPair().getPrivate(), en_test);
         System.out.println( new  String(de_test));
     }
}

4、定义密码验证类

定义TestPasswordValidatorRSA.java密码验证类

定义一个类,命名为TestPasswordValidatorRSA.java,扩展于AbstractPasswordValidator,重写其中密码验证方法encodePassword,先把输入的密码进行翻转,然后再进行加密,返回密码进行验证,具体代码如下:

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
package  com.fr.privilege;  
 
import  com.fr.privilege.providers.dao.AbstractPasswordValidator;  
public  class  TestPasswordValidatorRSA  extends  AbstractPasswordValidator{  
     //@Override
     public  String encodePassword( String clinetPassword) {
         try  {
             //对密码进行翻转如输入ab翻转后为ba
             StringBuffer sb =  new  StringBuffer();  
             sb.append( new  String(clinetPassword));
             String bb = sb.reverse().toString();
             //进行加密
             byte [] en_test = RSAUtil.encrypt(RSAUtil.getKeyPair().getPublic(),bb.getBytes());          
             //进行解密,如果数据库里面保存的是加密码,则此处不需要进行解密
             byte [] de_test = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),en_test);  
             //返回加密密码
             clinetPassword= new  String(de_test);       
         catch  (Exception e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
         return  clinetPassword;  //即获取加密密码再与数据库密码匹配。  
     }
 
     @Override
     public  boolean  validatePassword(String arg0, String arg1) {
         // TODO Auto-generated method stub
         return  false ;
     }
 
 
}

5、编译类文件

首先编译RSAUtil.java类文件在服务器的D盘生成RSAKey.txt文件,再编译TestPasswordValidatorRSA.java类,把编译后的class文件放到项目工程web-inf/classes/com/fr/privilege文件夹中。

6、登陆Login.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
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
<%@page contentType= "text/html"  pageEncoding= "UTF-8" %>
<%@page import= "com.fr.privilege.providers.dao.RSAUtil" %>
<%!public String Testmo() {
         String module =  "" ;
         try  {
             java.security.interfaces.RSAPublicKey rsap = (java.security.interfaces.RSAPublicKey) RSAUtil
                     .getKeyPair().getPublic();
             module = rsap.getModulus().toString(16);
         catch  (Exception e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
         return  module;
     }%>
<%!public String Testem() {
         String empoent =  "" ;
         try  {
             java.security.interfaces.RSAPublicKey rsap = (java.security.interfaces.RSAPublicKey) RSAUtil
                     .getKeyPair().getPublic();
             empoent = rsap.getPublicExponent().toString(16);
         catch  (Exception e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
         return  empoent;
     }%>
<html>
     <head>
         <script type= "text/javascript"
             src= "ReportServer?op=emb&resource=finereport.js" ></script>
         <script type= "text/javascript"  src= "js/RSA.js" ></script>
         <script type= "text/javascript"  src= "js/BigInt.js" ></script>
         <script type= "text/javascript"  src= "js/Barrett.js" ></script>
         <script type= "text/javascript" >    
     function  bodyRSA()  
     {  
     setMaxDigits(130);  
     var  a =  "<%=Testmo()%>" ;
     var  b =  "<%=Testem()%>" ;
     key =  new  RSAKeyPair(b, "" ,a);
    
function  doSubmit() {   
     bodyRSA(); 
     var  username = FR.cjkEncode(document.getElementById( "username" ).value);  //获取输入的用户名    
     var  password = FR.cjkEncode(document.getElementById( "password" ).value);   //获取输入的参数    
     $.ajax({    
         url :  "ReportServer?op=auth_login&fr_username="  + username +  "&fr_password="  + password,    //将用户名和密码发送到报表认证地址op=auth_login   
         data : {__redirect__ :  'false' },        
         complete :  function (res) {    
             var  jo = FR.jsonDecode(res.responseText);    
             if (jo.url) {    
                window.location=jo.url+  "&_="  new  Date().getTime();    //认证成功跳转页面,因为ajax不支持重定向所有需要跳转的设置  
             }    
             else {    
                alert( "用户名密码错误!" )   //认证失败    
             }    
         }    
     })    
}    
</script>
     </head>
     <body>
         <p>
             请登录
         </p>
         <form name= "login"  method= "POST" >
             <p>
                 用户名:
                 <input id= "username"  type= "text"  />
             </p>
             <p>
                 密 码:
                 <input id= "password"  type= "password"  />
             </p>
             <input type= "button"  value= "登录"  onclick= "doSubmit()"   />
         </form>
     </body>
</html>


本文转自 雄霸天下啦 51CTO博客,原文链接:http://blog.51cto.com/10549520/1839220,如需转载请自行联系原作者
相关文章
|
3月前
|
存储 安全 数据安全/隐私保护
打造安全防线!Python AES&RSA加密工具,黑客绕道走的秘籍
【9月更文挑战第9天】随着数字化时代的到来,信息安全问题日益凸显。本文将介绍如何使用Python结合AES与RSA两种加密算法,构建强大的加密工具。AES以其高效性和强安全性著称,适用于大量数据的快速加密;RSA作为非对称加密算法,在加密小量数据及实现数字签名方面表现卓越。通过整合两者,可以构建既安全又灵活的加密系统。首先,需要安装pycryptodome库。接着,实现AES加密与解密功能,最后利用RSA加密AES密钥,确保其安全传输。这种设计不仅提高了数据传输效率,还增强了密钥交换的安全性,为敏感数据提供坚实保护。
235 43
|
3月前
|
安全 算法 网络安全
网络安全与信息安全:构建数字世界的坚固防线在数字化浪潮席卷全球的今天,网络安全与信息安全已成为维系社会秩序、保障个人隐私和企业机密的关键防线。本文旨在深入探讨网络安全漏洞的本质、加密技术的前沿进展以及提升公众安全意识的重要性,通过一系列生动的案例和实用的建议,为读者揭示如何在日益复杂的网络环境中保护自己的数字资产。
本文聚焦于网络安全与信息安全领域的核心议题,包括网络安全漏洞的识别与防御、加密技术的应用与发展,以及公众安全意识的培养策略。通过分析近年来典型的网络安全事件,文章揭示了漏洞产生的深层原因,阐述了加密技术如何作为守护数据安全的利器,并强调了提高全社会网络安全素养的紧迫性。旨在为读者提供一套全面而实用的网络安全知识体系,助力构建更加安全的数字生活环境。
|
2月前
|
存储 分布式计算 算法
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
72 0
|
3月前
|
安全 算法 网络安全
浅谈非对称加密(RSA)
浅谈非对称加密(RSA)
156 0
|
2月前
|
存储 算法 搜索推荐
这些算法在实际应用中有哪些具体案例呢
【10月更文挑战第19天】这些算法在实际应用中有哪些具体案例呢
52 1
|
2月前
|
算法 数据可视化 新制造
Threejs路径规划_基于A*算法案例完整版
这篇文章详细介绍了如何在Three.js中完整实现基于A*算法的路径规划案例,包括网格构建、路径寻找算法的实现以及路径可视化展示等方面的内容。
78 0
Threejs路径规划_基于A*算法案例完整版
|
2月前
|
算法 安全 Go
RSA加密算法详解与Python和Go实现
RSA加密算法详解与Python和Go实现
149 1
|
2月前
|
算法 安全 网络安全
使用 Python 实现 RSA 加密
使用 Python 实现 RSA 加密
95 2
|
2月前
|
存储 算法 机器人
Threejs路径规划_基于A*算法案例V2
这篇文章详细介绍了如何在Three.js中使用A*算法进行高效的路径规划,并通过三维物理电路的实例演示了路径计算和优化的过程。
86 0
|
3月前
|
存储 安全 算法
RSA在手,安全我有!Python加密解密技术,让你的数据密码坚不可摧
【9月更文挑战第11天】在数字化时代,信息安全至关重要。传统的加密方法已难以应对日益复杂的网络攻击。RSA加密算法凭借其强大的安全性和广泛的应用场景,成为保护敏感数据的首选。本文介绍RSA的基本原理及在Python中的实现方法,并探讨其优势与挑战。通过使用PyCryptodome库,我们展示了RSA加密解密的完整流程,帮助读者理解如何利用RSA为数据提供安全保障。
143 5