前端加密体系

241 阅读10分钟

前端加密是指在前端(客户端)实施的一种数据加密措施,通常用于保护敏感信息在传输或存储过程中的安全性。 通常跟服务器的交互中,为保障数据传输的安全性,避免被人抓包篡改数据。前端加密可以分为两大类:传输加密本地加密

1.传输加密

  • SSL/TLS: 通过使用 HTTPS 协议,前端与服务器之间的通信可以通过 SSL/TLS 进行加密,确保数据在传输过程中不被窃听或篡改。
  • HTTPS: 在网站上启用 HTTPS 是一种常见的传输加密方式,可以通过在网站服务器上配置 SSL/TLS 证书实现。

2.本地加密:

2.1 简介

  • 加密算法: 在前端,可以使用一些加密算法对敏感数据进行加密,以确保即使在客户端存储,也不容易被恶意访问。常见的加密算法包括: 对称加密算法:AES、DES; 非对称加密算法:RSA 等。
  • 加密库: 使用现有的加密库,例如 CryptoJS,可以简化前端加密的实现过程,提供常用的加密算法和工具函数。
  • Hash 函数: 前端还常常使用哈希函数对密码等敏感信息进行加密存储,常见的哈希算法包括 MD5、SHA-256 等。

2.2 加密算法

目前常见的加密算法可以分成三类

  • 对称加密算法:AES、DES、3DES...
  • 非对称加密算法:RSA、ECC(移动设备用)...
  • Hash 算法:MD5、SHA-256
  • base64编码

1、对称加密算法

 对称加密算法 中,使用的密钥只有一个发送 和 接收 双方都使用这个密钥对数据进行 加密 和 解密。这就要求加密和解密方事先都必须知道加密的密钥。

image.png

特点

  • 优点:算法公开、计算量小、加密速度快、加密效率高。
  • 缺点:在数据传送前,发送方和接收方必须商定好密钥,然后双方保存好密钥。如果一方的密钥被泄露,那么加密信息也就不安全了
  • 使用场景:本地数据加密、https 通信、网络传输等

主要算法

  • DES算法
  • 3DES算法
  • TDEA算法
  • Blowfish算法
  • RC5算法
  • IDEA算法
  • AES算法

AES

AES:高级加密标准(Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。

AES加密算法采用分组密码体制,每个分组数据的长度为128位16个字节,密钥长度可以是128位16个字节、192位或256位,一共有四种加密模式:(ECB、CBC、CFB、OFB)

以  Vue 作为例子

1、要用 AES 算法加密,首先我们要引入 crypto-js ,crypto-js 是一个纯 javascript 写的加密算法类库 ,可以非常方便地在 javascript 进行 MD5SHA1SHA2SHA3RIPEMD-160 哈希散列,进行 AESDESRabbitRC4Triple DES 加解密,我们可以采用 npm install crypto-js --save 进行下载安装,也可以直接去 GitHub下载源码~

// 引入AES源码js
import CryptoJS from 'crypto-js'

/**
* @param {string} key - 加密使用的密钥 key
* CipherOption, 加密的一些选项:
* mode: 加密模式, 可取值(CBC, CFB, CTR, CTRGladman, OFB, ECB), 都在 CryptoJS.mode 对象下
* padding: 填充方式, 可取值(Pkcs7, AnsiX923, Iso10126, Iso97971, ZeroPadding, NoPadding), 都在     CryptoJS.pad 对象下
* iv: 偏移量, mode === ECB 时, 不需要 iv
* 返回的是一个加密对象
*/

const key = CryptoJS.enc.Utf8.parse( 'bGvnMc62sh5RV6zP' ) // 十六位十六进制数作为密钥
const iv = CryptoJS.enc.Utf8.parse( '1eZ43DLcYtV2xb3Y' ) // 十六位十六进制数作为密钥偏移量

// 解密方法
export function Decrypt(word) {
    const encryptedHexStr = CryptoJS.enc.Hex.parse(word)
    const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr)
    const decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })
    const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
    return decryptedStr.toString()
}

// 加密方法
export function Encrypt(word) {
    const srcs = CryptoJS.enc.Utf8.parse(word)
    const encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })
    return encrypted.ciphertext.toString().toUpperCase()
}

2、非对称加密算法

非对称加密算法是一种密钥的保密方法。 非对称加密算法需要两个密钥公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

非对称加密算法实现机密信息交换的基本过程是:甲方生成一对 密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方;甲方再用自己私钥对加密后的信息进行解密。甲方想要回复乙方时正好相反,使用乙方的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密。

非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要

非对称 密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

特点总结

  • 优点:非对称加密与对称加密相比其安全性更好
  • 缺点:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。
  • 使用场景:https 会话前期、CA 数字证书、信息加密、登录认证等

