zoukankan      html  css  js  c++  java
  • javascript JS CryptoJS DES加解密CBC模式与C#DES加解密相同互通

    我们只知道不同的语言解密要相互通用,就需要遵循相同的加密方式,然而在具体做技术预研的时候,就发现会遇到很多问题,网上找的资料也是比较片面,所以我踩了坑,并且把解决方案和相关资料源码提供出来,给需要的朋友一些参考。

    场景:网页客户端(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 ciphertext
                var 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);
            }
            //十六进制字符串转为base64
            function 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

    最后感谢网络上我参考过的文章、博客。有的代码是直接抄过来改的,参考太多无法一一列出,但要感谢他们无私精神。

  • 相关阅读:
    2016"百度之星"
    codeforces 55 div2 C.Title 模拟
    codeforces 98 div2 C.History 水题
    codeforces 97 div2 C.Replacement 水题
    codeforces 200 div2 C. Rational Resistance 思路题
    bzoj 2226 LCMSum 欧拉函数
    hdu 1163 九余数定理
    51nod 1225 余数的和 数学
    bzoj 2818 gcd 线性欧拉函数
    Codeforces Round #332 (Div. 2)D. Spongebob and Squares 数学
  • 原文地址:https://www.cnblogs.com/roak/p/14368775.html
Copyright © 2011-2022 走看看