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

最后感謝網絡上我參考過的文章、博客。有的代碼是直接抄過來改的,參考太多無法一一列出,但要感謝他們無私精神。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM