前端常用加密算法

懒得起名字了1024 2024-07-10 16:33:02 阅读 91

一、常用加密方法

加密方法主要包括以下几种:

1、对称加密算法。这类算法使用相同的密钥进行加密和解密。常用的对称加密算法包括AES和DES。对称加密的优点是算法公开、计算量小、加密速度快、效率高。然而,它的安全性依赖于密钥的保密性,如果密钥泄露,加密信息就不安全。适用于本地数据加密、HTTPS通信和网络传输等场景。

2、非对称加密算法。这种算法使用不同的密钥进行加密和解密,公钥用于加密,私钥用于解密。常用的非对称加密算法有RSA。非对称加密可以保证数据传输的安全性,但算法复杂、计算量大、加密速度慢、效率低。适用于数字签名、身份认证等场景。

3、Hash算法。Hash算法将任意长度的数据转换成固定长度的哈希值,如MD5和SHA-1。Hash算法不可逆,常用于验证数据的完整性,例如文件校验和密码加密。它的优点是可以将任意长度的数据转换成固定长度的哈希值,计算速度快、效率高。缺点是无法通过哈希值恢复原始数据。

4、国密

npm地址:sm-crypto中国独有的一套加密算法,有SM1,SM2,SM3,SM4SM1 :类似于AES加密,对称加密,该算法不公开SM2 : 基于ECC,非对称加密SM3 : 类似于MD5或SHA256,用于文章摘要 SM4 :类似于AES加密,对称加密

5、混淆和编码。这是一种简单的数据转换方法,例如Base64编码,它可以增加数据的可读性难度,同时将数据转换为可打印的字符序列,有助于增加传输的便利性和安全性。

前端加密一般依赖第三方库,例如CryptoJS。

<code>npm i crypto-js --save

二、对称加密算法(DES、3DES、AES)

对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。优点:算法公开、计算量小、加密速度快、加密效率高。缺点:

  (1)交易双方都使用同样钥匙,安全性得不到保证。  

  (2)每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。

使用场景:本地数据加密、https通信、网络传输等

 2.1 AES

  AES:高级加密标准(Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。密钥:用来加密明文的密码。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取数据。

  2.1.1 纯文本加密

/ 加密

var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();

 

// 解密

var bytes  = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');

var originalText = bytes.toString(CryptoJS.enc.Utf8);

 

console.log(originalText); // 'my message'

   2.1.2 对象加密

var data = [{id: 1}, {id: 2}]

 

// 加密

var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString();

 

// 解密

var bytes  = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');

var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));

 

console.log(decryptedData); // [{id: 1}, {id: 2}]

 2.1.3 项目中使用

加密:

// 引入crypto-js库

import * as CryptoJS from 'crypto-js';

/*** @param {string} data - 需要加密的数据, 传过来前先进行 JSON.stringify(data);

* @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(aesKey);

let data = JSON.stringify(data);

const AESData = CryptoJS.AES.encrypt(data, key, {

    mode: CryptoJS.mode.ECB,

    padding: CryptoJS.pad.Pkcs7

});

// AESData 传给后台

AES解密(防篡改):

import * as CryptoJS from 'crypto-js';

import getSha256 from 'crypto-js/sha256';

function decryption(res) {

    /**

    * @param {object} res - 响应报文

    * 响应报文格式: {data: 'QukvMrekoCs7xnvqVDorjD4x6YMJx52HOqYM76YSDeOdwhGEGJvRp5aUZnR', mic: 'YrPA7gr8PgqvR7MKCueWX9LB88vkhadK0Ktg='}

    */

    let decryptedData = CryptoJS.AES.decrypt(res.data, key, {

        mode: CryptoJS.mode.ECB,

        padding: CryptoJS.pad.Pkcs7

    });

    var decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8); // 解密后明文

 

    // 对响应报文进行SH256加密

    const sha256Decode = getSha256(decryptedStr).toString();

    var encryptedHexStr = CryptoJS.enc.Hex.parse(sha256Decode);

    var sha256Result = CryptoJS.enc.Base64.stringify(encryptedHexStr);

    

    // 将响应报文前端与后端加密后的密文进行比对,比对一致则说明数据未被篡改

    if (sha256Result === res.mic) {

        return JSON.parse(decryptedStr)

    } else {

        Toast.info('解密失败')code>

    }

}

具体实现如下:

// 加密 secretKey为秘钥 message是需要加密后的字段

