JS使用cryptojs加密解密(对称加密库)的问题

作者:键盘侠时间:2026-10-31 07:59:49浏览:262

本文详解如何使用JS库crypto-js进行AES等对称加密,并解决前后端加解密互通问题。重点解析WordArray二进制数据与UTF8、Base64及Hex格式的转换方法,通过JS与PHP代码对比验证,确保密钥Key和向量IV在跨语言交互中的一致性,实现前端JS解密后端PHP加密数据的完整流程。

crypto-js库简介与安装

在JavaScript中实现加密解密功能,可以使用crypto-js库。这是一个专注于对称加密的工具库,支持AES和DES算法,但不包含RSA等非对称加密方法。安装该库非常简单,只需执行命令npm install crypto-js即可。它提供了MD5、SHA-1、SHA-256、Base64、AES和DES等多种算法的支持。

import crypto from "crypto-js"
	let md5binary = crypto.MD5("message");
	let hamcmd5binary =crypto.HmacMD5("message");
	//以上两个得到的是一个二进制的数据, 要可打印出业,就要使用 16进制模式或者base64方式
	//crypto 也有应的转换方法

若需将WordArray(即二进制数据对象)转换为其他格式,可以通过显式调用toString方法并指定相应的编码器来实现。

import crypto from "crypto-js"
	 let md5message = cryptjs.MD5(str); //这里得到的都是摘要的 二进制数据
  console.log(md5message);  //打印的二进制数据
  let hmacmd5message = cryptjs.HmacMD5(str,"haha"); //这里得到的都是摘要的 二进制数据
  console.log(hmacmd5message); //打印的二进制数据
  let sha1message = cryptjs.SHA1(str); //这里得到的都是摘要的 二进制数据
  console.log(sha1message); //打印的二进制数据
  let hamcsha1message = cryptjs.HmacSHA1(str,"haha");//这里得到的都是摘要的 二进制数据
  console.log(hamcsha1message); //打印的二进制数据
  let sha512message = cryptjs.SHA512(str); //这里得到的都是摘要的 二进制数据
  console.log(sha512message); //打印的二进制数据
  let hmacsha512message = cryptjs.HmacSHA512(str,"haha");//这里得到的都是摘要的 二进制数据
  console.log(hmacsha512message);//打印的二进制数据
  //上面打印的都是二进制的数据, 不利于传输, 所以, 我们要把它们变成 十六进制数据,或都base64的数据来进行传输
  //通过显式调用toString方法并传递编码器,可以将WordArray(二进制)对象转换为其他格式。
  //转成 base64 格式的方法
  let strbyhex = md5message.toString(cryptjs.enc.Hex);   //把二进制数据转成16进制
  console.log(strbyhex,"|||||||| js 十六进制结果");
  let strbybase64 = md5message.toString(cryptjs.enc.Base64);    //把二进制数据转成base64
  console.log(strbybase64,"||||||||js base64 结果")

为了验证转换的准确性,我们将最后几行代码中二进制转16进制和二进制转Base64的结果,与PHP生成的结果进行对比。

    public function testpass(){
        $md5binary =  hash("md5","message",true);  //第三个参数 为false  输出的是十六进制数据   如果是true  输出的是二进制数据
        //php 转二进制数据到 十六进制数据
        $md5hex = bin2hex($md5binary);
        //php 二进制数据到base64
        $md5base64 = base64_encode($md5binary);
        echo "php十六进制结果";
        echo $md5hex;
        echo "<br/>";
        echo "php base64结果";
        echo $md5base64;
        }

分别运行相关代码以查看输出结果。

crypto-js库简介与安装

crypto-js库简介与安装

经过对比,结果一致,没有问题。

JS与PHP数据格式转换验证

对称加密

crypto-js同样适用于对称加密场景。以AES对称加密为例,该过程需要密钥(key)和向量(iv)。Crypto-js支持AES-128、AES-192和AES-256三种变体,系统会根据传入密钥的大小自动选择对应的变体。若使用密码短语,库会自动生成256位密钥。当然,开发者也可以手动定义密钥key和iv向量。在此之前,我们需要先了解JS中Base64、16进制和UTF8之间的转换机制。

JS与PHP中UTF8字符串转Base64的方法。

let str = "这是一个测式";
  let words = cryptjs.enc.Utf8.parse(str);  //先把字符串转成words数型的二进制数组
  let base64words = cryptjs.enc.Base64.stringify(words);  //把二进制数组转成 base64字符串
  console.log(base64words);  //输出  6L+Z5piv5LiA5Liq5rWL5byP

我们可以使用PHP的base64_encode函数来验证JS端生成的Base64结果。

 $a = "这是一个测式";
 echo base64_encode($a);   //输出的结果  6L+Z5piv5LiA5Liq5rWL5byP

JS与PHP中将Base64字符转换回UTF8字符串的方法。

let baseStr = "6L+Z5piv5LiA5Liq5rWL5byP";
  let wordsbyBase64 = cryptjs.enc.Base64.parse(baseStr);  //把base64字符串转成 words数组(二进制数组)
  let res = cryptjs.enc.Utf8.stringify(wordsbyBase64);
  console.log(res);   //结果 这是一个测式

使用PHP的base64_decode函数进行验证。

 		$a = "6L+Z5piv5LiA5Liq5rWL5byP";
        echo base64_decode($a);  // 结果 这是一个测式

JS与PHP中将UTF8字符串转换为16进制数据的方法。

  let str1 = "这是一个字符串转成十六进制的测试";
  let words16bystr = cryptjs.enc.Utf8.parse(str1);
  let hexstr = cryptjs.enc.Hex.stringify(words16bystr);
  console.log(hexstr);  //得到结果 e8bf99e698afe4b880e4b8aae5ad97e7aca6e4b8b2e8bdace68890e58d81e585ade8bf9be588b6e79a84e6b58be8af95

使用PHP进行验证。

        $str = "这是一个字符串转成十六进制的测试";
        $strto16 = bin2hex($str);
        echo $strto16; //结果 e8bf99e698afe4b880e4b8aae5ad97e7aca6e4b8b2e8bdace68890e58d81e585ade8bf9be588b6e79a84e6b58be8af95

此处存在一个疑问:明明处理的是字符串,为什么PHP转换时使用了bin2hex函数?通常该函数用于二进制数据转Hex。随后,我使用PHP的gettype函数检查发现,无论是字符串还是二进制数据,在PHP中均被识别为string类型。这表明PHP底层将字符串视为二进制数据处理(此观点仅供参考,可能存在理解偏差)。

   $str = "这是一个字符串转成十六进制的测试";
        echo gettype($str);     // 显示 string
        echo "<br/>";
        //为了得到一个二进制的乱码一样的数据, 我们可以使用 hash函数得到
        //hash 第三个参数如果设为 true ,就可以得到一个二进制数据
        $binary = hash("md5","123456",true);
        echo $binary;  // 显示  � �9I�Y��V�W��>
        echo gettype($binary);  // 显示 string 但这个明显是一些乱码

从上述示例可见,$str和$binary在PHP中属于同一类型(string),底层均视为二进制数据。然而,为何一个显示正常而另一个显示乱码?原因在于$str包含的中文字符在字符码表中有对应的编码,而$binary是一串无序的二进制数,部分字节可能在中文码表中无对应字符,从而显示为乱码。由于部分数据会显示乱码,因此在传输时建议使用Base64编码,将二进制数据转换为Base64格式传输,以确保数据不丢失。

JS与PHP中将16进制数据转换回UTF8字符串的方法。

