Cifrado y descifrado back-end antes y después del capítulo adicional sobre el crecimiento del programa ape (algoritmo híbrido de cifrado y descifrado rsa+aes)

En la víspera del Día Nacional de este año, me hice cargo de un proyecto externo y dije que era para garantizar la seguridad de los datos de la interfaz. La seguridad de los datos es relativamente fácil. Emmmmm, para la seguridad de la interfaz, debemos considerar algoritmos de cifrado y descifrado, listas blancas y otros asuntos. Así que planeo lanzar hoy un capítulo especial sobre el camino hacia el crecimiento sobre el tema de la seguridad de la interfaz.

Por qué considerar la seguridad de la interfaz

Presumiblemente, ustedes no necesitan gastar mucho tiempo y energía escribiendo una interfaz comercial no central, pero ¿alguna vez han considerado una pregunta: cuando estamos desarrollando algunos sistemas, especialmente para sistemas públicos y de clientes (como applets, cuentas oficiales), etc.), una vez que los datos de la interfaz son secuestrados, manipulados o incluso maliciosos e ilegales llamados remotamente a la interfaz, las consecuencias serán desastrosas. En este momento, debemos considerar cuidadosamente los problemas de seguridad de la interfaz.

¿Cuáles son los problemas de seguridad de la interfaz?

  1. Problema de derechos de acceso a la interfaz, hasta donde yo sé, hay derechos de acceso de inicio de sesión, derechos de acceso de roles y derechos de acceso de comportamiento

Autoridad de acceso de inicio de sesión:
la llamada autoridad de acceso de inicio de sesión significa que solo los usuarios autenticados tienen derecho a acceder a la interfaz, y se rechaza el acceso de usuarios no autenticados. Las soluciones
comunes son los marcos de seguridad shiro y spring, que resuelven el problema de acceso de inicio de sesión de una vez por todas. para todos.
Las soluciones poco comunes son los módulos de servicio de verificación de inicio de sesión personalizados aop e interceptor.

Autoridad de acceso a roles:
la llamada autoridad de acceso a roles significa que solo los roles relevantes tienen derecho a acceder, y la información de roles se puede obtener después de la autenticación de inicio de sesión del usuario, es decir, los usuarios con diferentes roles reciben una autoridad de acceso a roles diferente después del inicio de sesión. . Por ejemplo, es posible establecer dos roles de superadministrador y empleado ordinario para un determinado sistema.
De acuerdo con la granularidad diferente, las soluciones se dividen en formas de anotación + aop e interceptor [cómo realizar los dos derechos de acceso anteriores, cavar un hoyo primero y completar el siguiente problema] Derechos de acceso de comportamiento: Los llamados derechos de acceso de comportamiento
se
refieren a la restricción de un rol para realizar una determinada tarea.Operaciones de comportamiento.

  1. Los problemas de seguridad de los datos de la interfaz se dividen en problemas de seguridad de los parámetros entrantes y problemas de seguridad de los parámetros de retorno.

Problemas de seguridad de parámetros entrantes :
los parámetros entrantes generalmente se refieren a parámetros de solicitud, generalmente se refieren a parámetros de cuerpo de solicitud
@RequestMapping("test") public ResponseData test(@RequestBody String param1) { .... }
Aquí, param1 es el parámetro de
retorno
de parámetro entrante El parámetro de retorno generalmente se refiere al parámetro devuelto por la interfaz al front-end, como
public ResponseData test(@RequestBody String param1) { .... }
data: {errcode:'200',data:{}, errmsg:'插入成功!'}
datos aquí es el parámetro de retorno
para procesar esto La mejor manera de resolver estos problemas es realizar el cifrado y descifrado de front-end y back-end.

  1. Problema de dirección IP de acceso a la interfaz

Para evitar ataques distribuidos DDOS y evitar el acceso de proxy

Método de cifrado para problemas de seguridad de datos de interfaz

  1. Cifrado simétrico AES (cifrado y descifrado en forma de clave generada, la clave de cifrado y la clave de descifrado son las mismas)
    características: alta eficiencia de cifrado y descifrado, adecuado para el cifrado y descifrado de grandes cantidades de datos, pero la seguridad no es alta y no se puede autenticar.
  2. Cifrado asimétrico RSA (generar clave pública y clave privada de acuerdo con el algoritmo, cifrado de clave pública, descifrado de clave privada)
    características: baja eficiencia de cifrado y descifrado [porque las claves públicas y privadas son largas y son operaciones de módulo], adecuado para cifrar y descifrar contenido con una pequeña cantidad de datos, alta seguridad, con función de autenticación.
  3. Cifrado híbrido AES + RSA (cifre el texto sin formato con AES primero, luego cifre la clave AES con la clave pública RSA y devuelva el texto cifrado y la clave cifrada RSA) Características: Combinando las ventajas de los
    métodos 1 y 2, mejor Evite las deficiencias de los métodos 1 y 2

Introducir el principio de realización del algoritmo AES+RSA

Nota: cifrado de clave pública rsa, descifrado de clave privada rsa
inserte la descripción de la imagen aquí

Código backend del algoritmo AES+RSA

Aprenda del código de este tipo grande
https://blog.csdn.net/qq_36360181/article/details/111871712
código de algoritmo de cifrado y descifrado rsa


import com.alibaba.fastjson.JSONObject;
import com.zygswo.test1.common.exception.MyException;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * rsa 加解密工具类
 * @author 章瑜亮
 */
@Slf4j
public class RsaEncryptUtil<T> {
    
    
    /**
     * 加密算法
     */
    private static final String ALGO_NAME = "RSA";
    /**
     * RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024
     */
    public static final int KEY_SIZE = 2048;
    /**
     * 算法默认为RSA/NONE/PKCS1Padding,未验证
     */
    public static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";

    /**
     * 加密请求返回对象的公钥
     */
    private static final String PUBLIC_KEY = "";
    /**
     * 解密请求返回对象的私钥(放在配置文件中)
     */
   private static final String PRIVATE_KEY = "";

    /**
     * 注意只能生成一次
     * @return 私钥公钥密钥对
     */
    private static Map<String,String> generateKeyPairs() {
    
    
        try {
    
    
            KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGO_NAME);
            generator.initialize(KEY_SIZE);  //rsa长度
            KeyPair keyPair = generator.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            Map<String, String> map = new ConcurrentHashMap<>();
            map.put("public_key", Base64.getEncoder().encodeToString(publicKey.getEncoded()));
            map.put("private_key",Base64.getEncoder().encodeToString(privateKey.getEncoded()));
            return map;
        } catch (NoSuchAlgorithmException e) {
    
    
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 给AES密钥解密,再调用AES解密
     * @param privatekey 解密用的rsa私钥
     * @param encodedText 密文
     * @param aesKeyEncrypt rsa加密后的AES密钥
     * @return 解密后的明文
     */
    public static String decryptionRsaAndAes(String privatekey, String encodedText,String aesKeyEncrypt){
    
    
        // 解密
        String aesKeyDecrypt = decodeString(privatekey, aesKeyEncrypt);
        //解密后aes密钥
        String data = AesEncryptUtil.decryptStringBySecret(encodedText, aesKeyDecrypt);
        return data;
    }

    /**
     * 调用AES加密明文(JSON OBJECT),再用RSA算法加密AES密钥
     * @param data 明文
     * @return 解密后的明文
     */
    public static <T> Map<String, String> encryptionRsaAndAes(T data) {
    
    
        //加密明文
        log.info("-------------------data=" + JSONObject.toJSONString(data) + "---------------------");
        String encodedText = AesEncryptUtil.encryptString(JSONObject.toJSONString(data), AesEncryptUtil.SYMMETRY_ENCRYPT.AES);
        log.info("-------------------encodedText=" + encodedText + "---------------------");
        // 加密后aes密钥
        String aesKeyEncrypt = encodeString(PUBLIC_KEY, AesEncryptUtil.DEFAULT_SECRET);
        //解密后aes密钥
        Map<String, String> map = new ConcurrentHashMap<>();
        map.put("encodedText", encodedText);
        map.put("aesKeyEncrypt",aesKeyEncrypt);
        return map;
    }

    /**
     * 生成公私钥的算法(只生成一次)
     * @param args 参数
     */
//    public static void main(String[] args) {
    
    
//        Map<String,String> keyPairs = generateKeyPairs();
//        String publicKey = keyPairs.get("public_key");
//        String privateKey = keyPairs.get("private_key");
//        log.info("----------------publicKey = " + publicKey + "-------------------");
//        log.info("----------------privateKey = " + privateKey + "-------------------");
//        String encodedStr = encodeString(publicKey, "123456");
//        log.info("----------------base64Str = " + encodedStr + "-------------------");
//        String result = decodeString(privateKey, encodedStr);
//        log.info("----------------final result = " + result + "-------------------");
//    }

    /**
     * 加密算法
     * @param needEncodeText 需要加密的字符串
     * @param publicKey 加密密钥(公钥)
     */
    private static String encodeString(String publicKey, String needEncodeText) {
    
    
        try {
    
    
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            //将字符串转PublicKey对象
            // bytes 为base64处理后的字节码,所以要先base64Encoder一下
            byte[] data = Base64.getDecoder().decode(publicKey.getBytes());
            X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
            KeyFactory fact = KeyFactory.getInstance(ALGO_NAME);
            PublicKey publicKey1 = fact.generatePublic(spec);
            //初始化加密工具
            cipher.init(Cipher.ENCRYPT_MODE, publicKey1);
            //将需要加密的字串转字节码
            byte[] bytes = needEncodeText.getBytes();
            // 加密
            byte[] resultBytes = cipher.doFinal(bytes);
            //转base64(不清楚是否需要判断为空)
            return Base64.getEncoder().encodeToString(resultBytes);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeySpecException |
                InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
    
    
            e.printStackTrace();
            log.error(e.getMessage());
            throw new MyException(e.getMessage());
        }
    }

    /**
     * 解密算法
     * @param needDecodeText 需要解密的字符串
     * @param privateKey 解密密钥(私钥)
     */
    private static String decodeString(String privateKey, String needDecodeText) {
    
    
        try {
    
    
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            //将字符串转PublicKey对象
            // bytes 为base64处理后的字节码,所以要先base64Encoder一下
            byte[] data = Base64.getDecoder().decode(privateKey.getBytes());
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(data);
            KeyFactory fact = KeyFactory.getInstance(ALGO_NAME);
            PrivateKey privateKey1 = fact.generatePrivate(spec);
            //初始化加密工具
            cipher.init(Cipher.DECRYPT_MODE, privateKey1);
            //将需要加密的字串转字节码
            //base64转byte
            byte[] bytes = Base64.getDecoder().decode(needDecodeText.getBytes());
            // 解密
            byte[] resultBytes = cipher.doFinal(bytes);
            return resultBytes == null ? null : new String(resultBytes);
        } catch (Exception e) {
    
    
            e.printStackTrace();
            log.error(e.getMessage());
            throw new MyException("解密失败,请检查加解密密钥");
        }
    }
}

Código de algoritmo de cifrado y descifrado AES


import com.zygswo.test1.common.exception.MyException;
import lombok.extern.slf4j.Slf4j;


import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;

/**
 * aes加密
 */
@Slf4j
public class AesEncryptUtil {
    
    
        //DES算法要有一个随机数源,因为Random是根据时间戳生成的有限随机数,比较容易破解,所以在这里使用SecureRandom
        private static SecureRandom secureRandom = new SecureRandom();
        //AES默认加密key, 长度固定为16位,代表128bit的密钥
        static final String DEFAULT_SECRET = "自定义加密key";
        //字符集
        private static final String CHARSET = "UTF-8";