function encryptByAES(message, secretKey) {

// 将密钥转换为UTF-8编码的字节数组

const key = CryptoJS.enc.Utf8.parse(secretKey);

// 使用AES算法对消息进行加密

const encrypted = CryptoJS.AES.encrypt(message, key, {

mode: CryptoJS.mode.ECB, // 使用ECB模式

padding: CryptoJS.pad.Pkcs7 // 使用Pkcs7填充

});

// 将加密后的结果转换为字符串并返回

return encrypted.toString();

}

// 解密 secretKey为秘钥 ciphertext是加密后的字段

function decryptByAES(ciphertext, secretKey) {

// 将密钥转换为UTF-8编码的字节数组

const key = CryptoJS.enc.Utf8.parse(secretKey);

// 使用AES算法对密文进行解密

const decrypted = CryptoJS.AES.decrypt(ciphertext, key, {

mode: CryptoJS.mode.ECB, // 使用ECB模式

padding: CryptoJS.pad.Pkcs7 // 使用Pkcs7填充

});

// 将解密后的结果转换为UTF-8编码的字符串并返回

return decrypted.toString(CryptoJS.enc.Utf8);

}

 

三、非对称加密(RSA、DSA)

非对称加密算法,加密原理来自于大数的质因数分解。需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。前端用公钥加密,后端用私钥解密。优点:非对称加密与对称加密相比其安全性更好缺点:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。使用场景:https会话前期、CA数字证书、信息加密、登录认证等

3.1 RSA

RSA加密算法是非对称加密算法最常见的一种。RSA是1977年由Ron Rivest、Adi Shamir和Leonard Adleman一起提出的。RSA就是他们三人姓氏开头字母拼在一起组成的。

3.1.1 项目中使用

使用jsencrypt.js:就是一个基于rsa加解密的js库

const JSEncrypt = require("jsencrypt"); // 引入模块

const encrypt = new JSEncrypt.JSEncrypt(); // 实例化加密对象

encrypt.setPublicKey(公钥); // 设置公钥

const RSAData = encrypt.encrypt(aesKey); // 要加密的内容

// RSAData 传给后台

实现方式如下:

// 生成公钥和私钥

const keyPair = await window.crypto.subtle.generateKey(

{

name: "RSA-OAEP", // 使用RSA-OAEP算法

modulusLength: 2048, // 密钥长度为2048位

publicExponent: new Uint8Array([1, 0, 1]), // 公共指数为65537

hash: "SHA-256" // 哈希算法为SHA-256

},

true, // 生成可导出的密钥对

["encrypt", "decrypt"] // 可用于加密和解密操作

);

keyPair.then(function(result) {

// 处理生成的密钥对

console.log(result.publicKey); // 打印公钥

console.log(result.privateKey); // 打印私钥

}).catch(function(error) {

// 处理错误

console.error(error);

});

// 加密

async function encryptByRSA(message, publicKey) {

// 将消息编码为Uint8Array格式

const encodedMessage = new TextEncoder().encode(message);

// 使用Web Crypto API的encrypt()方法对消息进行加密

const encrypted = await window.crypto.subtle.encrypt(

{

name: "RSA-OAEP" // 加密算法为RSA-OAEP

},

publicKey, // 使用传入的公钥进行加密

encodedMessage // 要加密的消息

);

// 将加密后的数据转换为Base64编码的字符串

return window.btoa(String.fromCharCode(...new Uint8Array(encrypted)));

}

// 解密 使用RSA私钥对密文进行解密

async function decryptByRSA(ciphertext, privateKey) {

// 将Base64编码的密文解码为Uint8Array格式

const decodedCiphertext = Uint8Array.from(

atob(ciphertext),

c => c.charCodeAt(0)

);

// 使用Web Crypto API的decrypt()方法对密文进行解密

const decrypted = await window.crypto.subtle.decrypt(

{

name: "RSA-OAEP" // 解密算法为RSA-OAEP

},

privateKey, // 使用传入的私钥进行解密

decodedCiphertext // 要解密的密文

);

// 将解密后的数据转换为字符串

return new TextDecoder().decode(decrypted);

}

 

四、HASH算法(MD5、SHA-1、SHA-256)

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。将数据转化为固定长度的散列。优点:不可逆、易计算、特征化缺点:可能存在散列冲突使用场景:文件或字符串一致性校验、数字签名、鉴权协议

