前端加密cryptojs与JSEncrypt使实例详解

目录
  • 单向散列函数
  • MD5
    • 简单介绍
    • 使用场景
    • 使用 crypto-js 进行 MD5 加密
    • CryptoJS.MD5()
    • algo
  • 对称加密算法 AES
    • 使用 crypto-js 进行 AES 加密
    • 解密
  • 非对称加密RSA
    • 使用 JSEncrypt 进行 RSA 加密
    • 使用 JSEncrypt 进行 RSA 解密
    • OpenSSL
    • 安装
    • 生成私钥
    • 生成公钥

单向散列函数

在网站项目中,有时我们需要对传给后端的数据,比如 token 等进行加密处理。本文是对几种常见的前端加密方法,以及如何使用开源的加密库 crypto-js、JSEncrypt 来实现它们的分享。

又称为消息摘要算法,是不可逆的加密算法,即对明文进行加密后,无法通过得到的密文还原回去得到明文。一般所谓的比如 MD5 破解,其实是不断的尝试用不同的明文进行加密,直到得到的加密结果一致。

常见的单项散列函数有 MD5、SHA1、SHA256、SHA512 ,以及它们之前加上 Hmac(Keyed-hash message authentication codes) 后的 HmacMD5、HmacSHA1 等。下面以 MD5 为例重点介绍,其它几种则可以举一反三,不多赘述:

MD5

简单介绍

MD5 长度固定,不论输入的内容有多少字节,最终输出结果都为 128 bit,即 16 字节。这也就解释了为什么 MD5 以及其它单向散列函数是不可逆的 —— 输出定长代表会有数据丢失。

通常,我们可以用 16 进制字面值来表示它,每 4 bit 以 16 进制字面值显示,得到的是一个长度为 32 位的字符串。注意,MD5 等单向散列函数具有高度的离散性,意思是只要输入的明文不一样,得到的结果就完全不一样,哪怕是仅仅多了一个空格。

使用场景

MD5 有下面几种使用场景:

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

使用 crypto-js 进行 MD5 加密

为了方便,我采用了在普通 html 页面直接引入 cdn 的方式来引入 crypto-js。

<script src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

引入后,我们就能得到 CryptoJS 这个对象,它包含了很多方法,打印结果如下图:

其中就定义了 MD5 方法和 algo 对象,借助它们,可以分别得到输入数据的 MD5 结果:

CryptoJS.MD5()

CryptoJS.MD5('2022JueJin').toString()

结果为 84231025843afb62d818bf4f21612051。“2022JueJin” 就是我们需要加密的明文数据,得到的结果需要转为字符串输出,不然会是一个对象,而不是 16 进制字面值显示的 32 位字符串(由 0 - 9 和 a - f 组成)。

  • WordArray

传入CryptoJS.MD5() 的参数除了字符串外,还可以是 CryptoJS 定义的一种叫做 WordArray 的数据类型。

const wordArray = CryptoJS.enc.Utf8.parse('2022JueJin')
CryptoJS.MD5(wordArray).toString()

上面这段代码将 utf8 字符串先转成了 WordArray 对象,再将其传给 CryptoJS.MD5(),最终得到的结果如果打印输出的话也是 84231025843afb62d818bf4f21612051。

enc 可以看成是 Encode(编码) 的缩写。Utf8 还能换成 Latin1HexBase64 等。如果想将一个 WordArray 对象转换回 utf8 字符,可以执行

CryptoJS.enc.Utf8.stringify(wordArray)

一般情况下,消息摘要算法得到的结果都是以 16 进制字面值表示,如果想要得到 Base64,可以将加密结果通过 CryptoJS.enc.Base64.stringify() 转换:

const base64 = CryptoJS.enc.Base64.stringify(CryptoJS.MD5('2022JueJin'))
console.log(base64) // hCMQJYQ6+2LYGL9PIWEgUQ==

algo