        /**
         * 功能描述: <br>
         * 〈字符串解密〉<密钥参数>
         */
        public static String decryptStringBySecret(String source, String secret) {
    
    
            try {
    
    
                byte[] sourceBytes = Base64.getDecoder().decode(source);
                byte[] secretBytes = secret.getBytes(CHARSET);
                byte[] encryptBytes = decrypt(sourceBytes, secretBytes, SYMMETRY_ENCRYPT.AES);
                return new String(encryptBytes, CHARSET);
            } catch (Exception e) {
    
    
                e.printStackTrace();
                throw new MyException("解密失败,请检查加解密密钥");
            }
        }

        /**
         * 功能描述: <br>
         * @param source 要加密的文本
         * @param encryptType 加密类型(AES,DES)
         * 〈字符串加密〉
         */
        public static String encryptString(String source, SYMMETRY_ENCRYPT encryptType) {
    
    
            try {
    
    
                byte[] sourceBytes = source.getBytes(CHARSET);
                byte[] secretBytes = DEFAULT_SECRET.getBytes(CHARSET);
                byte[] encryptBytes = encrypt(sourceBytes, secretBytes, encryptType);
                return Base64.getEncoder().encodeToString(encryptBytes);
            } catch (InvalidKeyException | NoSuchAlgorithmException | UnsupportedEncodingException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeySpecException e) {
    
    
                e.printStackTrace();
                throw new MyException(e.getMessage());
            }
        }