4.1 MD5

MD5是比较常见的Hash算法,对于MD5而言,有两个特性是很重要的,第一:明文数据经过散列以后的值是定长的;第二:是任意一段明文数据,经过散列以后,其结果必须永远是不变的。前者的意思是可能存在有两段明文散列以后得到相同的结果,后者的意思是如果我们散列特定的数据,得到的结果一定是相同的。

比如在登录时将密码进行 md5 加密再传输给服务器,服务器中的密码也是用 md5 加密后存储的,那么只要验证加密后的密文是否一致则可。

在项目中需要用到MD5加密时,可以使用开源的js库:JavaScript-MD5。

MD5是一种常用的密码散列函数,通常用于对一段数据产生唯一的“指纹”,以便于验证数据的完整性和一致性。在这个页面中,当用户点击“MD5加密”按钮时,会调用一个JavaScript函数fn2(),该函数使用了md5.js库文件中提供的md5()方法进行MD5加密操作。具体实现如下:

// MD5加密(不可逆的) 密码散列函数 需要引入https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js 这个js文件

var fn2=()=>{

// 加密

var str = '123'

var str2 = md5(str)

console.log('加密后',str2);

md5()方法接受一个字符串作为参数,返回该字符串的MD5编码结果。

 4.2 SHA256加密:防篡改

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

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

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

// 字符串简单加密

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

4.2.1 项目中使用

import getSha256 from 'crypto-js/sha256'; 

const sha256Encrypt = getSha256(data).toString(); // data - 需要加密的数据

const encryptedHexStr = CryptoJS.enc.Hex.parse(sha256Encrypt);

const mic = CryptoJS.enc.Base64.stringify(encryptedHexStr); // base64加密

// mic 传给后台

4.3  SHA-1加密

SHA-1是一种常用的密码散列函数,类似于MD5,但具有更高的安全性。在这个页面中,当用户点击“sha-1.js加密”按钮时,会调用一个JavaScript函数fn3(),该函数使用了sha1.js库文件中提供的sha1()方法进行SHA-1加密操作。具体实现如下:

// sha-1加密(不可逆) 是一种数加密算法 需要引入https://cdn.bootcss.com/js-sha1/0.6.0/sha1.js

var fn3=()=>{

// 加密

var str = '123'

var str2 = sha1(str)

console.log('加密后',str2);

}

 sha1()方法接受一个字符串作为参数,返回该字符串的SHA-1编码结果。

五、Base64编码

Base64,顾名思义,就是包括小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"一共64个字符的字符集,(另加一个“=”,实际是65个字符,至于为什么还会有一个“=",这个后面再说)。任何符号都可以转换成这个字符集中的字符,这个转换过程就叫做base64编码。Base64编码只是一种编码格式并不是加密算法,它可用于在HTTP环境下传递较长的标识信息。

特点:

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

现代浏览器都提供了Base64编码、解码方法,btoa() 和 atob()

<script>

       let str = 'ImGod';

       let str64 = window.btoa(str);

       console.log('转化后:'+str64);

       let jm = window.atob(str64);

       console.log('解码后:'+jm);

    </script>

六、编码解码加密

在Web开发中,经常需要对URL、Cookie等数据进行编码和解码操作,以便于传输和存储。在这个页面中,当用户点击“编码解码加密”按钮时,会调用一个JavaScript函数fn4(),该函数使用了escape()和unescape()方法进行编码和解码操作。具体实现如下:

<code>//编码解码  使用JS函数的escape()和unescape()

var fn4=()=>{

  // 加密

  var str = '中国123abc'

  let str1 = escape(str);

  console.log('加密后',str1);

  // 解密

  let str2 = unescape(str);

  console.log('解密后',str2);

}

escape()方法接受一个字符串作为参数,返回该字符串的URL编码结果。unescape()方法接受一个URL编码的字符串作为参数,返回该编码的原始字符串。

七、混淆加密

通过混淆代码或者加入噪音的方式来增强安全性,常见的方式有代码混淆、字符替换等。实现方式如下:

//参数为要加密的字段

 

// 字符串替换

function replaceChars(str) {

  return str.replace(/a/g, "@").replace(/e/g, "3").replace(/i/g, "1");

}

 

// 代码混淆

function obfuscateCode(code) {

  // 实现方式可以使用自己的加密算法,这里只是示例

  return code.split("").reverse().join("");



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。