let str2 = "e8bf99e698afe4b880e4b8aae5ad97e7aca6e4b8b2e8bdace68890e58d81e585ade8bf9be588b6e79a84e6b58be8af95";
  let hextowords = cryptjs.enc.Hex.parse(str2);  //把十六进制转成 words (二进制数组)
  let str2back = cryptjs.enc.Utf8.stringify(hextowords);  //把二进制转成utf8
  console.log(str2back);

使用PHP进行验证。

       $hexstr = 'e8bf99e698afe4b880e4b8aae5ad97e7aca6e4b8b2e8bdace68890e58d81e585ade8bf9be588b6e79a84e6b58be8af95';
       $str = hex2bin($hexstr);
       echo $str;

JS与PHP AES加解密互通示例

基于上述基础知识,我们接下来进行一个综合示例。

由后端PHP使用对称加密对一段文字进行加密,返回给前端JS,同时返回加密所需的iv。随后,前端JS使用crypto-js进行解密,验证是否正确。这是一个JS AES加解密的示例。

crypto-js.AES.encrypt参数中的key和iv均以WordArray(二进制)形式传入,因此需要理解Utf8.parse方法的用法。Crypto-js支持AES-128、AES-192和AES-256,会根据传入密钥的大小自动选择变体。因此,在下例中,由于key1只有16位,系统会自动选用AES-128。

   //加密
  let secretStr = "这是一个测试AES";
  let key1 = cryptjs.enc.Utf8.parse("1234567812345678");  //十六位的
  let encrypted1 = cryptjs.AES.encrypt(secretStr,key1,{
    iv:cryptjs.enc.Utf8.parse("abcdefghijklmnop"),
    mode:cryptjs.mode.CBC,   //aes加密模式cbc  这个参数要前后端一至使用统一的加密模式
    padding:cryptjs.pad.Pkcs7  //使用 Pkcs7的方式填充   //这个php 加密时默认就是这种方式
  });
  console.log(encrypted1);  //加密的结果是一个对象
  console.log(encrypted1.key);  //对象中有 key , iv 等信息
  console.log(cryptjs.enc.Utf8.stringify(encrypted1.key))  //打印出key 的utf8字符串
  console.log(encrypted1.toString())    //使用toString 方法可以得到加密后的字符串
//加密的结果是:  YzXNRYB6/mmevnBiZPLRPu4Knk+qUVNyhUKonAB2Wjg=  这明显是一个base64格式的 
  //解密
  let result = cryptjs.AES.decrypt(encrypted1.toString(),key1,{
    iv:cryptjs.enc.Utf8.parse("abcdefghijklmnop"),
    mode:cryptjs.mode.CBC,
    padding:cryptjs.pad.Pkcs7
  })
  console.log(result);  //解密后得到的是一个 wordArray 二进制的对象
  console.log(cryptjs.enc.Utf8.stringify(result));    //把二进制对象转成 utf8的字符
  //解密的结果是 这是一个测试AES

PHP端的AES加解密实现。

        $str =  "这是一个测试AES";
        $algo = "AES-128-CBC";
        dump(openssl_cipher_iv_length($algo));  //这里我们可以先看一下 AES-128-CBC 的所需要的  iv 长度 结果是16,所以我们自定义了一个iv 是16个字符
        $key = "1234567812345678";
        $iv = "abcdefghijklmnop";
        $encrypt = openssl_encrypt($str,$algo,$key,OPENSSL_RAW_DATA,$iv);
        echo $encrypt;  //显示结果 YzXNRYB6/mmevnBiZPLRPu4Knk+qUVNyhUKonAB2Wjg=
        echo "<br/>";
        $decrypt = openssl_decrypt($encrypt,$algo,$key,OPENSSL_RAW_DATA,$iv);
        echo $decrypt;

从上述结果可以看出,JS和PHP的加密结果一致,说明前端JS与后端PHP可以实现加解密的互通。

至此,关于JS使用crypto-js进行对称加密解密的文章介绍完毕。如需了解更多JS加密解密相关内容,请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章