        /**
         * 功能描述: <br>
         * 〈字符串解密〉
         */
        public static String decryptString(String source, SYMMETRY_ENCRYPT encryptType) {
    
    
            try {
    
    
                byte[] sourceBytes = Base64.getDecoder().decode(source);
                byte[] secretBytes = DEFAULT_SECRET.getBytes(CHARSET);
                byte[] encryptBytes = decrypt(sourceBytes, secretBytes, encryptType);
                return new String(encryptBytes, CHARSET);
            } catch (InvalidKeyException | NoSuchAlgorithmException | UnsupportedEncodingException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeySpecException e) {
    
    
                e.printStackTrace();
                throw new MyException(e.getMessage());
            }
        }

        /**
         * 功能描述: <br>
         * 〈使用原始密钥数据转换为SecretKey对象〉
         */
        private static SecretKey getSecretKey(byte[] keyBytes, String type) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
    
    
            if ("DES".equals(type)) {
    
    
                // 创建一个密匙工厂
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(type);
                // 创建一个DESKeySpec对象
                DESKeySpec dks = new DESKeySpec(keyBytes);
                // 将DESKeySpec对象转换成SecretKey对象
                return keyFactory.generateSecret(dks);
            }
            return new SecretKeySpec(keyBytes, type);
        }

        /**
         * 功能描述: <br>
         * 〈DES加密〉
         */
        private static byte[] encrypt(byte[] contentArray, byte[] keyArray, SYMMETRY_ENCRYPT encryptType) throws InvalidKeyException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeySpecException {
    
    
            return symmetryDE(contentArray, keyArray, Cipher.ENCRYPT_MODE, encryptType);
        }

        /**
         * 功能描述: <br>
         * 〈DES解密〉
         */
        private static byte[] decrypt(byte[] encryptArray, byte[] keyArray, SYMMETRY_ENCRYPT encryptType) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidKeySpecException {
    
    
            return symmetryDE(encryptArray, keyArray, Cipher.DECRYPT_MODE, encryptType);
        }

        /**
         * 功能描述: <br>
         * 〈Cipher 加密解密操作〉
         */
        private static byte[] symmetryDE(byte[] contentArray, byte[] keyArray, int mode, SYMMETRY_ENCRYPT encryptType) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException {
    
    
            //获取密钥对象
            SecretKey secretKey = getSecretKey(keyArray, encryptType.getType());
            //获取真正执行加/解密操作的Cipher
            Cipher cipher = Cipher.getInstance(encryptType.getEncrypt());
            //用密匙初始化Cipher对象
            cipher.init(mode, secretKey, secureRandom);
            //执行加/解密操作
            return cipher.doFinal(contentArray);
        }

        /**
         * 功能描述: <br>
         * 〈加密方式〉
         *
         * @author Blare
         * @date 2019/12/11
         */
        enum SYMMETRY_ENCRYPT {
    
    
            AES("AES", "AES/ECB/PKCS5Padding"),
            DES("DES", "DES/ECB/PKCS5Padding");

            SYMMETRY_ENCRYPT(String type, String encrypt) {
    
    
                this.type = type;
                this.encrypt = encrypt;
            }

            private String type;
            private String encrypt;

            public String getType() {
    
    
                return type;
            }

            public String getEncrypt() {
    
    
                return encrypt;
            }
        }
}

Precauciones

Traté de usar el interceptor para descifrar los parámetros entrantes de la interfaz antes, pero descubrí que dado que el interceptor opera después del dispatcherServlet y antes de llamar al controlador, informará una excepción de cierre de vapor cuando se usa junto con la anotación @RequestBody, por lo que es mejor utilizar un filtro de tratar.

Código de filtro:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 过滤器
 * @author 章瑜亮
 */
@Component
@Slf4j
@WebFilter(filterName = "requestBodyFilter", urlPatterns = "/*", asyncSupported = true)
public class RequestBodyFilter implements Filter {
    
    

