前言
之前项目中,登录模块发送登录请求基本上都是明文传输用户名、密码,这样如果系统的请求被恶意抓取,用户的信息就会泄漏无疑,毫无安全可言,那么有什么办法可以提高安全性呢?
-
js加密
在js中加密用户的密码,使之在传输过程中程加密状态,这样,即使在被恶意拦截了请求,获取了用户名密码后,别人并不会知道密码,因此完成加密! -
RSA加密算法
RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
到目前为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。
2009年12月12日,编号为RSA-768(768 bits, 232 digits)数也被成功分解。这一事件威胁了现通行的1024-bit密钥的安全性,普遍认为用户应尽快升级到2048-bit或以上。
了解更多关于RSA
调查
在寻找保密方法的时候,曾经查看过很多知名网站的登录,大部分都是用户名不管,密码加密即可,所以我们采用同样的方式。
-
美团登录
-
阿里云登录
-
新浪登录
新浪可能是用户名也加密了,但是在请求中发现了
pwencode: rsa2
rsakv: 1330428213
基本可以初步判断新浪在登录上也是用了RSA加密
-
京东
在京东请求中发现了
pubKey
字段,京东可能也是使用了非对称加密。
简单原理
在使用RSA加密手段之前,我们需要了解RSA加密大概的流程,这样有助于帮助我们更好的使用此加密手段。
- 首先,系统跟根据一定的规则生成一对秘钥,
-
我们可以选择一个秘钥去公开它,另外一个一定要严格保密,通常公开的秘钥我们称之为
公钥
,留下的秘钥称之为
私钥
。 - 我们可以对外开放一个可以获取公钥的接口,用于外部程序来获取公钥,外部应用通过此公钥来加密数据,这些加密后的数据只能通过私钥才能解开,相对的,私钥加密的数据需要公钥来解密,即使别人获取了你的公钥、’密文,只要私钥不泄露,只要秘钥位数足够长,是解不开的。
代码
页面处理
在页面上使用rsa加密非常简单,我们只需要在页面写下如下代码,即可完成加密功能
var encrypt=new JSEncrypt();
encrypt.setPublicKey(public_key);
var rsa_password = encrypt.encrypt($('#password').val());
这样,密码就加密完成了。
后台处理
package rsalogin.util;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class RSAUtil {
//生成秘钥对
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
//获取公钥(Base64编码)
public static String getPublicKey(KeyPair keyPair){
PublicKey publicKey = keyPair.getPublic();
byte[] bytes = publicKey.getEncoded();
return byte2Base64(bytes);
}
//获取私钥(Base64编码)
public static String getPrivateKey(KeyPair keyPair){
PrivateKey privateKey = keyPair.getPrivate();
byte[] bytes = privateKey.getEncoded();
return byte2Base64(bytes);
}
//将Base64编码后的公钥转换成PublicKey对象
public static PublicKey string2PublicKey(String pubStr) throws Exception{
byte[] keyBytes = base642Byte(pubStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
//将Base64编码后的私钥转换成PrivateKey对象
public static PrivateKey string2PrivateKey(String priStr) throws Exception{
byte[] keyBytes = base642Byte(priStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
//公钥加密
public static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
//私钥解密
public static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
//字节数组转Base64编码
public static String byte2Base64(byte[] bytes){
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(bytes);
}
//Base64编码转字节数组
public static byte[] base642Byte(String base64Key) throws IOException{
BASE64Decoder decoder = new BASE64Decoder();
return decoder.decodeBuffer(base64Key);
}
}
Demo
主要代码如上所示,如果需要示例可以访问码云来查看我写的一个例子。
示例
如果发现错误或者其它问题请留言指正,谢谢!
- 此Demo采用了Springboot 2.0.4开发,模拟了登录加密的流程。
- 采用了定时刷新秘钥对策略,有助于私钥定期刷新。
页面所用的加密js的GitHub地址如下
页面加密js GitHub地址
版权声明:本文为New_Yao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。