如果需要生成 MD5 的数据是个大文件,一般我们可以把大文件分为多段。采用下面的方式,先使用 CryptoJS.algo.MD5.create()创建一个对象,命名为 hasher。然后将数据一段段的传入 hasher.update() 处理:

const hasher = CryptoJS.algo.MD5.create()
hasher.update('2022')
hasher.update('JueJin')
const hash = hasher.finalize()
console.log(hash.toString())

最后调用 hasher.finalize() 表示传输完成,finalize() 里也可以传入数据。打印得到的结果也是 84231025843afb62d818bf4f21612051。如果想清除之前的 update,可以调用 hasher.reset()

上面介绍的单向散列函数严格来说并不是加密算法,更多是用于签名。项目中需要进行加密的时候,最好采用下面介绍的加密算法。它们的加密和解密过程是可逆的,分为对称加密和非对称加密。

对称加密算法 AES

所谓对称,指的是加密和解密使用的是相同的秘钥,常见的有 DES、3DES 、RC4、RC5、RC6 和 AES。下面以我在公司最近的项目中使用的 AES 为重点进行介绍。

英文全称为 Advanced Encryption Standard,即高级加密标准的意思。它的推出,用于取代已经被证明不安全的 DES 算法。AES 属于分组加密算法,因为它会把传入的明文数据以 128 bit 为一组分别处理。其秘钥长度则可以是 128、192 和 256 bit。AES 或者说对称加密算法的优点是速度快,缺点就是不安全,因为网站上的代码和秘钥都是明文,别人只要得到了加密结果再结合秘钥就能得到加密的数据了。

使用 crypto-js 进行 AES 加密

加密

我们将 “JueJin2022” 通过 AES 加密,得到的将是一个对象,我们需要通过 toString() 将其转成字符串输出,最终得到的是一个以 base64 编码的 “5yOOaUK1NSxVcRc8TA1fZw==”,代码如下:

const message = CryptoJS.enc.Utf8.parse('JueJin2022')
const secretPassphrase = CryptoJS.enc.Utf8.parse('0123456789asdfgh')
const iv = CryptoJS.enc.Utf8.parse('0123456789asdfgh')
const encrypted = CryptoJS.AES.encrypt(message, secretPassphrase, {
  mode: CryptoJS.mode.CBC,
  paddding: CryptoJS.pad.Pkcs7,
  iv
}).toString()
console.log(encrypted)

CryptoJS.AES.encrypt() 可以传入 3 个参数: 第 1 个为需要加密的明文; 第 2 个是秘钥,长度可以是 128、192 或 256 bit; 第 3 个为一个配置对象,可以添加一些配置。常见的配置属性有:

  • mode:加密模式。默认为 CBC,还支持且常用的是 ECB。CBC 模式需要偏移向量 iv,而 ECB 不需要。
  • paddding:填充方式。默认为 Pkcs7;
  • iv:偏移向量 ;

注意,明文、秘钥和偏移向量一般先用诸如 CryptoJS.enc.Utf8.parse() 转成 WordArray 对象再传入,这样做得到结果与不转换直接传入是不一样的。

解密

解密的写法和加密差不多,只是把 encrypt 方法名改为 decrypt,然后传入的第 1 个参数由明文替换为密文,最后将之前转换明文的方式传入 toString() 即可:

const secretPassphrase = CryptoJS.enc.Utf8.parse('0123456789asdfgh')
const iv = CryptoJS.enc.Utf8.parse('0123456789asdfgh')
const decrypted = CryptoJS.AES.decrypt(
  '5yOOaUK1NSxVcRc8TA1fZw==',
  secretPassphrase,
  {
    mode: CryptoJS.mode.CBC,
    paddding: CryptoJS.pad.Pkcs7,
    iv: '0123456789asdfgh'
  }
).toString(CryptoJS.enc.Utf8)
console.log(decrypted) // JueJin2022

注:如果之前在加密时没有将明文进行 parse 而是直接传入的,那么在解密时,传入 toString() 的解析方式就是写默认的 CryptoJS.enc.Utf8

非对称加密RSA

所谓的非对称,即加密和解密用的不是同一个秘钥。比如用公钥加密,就要用私钥解密。非对称加密的安全性是要好于对称加密的,但是性能就比较差了。

非对称加密算法中常用的就是 RSA 了。它是由在 MIT 工作的 3 个人于 1977 年提出,RSA 这个名字的由来便是取自他们 3 人的姓氏首字母。我们在访问 github 等远程 git 仓库时,如果是使用 SSH 协议,需要生成一对公私秘钥,就可以使用 RSA 算法。

使用 JSEncrypt 进行 RSA 加密

我们依旧是采用 cdn 方式直接在页面中引入 JSEncrypt 库:

<script src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.2.1/jsencrypt.min.js"></script>

使用的代码非常简单。首先需要 new 一个实例对象出来,然后将通过 openssl 生成的公钥传给实例对象的 setKey 方法,之后只需要把要加密的明文传给实例的 encrypt() 进行加密即可:

const crypt = new JSEncrypt()
crypt.setKey('openssl 生成的公钥')
const text = 'JueJin2022'
const enc = crypt.encrypt(text)
console.log(enc)

生成的密文是一段 base64 格式的 1024 位 RSA 私钥。

使用 JSEncrypt 进行 RSA 解密

解密就是把私钥传给实例的 setKey(),之后把密文传给 decrypt() 进行解密即可:

const crypt = new JSEncrypt()
crypt.setKey('openssl 生成的私钥')
const enc = 密文
const dec = crypt.decrypt(enc)
console.log(dec)

注意,setKey 有 2 个别名: 如果传入的是私钥,可以用 setPrivateKey() 替换 setKey(); 如果传入的是公钥,可以用 setPublicKey() 替换 setKey()

OpenSSL

从上面的内容可知,JSEncrypt 的加解密过程需要用到 OpenSSL 来生成秘钥,OpenSSL 是一个开源的软件,它是对 SSL 协议的实现。能够用于生成证书、证书签名、生成秘钥和加解密等。比如我公司最近的项目有个需求是要在本地开发时,localhost 使用 https 协议,就有用到 openssl。

安装

可以去 slproweb.com/products/Wi… 选择对应版本安装:

然后在环境变量中添加配置,例如我把 openssl 安装在了 D:\OpenSSL-Win64,就将 D:\OpenSSL-Win64\bin 添加到 Path 中:

生成私钥

我们可以在想要保存秘钥的文件夹启动命令行工具,并输入以下命令生成秘钥文件:

openssl genrsa -out rsa_1024_priv.pem 1024
  • genrsa: 生成 RSA 私有密钥;
  • -out:生成的密钥文件,后面配置的是我们生成的密钥文件的名字,可从中提取公钥;
  • 1024:生成的秘钥长度为 1024 bit;

生成的秘钥文件如下:

可以通过 cat rsa_1024_priv.pem 查看秘钥内容,然后复制粘贴给上面的 crypt.setKey()

注意:秘钥必须写成一行以 -----BEGIN PRIVATE KEY----- 开头,以 -----END PRIVATE KEY----- 结尾。像下面这样:

crypt.setKey(  '-----BEGIN PRIVATE KEY-----MIICdFCQBj...中间省略...D3t4NbK1bqMA=-----END PRIVATE KEY-----')

生成公钥

生成上面的私钥对应的公钥的命令为

openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem
  • rsa:处理 RSA 密钥的格式转换等问题;
  • -pubout:指定输出文件是公钥;
  • -in:输入文件,也就是我们上面生成的私钥文件;
  • -out:输出文件,也就是是我们要生成的公钥文件;

查看同样是使用 cat 命令。

以上就是前端加密cryptojs与JSEncrypt使实例详解的详细内容,更多关于前端加密cryptojs JSEncrypt的资料请关注我们其它相关文章!