    @Override
    public void destroy() {
    
    

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)  throws ServletException, IOException{
    
    
        //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中。
        // 在chain.doFiler方法中传递新的request对象
        ServletRequest requestWrapper = null;
        if(request instanceof HttpServletRequest) {
    
    
            requestWrapper = new RequestWrapper((HttpServletRequest) request);
        }
        if(requestWrapper == null) {
    
    
            chain.doFilter(request, response);
        } else {
    
    
            chain.doFilter(requestWrapper, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    
    

    }
}

Además, para resolver la situación de que la solicitud solo se puede recuperar una vez, se implementa la clase HttpServletRequestWrapper, cuyo
código es el siguiente:

import com.alibaba.fastjson.JSONObject;
import com.zygswo.test1.common.exception.MyException;
import com.zygswo.test1.common.util.RsaEncryptUtil;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

/**
 * 确保request可以多次读取
 * @author 章瑜亮
 */
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
    
    
    /**
     * 私钥
     */
    private String privateKey = "";

    /**
     * 请求体
     */
    private byte[] body;

    public RequestWrapper(HttpServletRequest request) {
    
    
        super(request);
        // 获取requestbody中的数据
        body = getBodyString(request);
    }

    @Override
    public BufferedReader getReader() throws IOException {
    
    
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
    
    
        // 定义内存中的输入流
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {
    
    

            @Override
            public int read() throws IOException {
    
    
                // 使用内存输入流读取数据
                return bais.read();
            }

            @Override
            public boolean isFinished() {
    
    
                return false;
            }

            @Override
            public boolean isReady() {
    
    
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
    
    

            }
        };
    }

    /**
     * 永久获取request请求头并进行请求体参数处理
     * @param request
     * @return
     */
    private byte[] getBodyString(HttpServletRequest request)  {
    
    
        try (BufferedInputStream bis = new BufferedInputStream(request.getInputStream());
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
    
    
            byte[] buffer = new byte[1024];
            int len;
            while ((len = bis.read(buffer)) > 0) {
    
    
                baos.write(buffer, 0, len);
            }
            byte[] bytes= baos.toByteArray();
            String body = new String(bytes);
            log.info("------------------- body = " + body + "------------------------");
            if (isNotBlank(body)) {
    
    
                JSONObject jsonBody = JSONObject.parseObject(body);
                if (null != jsonBody) {
    
    
                    String aesKey = request.getHeader("token");
                    String dataEncrypt = jsonBody.getString("data");
                    String data;
                    JSONObject json = null;
                    try {
    
    
                        log.info("------------------- dataEncrypt = " + dataEncrypt + "------------------------");
                        log.info("------------------- aesKey = " + aesKey + "------------------------");
                        data = RsaEncryptUtil.decryptionRsaAndAes(privateKey, dataEncrypt, aesKey);
                        // 如果数据不为空就编译
                        if (isNotBlank(data)) {
    
    
                            //如果参数为空前端传回undefined
                            if ("undefined".equalsIgnoreCase(data)) {
    
    
                                json = new JSONObject();
                            } else {
    
    
                                json = JSONObject.parseObject(data);
                            }
                        }
                    } catch (Exception e) {
    
    
                        log.error(e.getMessage());
                        e.printStackTrace();
                        throw new MyException("解密失败,请检查加解密密钥");
                    }
                    if (json != null) {
    
    
                        body = json.toJSONString();
                    }
                    log.info("------------------- body = " + body + "------------------------");
                    return body.getBytes();
                }
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
            log.error(e.getMessage());
            throw new MyException("解密失败,请检查加解密密钥");
        }
        return null;
    }

    /**
     * 判断字符串是否为空
     * @param string 字符串
     * @return 是否为空
     */
    private boolean isNotBlank(String string) {
    
    
        return string != null && !"".equals(string);
    }
}


Finalmente, simplemente registre el filtro y podrá usarlo.

Implementación de código front-end

Preparación:

  1. npm descargar Crypto.js npm instalar crypto-js
  2. npm descargar jsencrypt.min.js
import CryptoJS, {
    
     enc } from "crypto-js";
import JSEncrypt from './jsencrypt.min.js'

export default {
    
    
	
	// AES密钥(加密前)
	aesKey : '',
	// AES密钥(加密后)
    aesKeyEncrypt: '',
	
	/**
	  * rsa + aes加密
	  *@param word:需要加密的内容
	  *@returns {*} :返回加密的内容
	  */
	 encryptFun:function(word) {
    
    
	    //初始化AES密钥
	    this.aesKey = this.get32RandomNum();
	    //加密AES密钥
	    var encrypt = new JSEncrypt();
		console.log(publicKey);
	    encrypt.setPublicKey(publicKey);
	    this.aesKeyEncrypt = encrypt.encrypt(this.aesKey);
	
	    //AES加密密钥
	    var key = CryptoJS.enc.Utf8.parse(this.aesKey);
	    //AES加密内容
	    var srcs = CryptoJS.enc.Utf8.parse(word);
	    //AES加密
	    var encrypted =CryptoJS.AES.encrypt(srcs, key, {
    
     mode: CryptoJS.mode.ECB, padding:CryptoJS.pad.Pkcs7 });
	    //返回
	    return encrypted.toString();
	},
	
	/**
	  * rsa + aes解密
	  *@param encodedText:需要解密的内容
	  *@returns {*} :返回解密的内容
	  */
	 decryptFun:function(encodedText) {
    
    
	    //获取参数
	    var resultObj = JSON.parse(encodedText);
		//获取加密后的aeskey 和内容
		var aesKeyEncrypt = resultObj['aesKeyEncrypt'];
		var encodedText = resultObj['encodedText'];
		console.log("解密前密文 ===> " + encodedText);

	    //解密AES密钥
	    var decrypt = new JSEncrypt();
		console.log(privateKey);
	    decrypt.setPrivateKey(privateKey);
	    var aesKey = decrypt.decrypt(aesKeyEncrypt);
	    console.log("解密后AES密钥 ===> " + aesKey);
	
	    //AES解密密钥
	    var key = CryptoJS.enc.Utf8.parse(aesKey);
	    //AES解密
	    var decrypted = CryptoJS.AES.decrypt(encodedText, key, {
    
    
			mode: CryptoJS.mode.ECB,
			padding: CryptoJS.pad.Pkcs7
		});
	    //返回
		console.log("解密后密文 ===> " + CryptoJS.enc.Utf8.stringify(decrypted).toString());
	    var result=CryptoJS.enc.Utf8.stringify(decrypted).toString();
		return JSON.parse(result);
	},
	
	/**
	 * 加密参数
	 * @param data
	 * @returns {string}
	 */
	getEncryptData: function(data) {
    
    
	    return JSON.stringify({
    
    "data":this.encryptFun(JSON.stringify(data))});
	},
	
	/**
	 * 获取32位随机码
	 * @returns {string}
	 */
	get32RandomNum: function(){
    
    
	    var chars = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
	    var nums="";
	    for(var i=0;i<32;i++){
    
    
	        var id = parseInt(Math.random()*61);
	        nums+=chars[id];
	    }
	    return nums;
	},
	
	/**
	 * 判断url是否在验证白名单中
	 * @param url
	 */
	verifyWhiteList: function(url) {
    
    
	    var whiteList = ["/login"];
	    for (var i = 0;i < whiteList.length;i++){
    
    
	        if(url.indexOf(whiteList[i]) != -1){
    
    
	            return true;
	        }
	    }
	    return false;
	},
	
	/**
	 * rsa加密
	 */
	rasEncrypt: function() {
    
    
	    var encrypt = new JSEncrypt();
	    encrypt.setPublicKey(this.publicKey);
	    // 这里输出加密后的字符串
	    console.log(encrypt.encrypt("你好asd1"));
	},
	
	/**
	  * aes加密
	  *@param word:需要加密的内容
	  *@returns {*} :返回加密的内容
	  */
	encrypt: function(word) {
    
    
	    varkey = CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
	    var srcs =CryptoJS.enc.Utf8.parse(word);
	    var encrypted =CryptoJS.AES.encrypt(srcs, key, {
    
     mode: CryptoJS.mode.ECB, padding:CryptoJS.pad.Pkcs7 });
	    return encrypted.toString();
	},
	
	/**
	  * aes解密
	  * @param word
	  * @returns {*}
	  */
	decrypt: function(word) {
    
    
	    var key =CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
	    var decrypt =CryptoJS.AES.decrypt(word, key, {
    
     mode: CryptoJS.mode.ECB, padding:CryptoJS.pad.Pkcs7 });
	    returnCryptoJS.enc.Utf8.stringify(decrypt).toString();
	}
}

escribir al final

Hay otro problema que necesita atención, es decir, el paquete de seguridad del entorno jre necesita modificar dos paquetes jar local_policy.jar y US_export_policy.jar para permitir el cifrado y descifrado de claves de 256 bits.

Después de pisar muchas trampas, finalmente lo logré y finalmente puse una captura de pantalla de la realización.
Por favor agregue una descripción de la imagen

Supongo que te gusta

Origin blog.csdn.net/qq_31236027/article/details/127176084
Recomendado
Clasificación