javascript JS CryptoJS DES加解密CBC模式与C#DES加解密相同互通| Id | Title | DateAdded | SourceUrl | PostType | Body | BlogId | Description | DateUpdated | IsMarkdown | EntryName | CreatedTime | IsActive | AutoDesc | AccessPermission |
| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------| -------------|
| 14368775| javascript JS CryptoJS DES加解密CBC模式与C#DES加解密相同互通| 2021-02-03T18:39:00| | BlogPost|
我们只知道不同的语言解密要相互通用,就需要遵循相同的加密方式,然而在具体做技术预研的时候,就发现会遇到很多问题,网上找的资料也是比较片面,所以我踩了坑,并且把解决方案和相关资料源码提供出来,给需要的朋友一些参考。
场景:网页客户端(html)页面通过在发起请求时,将数据加密发送给C#编写的后端。C#后端接受到数据后需要进行解密,解密后得到明文,用明文进行业务操作,操作完成后,将结果加密返回。
因为C#后端使用的是DES CBC模式,所以前端JS也要使用相同的方式。否则加密解密结果不以言,就无法互通了。
使用技术:
1.前端javascript 使用CryptoJS进行加解密。
2.使用System.Security.Cryptography 命名空间下的相关类。
前端核心代码:
<!DOCTYPE html> <html> <head><meta charset="utf-8"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>JS_DES加解密CBC模式与C#DES加解密相同互通</title><script type="text/javascript">function CBCJiami() {var key = $("#desKey").val();var iv = $("#desIV").val();var msg = $("#source").val();var dd = encryptByDES(msg, key, iv);$("#JiaMiHou").val(dd);$("#target").val(toBase641(dd)); }function CBCJiemi() { var key = $("#desKey").val();var iv = $("#desIV").val();var msg = $("#JiaMiHou").val();var dd = decryptByDESModeEBC(msg, key, iv);$("#CBCJiemi").val(dd); }// DES CBC模式加密//加密内容、秘钥、向量function encryptByDES(message, key, iv) {var keyHex = CryptoJS.enc.Utf8.parse(key);var ivHex = CryptoJS.enc.Utf8.parse(iv);encrypted = CryptoJS.DES.encrypt(message, keyHex, {iv: ivHex,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});return encrypted.ciphertext.toString();}//DES CBC模式解密function decryptByDESModeEBC(ciphertext, key, iv) {//把私钥转换成UTF - 8编码的字符串var keyHex = CryptoJS.enc.Utf8.parse(key);var ivHex = CryptoJS.enc.Utf8.parse(iv);// direct decrypt ciphertextvar decrypted = CryptoJS.DES.decrypt({ciphertext: CryptoJS.enc.Hex.parse(ciphertext)}, keyHex, {iv: ivHex,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});return decrypted.toString(CryptoJS.enc.Utf8);}//十六进制字符串转为base64function toBase641(input) {var digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var base64_rep = "";var cnt = 0;var bit_arr = 0;var bit_num = 0;for (var n = 0; n < input.length; ++n) {if (input[n] >= 'A' && input[n] <= 'Z') {ascv = input.charCodeAt(n) - 55;}else if (input[n] >= 'a' && input[n] <= 'z') {ascv = input.charCodeAt(n) - 87;}else {ascv = input.charCodeAt(n) - 48;}bit_arr = (bit_arr << 4) | ascv;bit_num += 4;if (bit_num >= 6) {bit_num -= 6;base64_rep += digits[bit_arr >>> bit_num];bit_arr &= ~(-1 << bit_num);}}if (bit_num > 0) {bit_arr <<= 6 - bit_num;base64_rep += digits[bit_arr];}var padding = base64_rep.length % 4;if (padding > 0) {for (var n = 0; n < 4 - padding; ++n) {base64_rep += "=";}}return base64_rep;}</script><script src="jquery-3.4.1.min.js"></script><script src="CryptoJS v3.1.2/rollups/tripledes.js"></script><script src="CryptoJS v3.1.2/components/mode-ecb-min.js"></script><script src="Base64Helper.js"></script> </head> <body><div><fieldset><legend>DES CBC模式加密</legend>Key:<input type="text" id="desKey" value="z9j#$@4D"><br />IV:<input type="text" id="desIV" value="x34dg!df"><br />MSG:<input id="source" value="{}" /><br /><input type="button" onclick="CBCJiami();" name="" value="CBC加密" /><br />加密后:<input id="JiaMiHou" value="" /><br />转base64后:<input id="target" value="" /><br /><input type="button" onclick="CBCJiemi();" name="" value="CBC解密" /><br />解密后:<input id="CBCJiemi" value="" /></fieldset></div> </body> </html>
后端核心代码:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace WindowsFormsTest { public class DESHelper { /// <summary> /// DES加密字符串 /// </summary> /// <param name="encryptString">待加密的字符串</param> /// <param name="encryptKey">加密密钥,要求为8位</param> /// <returns>加密成功返回加密后的字符串,失败返回源串</returns> public static string EncryptDES(string encryptString, string encryptKey, string iv) { try { //将字符转换为UTF - 8编码的字节序列 byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8)); byte[] rgbIV = Encoding.UTF8.GetBytes(iv); byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString); //用指定的密钥和初始化向量创建CBC模式的DES加密标准 DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider(); dCSP.Mode = CipherMode.CBC; dCSP.Padding = PaddingMode.PKCS7; MemoryStream mStream = new MemoryStream(); CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write); cStream.Write(inputByteArray, 0, inputByteArray.Length); //写入内存流 cStream.FlushFinalBlock(); //将缓冲区中的数据写入内存流,并清除缓冲区 return Convert.ToBase64String(mStream.ToArray()); //将内存流转写入字节数组并转换为string字符 } catch { return encryptString; } } /// <summary> /// DES解密字符串 /// </summary> /// <param name="decryptString">待解密的字符串</param> /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param> /// <returns>解密成功返回解密后的字符串,失败返源串</returns> public static string DecryptDES(string decryptString, string decryptKey, string iv) { try { //将字符转换为UTF - 8编码的字节序列 byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 8)); byte[] rgbIV = Encoding.UTF8.GetBytes(iv); byte[] inputByteArray = Convert.FromBase64String(decryptString); //用指定的密钥和初始化向量使用CBC模式的DES解密标准解密 DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider(); dCSP.Mode = CipherMode.CBC; dCSP.Padding = PaddingMode.PKCS7; MemoryStream mStream = new MemoryStream(); CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write); cStream.Write(inputByteArray, 0, inputByteArray.Length); cStream.FlushFinalBlock(); return Encoding.UTF8.GetString(mStream.ToArray()); } catch { return decryptString; } } } } |
运行效果:
其中要注意一点:前端加密后有个转Base64的操作,加密解密后才会相同,原因是C#加密后的数据是转成base64的。
多说无益,直接上代码:
链接:https://pan.baidu.com/s/1FqpRa9LGuSfRZ9ZZ7Hau0g
提取码:hjvu
最后感谢网络上我参考过的文章、博客。有的代码是直接抄过来改的,参考太多无法一一列出,但要感谢他们无私精神。
| 648658| | 2024-04-29T20:50:00| false| | 2021-02-03T18:38:32.073| true| 我们只知道不同的语言解密要相互通用,就需要遵循相同的加密方式,然而在具体做技术预研的时候,就发现会遇到很多问题,网上找的资料也是比较片面,所以我踩了坑,并且把解决方案和相关资料源码提供出来,给需要的朋友一些参考。 场景:网页客户端(html)页面通过在发起请求时,将数据加密发送给C#编写的后端。C#| Anonymous|