• 前端数据加解密:保护敏感信息的关键


    前言

    如今,数据安全和隐私保护变得至关重要。本文旨在引领大家探索前端数据加密与解密的基本概念,并介绍常用的加密算法,让大家深入了解数据加解密的世界,探究其背后的原理、最佳实践和常见应用场景。


    前端主流加密方式

    • 对称加密

      对称加密使用相同的密钥来加密和解密数据。常见的对称加密算法包括 AES(高级加密标准)、DES数据加密标准)和 3DES

    • 非对称加密

      非对称加密使用一对密钥,即公钥和私钥。公钥用于加密数据,私钥用于解密数据。算法示例:常见的非对称加密算法包括 RSADSASM2

    • 散列加密

      散列加密是用于创建数据的固定长度哈希值的过程。哈希值通常是不可逆的。算法示例:常见的散列算法包括 SHA-256MD5SHA-1

    • 混淆加密

      混淆加密是通过混淆代码或者加入噪音的方式来增强安全性,常见的方式有代码混淆、字符替换等。不是一种加密算法。

    总结

    • 对称加密使用相同的密钥进行加密和解密,适用于快速加密和解密大量数据。
    • 非对称加密使用一对密钥,公钥用于加密,私钥用于解密,适用于安全通信和数字签名。
    • 散列加密用于生成数据的固定长度哈希值,通常不可逆,用于数据完整性验证。
    • 混淆加密是一种用于隐藏代码或数据的技术,不是标准的加密方法,常用于软件保护。

    sm2 加密(非对称)

    • SM2 是一种非对称加密算法,使用公钥进行加密,私钥进行解密。
    • 椭圆曲线密码算法:SM2 基于椭圆曲线密码算法(Elliptic Curve CryptographyECC)实现。
    • 密钥长度:SM2 的密钥长度为 256 位(32字节)。
    • 安全性:SM2 具有较高的安全性,适用于数字签名、密钥交换、身份认证等场景。
    • 应用场景:SM2 广泛应用于数字证书、电子签名、安全通信等领域。

    miniprogram-sm-crypto

    miniprogram-sm-crypto 是专门为微信小程序环境开发的国密加密库。它被设计用于在微信小程序中进行加密操作。『官网地址』

    安装

    npm install miniprogram-sm-crypto --save
    
    • 1

    获取公私钥

    const sm2 = require("miniprogram-sm-crypto").sm2;
    
    const keyPair = sm2.generateKeyPairHex();
    
    const publicKey = keyPair.publicKey;
    const privateKey = keyPair.privateKey;
    
    console.log("公钥:", publicKey);
    console.log("私钥:", privateKey);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    打印结果

    在这里插入图片描述

    实例

    封装文件

    // 引入 miniprogram-sm-crypto 库中的 SM2 模块
    const sm2 = require("miniprogram-sm-crypto").sm2;
    
    // SM2加密函数
    function sm2Encrypt(msgString) {
      let msg = msgString;
      // 检查传入的消息是否为字符串,如果不是字符串则转换为 JSON 字符串
      if (typeof msgString !== "string") {
        msg = JSON.stringify(msgString);
      }
      let cipherMode = 1; // 加密模式固定为1
      let publicKey =
        "你的sm2公钥"; // SM2公钥
      // 使用 SM2 加密算法对消息进行加密
      let encryptData = sm2.doEncrypt(msg, publicKey, cipherMode); // 加密结果
      return encryptData;
    }
    
    // SM2解密函数
    function sm2Decrypt(msgString) {
      let msg = msgString;
      let cipherMode = 1; // 解密模式固定为1
      let privateKey = "你的sm2私钥"; // SM2私钥
      // 使用 SM2 解密算法对消息进行解密
      let decryptData = sm2.doDecrypt(msg, privateKey, cipherMode); // 解密结果
      return decryptData;
    }
    
    // 导出加密和解密函数
    module.exports = {
      sm2Encrypt,
      sm2Decrypt,
    };
    
    • 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

    使用文件

    const {sm2Encrypt,sm2Decrypt} = require('../../utils/index');//引入加密模块
    
    onLoad(){
    	// 加密数据
    	const originalData = {
    	  name: 'Alice',
    	  age: 30
    	};
    	const encryptedData = sm2Encrypt(originalData);
    	// 解密数据
    	const decryptedData = sm2Decrypt(encryptedData);
    	console.log('加密后的数据:', encryptedData);
    	console.log('解密后的数据:', JSON.parse(decryptedData));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    打印结果

    在这里插入图片描述


    sm-crypto

    sm-crypto 是适用于 Node.js 环境的国密加密库。它可以在 Node.js 中使用,但不适用于浏览器或微信小程序环境。『官网地址』

    安装

    npm install --save sm-crypto
    
    • 1

    获取公私钥

    const sm2 = require('sm-crypto').sm2;
    
    let keypair = sm2.generateKeyPairHex();
    let publicKey = keypair.publicKey; // 公钥
    let privateKey = keypair.privateKey; // 私钥
    
    console.log("公钥: ", publicKey);
    console.log("私钥: ", privateKey);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    打印结果

    在这里插入图片描述

    实例

    封装文件

    import smCrypto from 'sm-crypto';
    const sm2 = require('sm-crypto').sm2;
    
    // 生成密钥对
    let keypair = sm2.generateKeyPairHex();
    let publicKey = keypair.publicKey; // 公钥
    let privateKey = keypair.privateKey; // 私钥
    
    export default {
        // 使用公钥加密数据
        encrypt(data) {
            try {
                return smCrypto.sm2.doEncrypt(data, publicKey, 1);
            } catch (error) {
                console.error("Encryption error: " + error.message);
                return null;
            }
        },
    
        // 使用私钥解密数据
        decrypt(encryptedData) {
            try {
                return smCrypto.sm2.doDecrypt(encryptedData, privateKey, 1);
            } catch (error) {
                console.error("Decryption error: " + error.message);
                return null;
            }
        },
    
        // 使用私钥对数据进行签名
        sign(data) {
            try {
                return smCrypto.sm2.doSignature(data, privateKey);
            } catch (error) {
                console.error("Signature error: " + error.message);
                return null;
            }
        },
    
        // 使用公钥验证数据的签名
        verify(data, signature) {
            try {
                return smCrypto.sm2.doVerifySignature(data, signature, publicKey);
            } catch (error) {
                console.error("Signature verification error: " + error.message);
                return false;
            }
        },
    
        // 计算数据的哈希值
        hash(data) {
            try {
                return smCrypto.sm3(data);
            } catch (error) {
                console.error("Hash calculation error: " + error.message);
                return null;
            }
        },
    
        // 使用公钥加密 JSON 对象
        encryptObject(data) {
            try {
                const dataStr = JSON.stringify(data);
                const encryptedData = smCrypto.sm2.doEncrypt(dataStr, publicKey, 1);
                return encryptedData;
            } catch (error) {
                console.error("Object encryption error: " + error.message);
                return null;
            }
        },
    
        // 使用私钥解密加密的 JSON 对象
        decryptObject(encryptedData) {
            try {
                const decryptedDataStr = smCrypto.sm2.doDecrypt(encryptedData, privateKey, 1);
                const decryptedData = JSON.parse(decryptedDataStr);
                return decryptedData;
            } catch (error) {
                console.error("Object decryption error: " + error.message);
                return null;
            }
        }
    };
    
    • 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

    main.js 文件

    import smCrypto from './utils/smCrypto';
    Vue.prototype.$smCrypto = smCrypto;
    
    • 1
    • 2

    任意使用文件

    mounted() {
      // 加密对象
      const originalData = { name: "John", age: 30 };
      const encryptedData = this.$smCrypto.encryptObject(originalData);
      console.log("加密后的对象:", encryptedData);
      // 解密对象
      const decryptedData = this.$smCrypto.decryptObject(encryptedData);
      console.log("解密后的对象:", decryptedData);
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    打印结果

    在这里插入图片描述


    04补位问题

    SM2 算法中,对于加密的数据,需要进行 04 补位,以确保数据的长度符合 SM2 算法的要求。但上面我们使用的是 sm-crypto 库,该库已经封装了 04 补位的功能,所以就不需要手动进行 04 补位操作。当调用 smCrypto.sm2.doEncrypt 方法时,该方法会自动进行 04 补位操作。同样,当调用 smCrypto.sm2.doDecrypt 方法时,该方法也会自动去除 04 补位。


    sm4 加密(对称)

    • SM4是一种对称加密算法,使用相同的密钥进行加密和解密。
    • 块密码算法:SM4128 位(16字节)的分组大小进行加密,对每个分组进行独立的加密操作。
    • 密钥长度:SM4 的密钥长度为 128 位(16字节)。
    • 加密速度:SM4 具有较高的加密速度,适用于大量数据的加密和解密操作。
    • 应用场景:SM4 广泛应用于数据加密、网络通信、存储介质加密等领域。

    实例

    封装文件

    // 导入'miniprogram-sm-crypto'包中的sm4模块
    const sm4 = require('miniprogram-sm-crypto').sm4;
    
    // 以十六进制格式定义加密密钥
    const hexKey = "yuorpasword";
    
    // 使用TextEncoder将十六进制密钥转换为字节数组
    const keyBytes = new TextEncoder().encode(hexKey);
    
    // 使用SM4算法的加密函数
    function sm4Encrypt(text) {
      // 使用指定的参数使用SM4算法对文本进行加密
      const cipherText = sm4.encrypt(text, keyBytes);
      return cipherText;
    }
    
    // 使用SM4算法的解密函数
    function sm4Decrypt(text) {
      // 使用指定的参数使用SM4算法对文本进行解密
      const decryptedText = sm4.decrypt(text, keyBytes);
      return decryptedText;
    }
    
    // 导出加密和解密函数以供外部使用
    module.exports = {
      sm4Encrypt,
      sm4Decrypt
    };
    
    • 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

    使用文件

    const plaintext = "Hello, World!";
    const encryptedText = util.sm4Encrypt(plaintext);
    console.log("加密后的文本:", encryptedText);
    const decryptedText = util.sm4Decrypt(encryptedText);
    console.log("解密后的文本:", decryptedText);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    打印结果

    在这里插入图片描述

    注意

    此方法在微信开发者工具中使用没有任何问题,但是在移动设备上,可能会遇到 TextEncoder 未定义的问题。这是因为 TextEncoderWeb API 的一部分,而移动设备的环境可能不支持该 API。为了解决这个问题,需要使用一个 polyfill 来提供 TextEncoder 的功能。通过安装 text-encoding 库来提供 TextEncoderpolyfill

    npm install text-encoding
    
    • 1
    const { TextEncoder } = require('text-encoding');
    const sm4 = require('miniprogram-sm-crypto').sm4;
    
    const hexKey = "yuorpasword";
    const keyBytes = new TextEncoder().encode(hexKey);
    
    // 加密函数
    function sm4Encrypt(text) {
      const cipherText = sm4.encrypt(text, keyBytes);
      return cipherText;
    }
    
    // 解密函数
    function sm4Decrypt(text) {
      const decryptedText = sm4.decrypt(text, keyBytes);
      return decryptedText;
    }
    
    module.exports = {
      sm4Encrypt,
      sm4Decrypt
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    MD5 加密(不可逆)

    MD5 是一种单向哈希算法,即将任意长度的“消息”经过哈希运算,生成一个 128 位的“指纹”。使用 MD5 加密可以将原始的字符串转化为不可逆的密文,从而保证数据在传输中不被篡改,提高安全性。在前端中,我们可以通过 JS 库调用 md5 加密函数进行字符串加密,以保护用户信息。

    安装

    npm install --save js-md5
    
    • 1

    1. 常规使用

    <script>
    import md5 from "js-md5";
    export default {
      mounted() {
        const hashedText = md5("123456789");
        console.log("加密后:", hashedText);
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. 加盐使用

    为了增强加密的安全性,我们可以在原始字符串的基础上再加上一段随机的字符串,这个字符串就是“盐”。

    <script>
    import md5 from "js-md5";
    export default {
      mounted() {
        const hashedText = md5("123456789");
        console.log("加密后:", "hello world" + hashedText);
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3. 多次加密使用

    为了提高加密的强度,我们可以将加密结果再次进行 md5 加密,多次加密后的结果更加难以破解。

    <script>
    import md5 from "js-md5";
    export default {
      mounted() {
        const hashedText = md5(md5("123456789"));
        console.log("加密后:", hashedText);
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    md5 使用注意事项

    • 不要使用固定的密钥进行加密,否则容易被破解。应该采用随机密钥或者动态生成密钥进行加密。
    • 不要将加密算法公开,否则可能会被攻击者破解。应该将加密算法保密,仅在需要的场合使用。
    • 即使在前端进行加密,也应该在后端进行加密验证,以增强应用的安全性。
  • 相关阅读:
    Spring Boot系列之条件注解
    单源最短路径 -- Dijkstra
    Crack【QCSPCChart】:SPC Control Chart Tools for .Net
    实用调试技巧(2)
    分享艾思软件PHP(Thinkphp)后台自主框架测试试题
    1.JUL
    Windows本地安装Redis且设置服务自启
    如何通过 Java 代码隐藏 Word 文档中的指定段落
    Vue实现登录功能全套详解(含封装axios)
    C#多线程Thread、Task
  • 原文地址:https://blog.csdn.net/Shids_/article/details/134182731