JS使用 cryptojs加密解密(对称加密库)的问题
作者:A黄俊辉A
js 加密解密可以使用 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 也有应的转换方法
通过显式调用toString方法并传递编码器,可以将WordArray(二进制数据)对象转换为其他格式。
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; }
分别运行代码看结果
对比没有问题
对称加密
cryptojs 也可以用来做对称加密,就拿 AES 对称加密来说
AES 对称加密是 需要有 密钥key 向量 iv
CryptoJS支持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 来验证一下
$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 都是一个类型的(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;
有了上面的基础, 我们下面来做一个例子
由后端php 使用 对称加密,加密一段文字, 然后返回给前端js , 同时要返回 加密的 iv, 然后前端 js 使用 cryptojs 来进行解密, 看是否正确 js AES 加解密
cryptjs.AES.encrypt 参数中的 key 和 iv 都是 以 wordsArray (二进制) 传入的,所以要明白 Utf8.parse 的方法
CryptoJS支持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 加密解密 cryptojs(对称加密库)的文章就介绍到这了,更多相关js 加密解密 cryptojs内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!