主要算法

  • RSA
  • Elgamal
  • 背包算法
  • Rabin
  • D-H
  • ECC(椭圆曲线加密算法)

RSA

  • 使用jsencrypt.js:就是一个基于rsa加解密的js库
  • RSA加密:非对称性加密(有一对公约和私钥,一个公钥对应一个私钥)
  • 加密原理来自于大数的质因数分解
  • 前端用公钥加密 后端用私钥解密
import JSEncrypt from 'jsencrypt'
const publicKey = 'bGvnMc62sh5RV6zP' //公钥 - 前端
/**
 * RSA加密
 * @param data 需要加密的内容
 * @param publicKey 
 * @returns {*}
 */
export function shortEncrypt(data, publicKey) {
    const jsencrypt = new JSEncrypt();
    jsencrypt.setPublicKey(publicKey);
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    return jsencrypt.encrypt(data)
}


const privateKey = 'xxxx' //私钥-后端
// RSA 解密
static decryptRSA(str: string) {
    const encryptor = new JSEncrypt() // 新建JSEncrypt对象
    encryptor.setPrivateKey(privateKey)//设置私钥
    const decrytStr = encryptor.decrypt(str)
    return decrytStr
}

3.Hash 算法

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。 简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

特点总结

  • 优点:不可逆、易计算、特征化
  • 缺点:可能存在散列冲突
  • 使用场景:文件或字符串一致性校验、数字签名、鉴权协议

MD5

MD5 长度固定,不论输入的内容有多少字节,最终输出结果都为 128 bit,即 16 字节。这也就解释了为什么 MD5 以及其它单向散列函数是不可逆的 —— 输出定长代表会有数据丢失。通常,我们可以用 16 进制字面值来表示它,每 4 bit 以 16 进制字面值显示,得到的是一个长度为 32 位的字符串。注意,MD5 等单向散列函数具有高度的离散性,意思是只要输入的明文不一样,得到的结果就完全不一样,哪怕是仅仅多了一个空格。

MD5 有下面几种使用场景:

  • 可以用来做密码的保护。比如可以不直接存储用户的密码,而是存储密码的 MD5 结果。但是现在一般认为用 MD5 来做加密是不太安全的,更多是利用 MD5 的高度离散性特点,用它来做数字签名、完整性校验,云盘秒传等;
  • 数字签名。我们可以在发布程序时同时发布其 MD5。这样,别人下载程序后自己计算一遍 MD5,一对比就知道程序是否被篡改过,比如植入了木马。
  • 完整性校验。比如前端向后端传输一段非常大的数据,为了防止网络传输过程中丢失数据,可以在前端生成一段数据的 MD5 一同传给后端,这样后端接收完数据后再计算一次 MD5,就知道数据是否完整了。

使用 crypto-js 进行 MD5 加密

import CryptoJS from 'crypto-js'

CryptoJS.MD5('xxxx').toString()

使用 js-md5 进行 MD5 加密

npm install --save js-md5
// 然后在页面中 引入
import md5 from 'js-md5';   
md5('holle') // bcecb35d0a12baad472fbe0392bcc043

SHA-256

sha256加密,类似于MD5加密,把一个字符串按照一个规则转换一下

该加密过程不可逆(即由A可加密成B,但无法由B解密出A)

文章摘要(防篡改):一般用SHA256加密或MD5加密进行文章摘要,即前端把需要传给后端的报文用SHA256加密后,把加密后的字符串传给后端,后端收到后,会先把解密后的明文再次进行SHA256加密,然后和前端传来的SHA256密文进行对比,如果一致,证明数据未被篡改

使用 crypto-js 进行 SHA256加密

// 字符串简单加密
const encryptData = CryptoJS.SHA256(‘待加密字符串’).toString();

4.base64编码

Base64 编码只是一种编码格式并不是加密算法,它可用于在 HTTP 环境下传递较长的标识信息。

特点

  • 可以将任意的二进制数据进行 Base64 编码
  • 数据加密之后,数据量会变大,变大 1/3 左右
  • 编码后有个非常显著的特点,末尾有个=号
  • 可进行反向解码
  • Base64 编码具有不可读性

使用 js-base64 进行 base64加解密

npm install --save js-base64
// 引入
let Base64 = require('js-base64').Base64
// 加密
Base64.encode('测试'); // 5bCP6aO85by+ 
Base64.encodeURI('测试'); // 5bCP6aO85by- 
// 解密
Base64.decode('5bCP6aO85by+'); // 测试
// note .decodeURI() is unnecessary since it accepts both flavors
Base64.decode('5bCP6aO85by-'); // 测试

使用window对象base64加解密

const enc = window.btoa('Hello World');
// SGVsbG8gV29ybGQ=
 
const str = window.atob(enc);
// Hello World