域名备案要先做网站的吗,外包加工网官网下载app,古风模板网,网站优化团队前言
为了提高用户登陆的安全性#xff0c;公司准备整理一份相对安全的登陆模式。
想法
主流加密算法 主流加密算法 #xff08;一#xff09;对称加密AES ,其特点是#xff1a;算法简单#xff0c;加密速度快#xff1b; #xff08;二#xff09;非对称加密方式公司准备整理一份相对安全的登陆模式。
想法
主流加密算法 主流加密算法 一对称加密AES ,其特点是算法简单加密速度快 二非对称加密方式代表是RSA加密算法其特点–采用的一对秘钥机制即加解密秘钥不同公钥加密、私钥解密管理简单缺点是解密速度慢。 最终方式 具体过程是先由接收方创建RSA密钥对接收方通过Internet发送RSA公钥到发送方同时保存RSA私钥。而发送方创建AES密钥。并用该 AES密钥加密待传送的明文数据同时用接受的RSA公钥加密AES密钥最后把用RSA公钥加密后的AES密钥同密文一起通过Internet传输发送 到接收方。当接收方收到这个被加密的AES密钥和密文后首先调用接收方保存的RSA私钥并用该私钥解密加密的AES密钥得到AES密钥。最后用该 AES密钥解密密文得到明文。
基本流程
请求
服务器端(server)生成密钥对server给client自己的公钥client生成AES密钥(aesKey)client使用自己的RSA私钥(privateKey)对请求明文数据(params)进行数字签名将签名加入到请求参数中然后转换为json格式client使用aesKey对json数据进行加密得到密文(data)client使用sever的RSA公钥对aesKey进行加密(encryptkey)分别将data和encryptkey作为参数传输给服务器端
服务器端进行请求响应时将上面流程反过来即可
使用
安装crypto-js
npm install crypto-js
npm install jsencryptAES加密工具类
import CryptoJS from crypto-js
import { JSEncrypt } from jsencrypt
/*** 创建密钥* returns AES密钥*/
export function createAesKey() {const expect 16let str Math.random().toString(36).substr(2)while (str.length expect) {str Math.random().toString(36).substr(2)}str str.substr(0, 16)return str
}
/*** AES加密* param {*} word 加密字段* param {*} keyStr AES密钥* returns */
export function AESencrypt(word, keyStr) {keyStr keyStr ? keyStr : abcdefgabcdefg12;var key CryptoJS.enc.Utf8.parse(keyStr); //Latin1 w8m31Yy/Nw6thPsMpO5fgvar srcs CryptoJS.enc.Utf8.parse(word);var encrypted CryptoJS.DES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return encrypted.ciphertext.toString();
}
/*** RSA加密算法* param {*} pas * returns */
export function RSAencrypt(pas,publickey) {let jse new JSEncrypt();jse.setPublicKey(publickey);return jse.encrypt(pas)}服务端 RSA工具类
import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;public class RSAUtil {public static final String KEY_ALGORITHM RSA;public static final String SIGNATURE_ALGORITHM MD5withRSA;private static final String PUBLIC_KEY RSAPublicKey;private static final String PRIVATE_KEY RSAPrivateKey;public static byte[] decryptBASE64(String key) {return Base64.decodeBase64(key);}public static String encryptBASE64(byte[] bytes) {return Base64.encodeBase64String(bytes);}/*** 用私钥对信息生成数字签名** param data 加密数据* param privateKey 私钥* return* throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);// 取私钥匙对象PrivateKey priKey keyFactory.generatePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名Signature signature Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(priKey);signature.update(data);return encryptBASE64(signature.sign());}public static PrivateKey strToPrivateKey(String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);// 取私钥匙对象return keyFactory.generatePrivate(pkcs8KeySpec);}/*** 校验数字签名** param data 加密数据* param publicKey 公钥* param sign 数字签名* return 校验成功返回true 失败返回false* throws Exception*/public static boolean verify(byte[] data, String publicKey, String sign)throws Exception {// 解密由base64编码的公钥byte[] keyBytes decryptBASE64(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);// 取公钥匙对象PublicKey pubKey keyFactory.generatePublic(keySpec);Signature signature Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常return signature.verify(decryptBASE64(sign));}public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception{// 对密钥解密byte[] keyBytes decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey keyFactory.generatePrivate(pkcs8KeySpec);// 对数据解密Cipher cipher Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 解密br* 用私钥解密** param data* param key* return* throws Exception*/public static byte[] decryptByPrivateKey(String data, String key)throws Exception {return decryptByPrivateKey(decryptBASE64(data),key);}/*** 解密br* 用公钥解密** param data* param key* return* throws Exception*/public static byte[] decryptByPublicKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey keyFactory.generatePublic(x509KeySpec);// 对数据解密Cipher cipher Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 加密br* 用公钥加密** param data* param key* return* throws Exception*/public static byte[] encryptByPublicKey(String data, String key)throws Exception {// 对公钥解密byte[] keyBytes decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data.getBytes());}/*** 加密br* 用私钥加密** param data* param key* return* throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey keyFactory.generatePrivate(pkcs8KeySpec);// 对数据加密Cipher cipher Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 取得私钥** param keyMap* return* throws Exception*/public static String getPrivateKey(MapString, Key keyMap)throws Exception {Key key (Key) keyMap.get(PRIVATE_KEY);return encryptBASE64(key.getEncoded());}/*** 取得公钥** param keyMap* return* throws Exception*/public static String getPublicKey(MapString, Key keyMap)throws Exception {Key key keyMap.get(PUBLIC_KEY);return encryptBASE64(key.getEncoded());}/*** 初始化密钥** return* throws Exception*/public static MapString, Key initKey() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGen KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(1024);KeyPair keyPair keyPairGen.generateKeyPair();MapString, Key keyMap new HashMap(2);keyMap.put(PUBLIC_KEY, keyPair.getPublic());// 公钥keyMap.put(PRIVATE_KEY, keyPair.getPrivate());// 私钥return keyMap;}
}DES工具类
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Locale;public class DESUtil {/*** DES解密算法* param content 解密字段* param key 解密密钥* return*/public static String decryptedDES(String content,String key) {try {Cipher cipher Cipher.getInstance(DES/ECB/PKCS5Padding);cipher.init(Cipher.DECRYPT_MODE, generateKey(key));byte[] buf cipher.doFinal(hexStr2Bytes(content));return new String(buf, utf-8);} catch (Throwable e) {e.printStackTrace();}return null;}private static SecretKey generateKey(String secretKey)throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {SecretKeyFactory keyFactory SecretKeyFactory.getInstance(DES);DESKeySpec keySpec new DESKeySpec(secretKey.getBytes());keyFactory.generateSecret(keySpec);return keyFactory.generateSecret(keySpec);}public static byte[] hexStr2Bytes(String src) {src src.trim().replace( , ).toUpperCase(Locale.US);int m 0, n 0;int iLen src.length() / 2;byte[] ret new byte[iLen];for (int i 0; i iLen; i) {m i * 2 1;n m 1;ret[i] (byte) (Integer.decode(0x src.substring(i * 2, m) src.substring(m, n)) 0xFF);}return ret;}
}解密算法 前端入参 encryptedWords DES加密后的报文 encryptedKey RSA算法加密过的DES密钥
import com.bull3d.core.tool.utils.RedisUtil;
import com.bull3d.system.user.cache.CacheNames;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;/*** Author: zhangshl* Date: 2021/4/10 17:21* Modify: linyuchi* 重新编写解密算法。 2021/04/26*/
Component
AllArgsConstructor
public class DecryptUtil {private RedisUtil redisUtil;public String decrypt(String encryptedWords, String encryptedKey){// 解密aes密钥String privateKey String.valueOf(redisUtil.get(CacheNames.SRA_KRY_PRIVATE));if (null privateKey){return ;}try {String decrypt new String(RSAUtil.decryptByPrivateKey(encryptedKey,privateKey));return DESUtil.decryptedDES(encryptedWords,decrypt);} catch (Exception e) {e.printStackTrace();return ;}}
}前端获取RSA密钥我其实在服务端设计密钥对放在redis服务器中。过期时间为1天如果过期则从新生成。 /*** 获取RSA秘钥*/ApiOperation(value 获取RSA秘钥)GetMapping(/auth/rsa-key)public RString rsaKey(){String key authService.getRsaKey();return R.data(key);}