使用RSA加密完成登錄功能,防止用戶信息被抓包泄漏!

前言

之前項目中,登錄模塊發送登錄請求基本上都是明文傳輸用戶名、密碼,這樣如果系統的請求被惡意抓取,用戶的信息就會泄漏無疑,毫無安全可言,那麼有什麼辦法可以提高安全性呢?

  1. js加密
    在js中加密用戶的密碼,使之在傳輸過程中程加密狀態,這樣,即使在被惡意攔截了請求,獲取了用戶名密碼後,別人並不會知道密碼,因此完成加密!
  2. 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加密大概的流程,這樣有助於幫助我們更好的使用此加密手段。

  1. 首先,系統跟根據一定的規則生成一對祕鑰,
  2. 我們可以選擇一個祕鑰去公開它,另外一個一定要嚴格保密,通常公開的祕鑰我們稱之爲公鑰,留下的祕鑰稱之爲私鑰
  3. 我們可以對外開放一個可以獲取公鑰的接口,用於外部程序來獲取公鑰,外部應用通過此公鑰來加密數據,這些加密後的數據只能通過私鑰才能解開,相對的,私鑰加密的數據需要公鑰來解密,即使別人獲取了你的公鑰、’密文,只要私鑰不泄露,只要祕鑰位數足夠長,是解不開的。

代碼

頁面處理

在頁面上使用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地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章