(0)

相关推荐

  • JS前端加密算法示例

    本文实例讲述了JS前端加密算法.分享给大家供大家参考,具体如下: 解密操作对服务器性能颇有消耗.寻思着能不能在前端完成.于是找到了crypto-js. crypto-js的github地址: https://github.com/brix/crypto-js crypto-js支持各类主流算法.弄个简单点的DES加密. function decryptByDES(ciphertext, key) { var keyHex = CryptoJS.enc.Utf8.parse(key); var d

  • Vue中使用jsencrypt进行RSA非对称加密的操作方法

    在线生成生成RSA密钥对:http://web.chacuo.net/netrsakeypair 下载jsencrypt cnpm i -S jsencrypt 引入 import { JSEncrypt } from "jsencrypt"; 基本使用 注意:要加密的数据必须是字符串!! 提示:给公钥直接用双引号“”引起来后可能要手动删掉每行末尾多余的空格,有点麻烦,此时可以直接用``来引.只是这样可能排版显示不太好看 testRSA() { let publicKey = &quo

  • VueJs里利用CryptoJs实现加密及解密的方法示例

    第一步 安装 安装crypto-js 第二步 创建 在js文件目录下创建一个js文件secret /** * 对页面上输入的密码进行加密传输给后台进行验证,对返回的数据进行解密,在页面展示 */ let CryptoJS = require('crypto-js'); // 引入AES源码js export default { /* * 对密码进行加密,传输给后台进行验证 * @param {String} word 需要加密的密码 * @param {String} keyStr 对密码加密的

  • Js参数RSA加密传输之jsencrypt.js的使用

    注意几点: 1.参数传递的+号处理,在传输时会把+变成空格,不处理后端就报错了. 1.前端代码 <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Login</title> <script src="~/Scripts/jquery-1.10.2.m

  • RSA实现JS前端加密与PHP后端解密功能示例

    本文实例讲述了RSA实现JS前端加密与PHP后端解密功能.分享给大家供大家参考,具体如下: web前端,用户注册与登录,不能直接以明文形式提交用户密码,容易被截获,这时就引入RSA. 前端加密 需引入4个JS扩展文件,jsbn.js.prng4.js.rng.js和rsa.js. <html> <head> <title>RSA Login Test</title> <meta charset="utf-8"> <scr

  • JavaScript实现的前端AES加密解密功能【基于CryptoJS】

    本文实例讲述了JavaScript实现的前端AES加密解密功能.分享给大家供大家参考,具体如下: js前端AES加密 最近由于项目需求做了一次MITM,突然即使发现使用HTTPS,也不能保证数据传输过程中的安全性. 通过中间人攻击,可以直接获取到Http协议的所有内容. 于是开始尝试做一些简单的加密,在一定程度上保证安全性. 本次采用AES加密数据,所以客户端和服务端使用的相同秘钥.(仅作为演示,正式环境推荐使用RSA) 首先准备一份明文密码和加密使用的KEY var source = "ABC

  • 前端加密cryptojs与JSEncrypt使实例详解

    目录 单向散列函数 MD5 简单介绍 使用场景 使用 crypto-js 进行 MD5 加密 CryptoJS.MD5() algo 对称加密算法 AES 使用 crypto-js 进行 AES 加密 解密 非对称加密RSA 使用 JSEncrypt 进行 RSA 加密 使用 JSEncrypt 进行 RSA 解密 OpenSSL 安装 生成私钥 生成公钥 单向散列函数 在网站项目中,有时我们需要对传给后端的数据,比如 token 等进行加密处理.本文是对几种常见的前端加密方法,以及如何使用开源

  • JAVA 中解密RSA算法JS加密实例详解

    JAVA 中解密RSA算法JS加密实例详解 有这样一个需求,前端登录的用户名密码,密码必需加密,但不可使用MD5,因为后台要检测密码的复杂度,那么在保证安全的前提下将密码传到后台呢,答案就是使用RSA非对称加密算法解决 . java代码 需要依赖 commons-codec 包 RSACoder.Java import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import java.security.

  • MySQL加密和解密实例详解

    MySQL加密和解密实例详解 数据加密.解密在安全领域非常重要.对程序员而言,在数据库中以密文方式存储用户密码对入侵者剽窃用户隐私意义重大. 有多种前端加密算法可用于数据加密.解密,下面我向您推荐一种简单的数据库级别的数据加密.解密解决方案.以MySQL数据库为例,它内建了相应的加密函数(AES_ENCRYPT() )和解密函数(AES_DECRYPT()). 在建表的时候,要注意字段的类型.如下图所示: 在表中插入加密数据 上面的插入语句有三个字段,"用户名"."密码&qu

  • Java使用AES加密和解密的实例详解

    Java使用AES加密和解密的实例详解 前言: AES的基本要求是,采用对称分组密码体制,密钥长度的最少支持为128.192.256,分组长度128位,算法应易于各种硬件和软件实现.1998年NIST开始AES第一轮分析.测试和征集,共产生了15个候选算法.1999年3月完成了第二轮AES2的分析.测试.2000年10月2日美国政府正式宣布选中比利时密码学家Joan Daemen 和 Vincent Rijmen 提出的一种密码算法RIJNDAEL 作为 AES. 在应用方面,尽管DES在安全上

  • swift MD5加密源码的实例详解

    swift MD5加密源码的实例详解 因为MD5加密是不可逆的,所以一般只有MD5加密的算法,而没有MD5解密的算法. 创建一个Sting+MD5.Swift字符串分类文件(同时此处需要创建一个bridge.h桥接文件,引入这个头文件 #import <CommonCrypto/CommonDigest.h>,md5加密方法需要使用的文件) 1.bridge.h桥接文件如下: #ifndef bridge_h #define bridge_h #import <CommonCrypto/

  • php 生成加密公钥加密私钥实例详解

    php 生成加密公钥加密私钥实例详解 生成公钥私钥     win下必须要openssl.cof支持   liunx一般已自带安装  $config = array( //"digest_alg" => "sha512", "private_key_bits" => 512, //字节数 512 1024 2048 4096 等 "private_key_type" => OPENSSL_KEYTYPE_RS

  • python实现rsa加密实例详解

    python实现rsa加密实例详解 一 代码 import rsa key = rsa.newkeys(3000)#生成随机秘钥 privateKey = key[1]#私钥 publicKey = key[0]#公钥 message ='sanxi Now is better than never.' print('Before encrypted:',message) message = message.encode() cryptedMessage = rsa.encrypt(messag

  • Python 加密的实例详解

     Python 加密的实例详解 hashlib支持md5,sha1,sha256,sha384,sha512,用法和md5一样 import hashlib #hashlib支持md5,sha1,sha256,sha384,sha512,用法和md5一样 m = hashlib.md5() #创建加密对象 m.update(b'password') #对输入内容进行加密, m.digest() #获取二进制加密密文 m.hexdigest() #获取十六进制加密密文 '''''python3默认

  • HTML中使背景图片自适应浏览器大小实例详解

    HTML中使背景图片自适应浏览器大小实例详解 解决办法: 1.图片不够大,又background属性不能拉伸图片: 2.只能用个div,把其z-index值设为负,并使这个div大小为整个body大小,在div里用<img> : 3.body的background属性去掉,要不然会被遮住. <html> <body> <div id="Layer1" style="position:absolute; left:0px; top:0p

  • 微信小程序 sha1 实现密码加密实例详解

    微信小程序 sha1 实现密码加密实例详解 在utils中的util.js 文件中增加 函数 实现 字符串转换为16进制加密后的字符串 function encodeUTF8(s) { var i, r = [], c, x; for (i = 0; i < s.length; i++) if ((c = s.charCodeAt(i)) < 0x80) r.push(c); else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x

随机推荐