[转]AES.js加密解密与C#的相互转换(及MD5值计算)

[转]AES.js加密解密与C#的相互转换


原文链接:AES.js加密解密与C#的相互转换
注:删除了原文最后部分的调试截图,增加了扩展部分的内容(自己使用过程中遇到的问题)。

AES简介#

AES, Advanced Encryption Standard,其实是一套标准:FIPS 197,而我们所说的AES算法其实是Rijndael算法。

NIST (National INstitute of Standards and Technology) 在1997年9月12日公开征集更高效更安全的替代DES加密算法,第一轮共有15种算法入选,其中5种算法入围了决赛,分别是MARS,RC6,Rijndael,Serpent和Twofish。又经过3年的验证、评测及公众讨论之后Rijndael算法最终入选。
image

具体实现#

1.服务端加密/解密#

public class DecryptStringAES
{
      /// <summary>  
      /// AES加密算法  
      /// </summary>  
      /// <param name="input">明文字符串</param>  
      /// <returns>字符串</returns>  
      public static string EncryptByAES(string input)
      {
     	  if (string.IsNullOrWhiteSpace(input))
          {
              return input;
          }
          using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
          {
              rijndaelManaged.Mode = CipherMode.CBC;
              rijndaelManaged.Padding = PaddingMode.PKCS7;
              rijndaelManaged.FeedbackSize = 128;

              rijndaelManaged.Key = Encoding.UTF8.GetBytes(Decrypt.Key);
              rijndaelManaged.IV = Encoding.UTF8.GetBytes(Decrypt.AES_IV);

              ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV);
              using (MemoryStream msEncrypt = new MemoryStream())
              {
                  using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                  {
                      using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                      {
                          swEncrypt.Write(input);
                      }
                      byte[] bytes = msEncrypt.ToArray();
                      return Convert.ToBase64String(bytes);
                  }
              }
          }
      }

      /// <summary>  
      /// AES解密  
      /// </summary>  
      /// <param name="input">密文字节数组</param>  
      /// <returns>返回解密后的字符串</returns>  
      public static string DecryptByAES(string input)
      {
   		  if (string.IsNullOrWhiteSpace(input))
          {
              return input;
          }
          var buffer = Convert.FromBase64String(input);
          using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
          {
              rijndaelManaged.Mode = CipherMode.CBC;
              rijndaelManaged.Padding = PaddingMode.PKCS7;
              rijndaelManaged.FeedbackSize = 128;

              rijndaelManaged.Key = Encoding.UTF8.GetBytes(Decrypt.Key);
              rijndaelManaged.IV = Encoding.UTF8.GetBytes(Decrypt.AES_IV);

              ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV);
              using (MemoryStream msEncrypt = new MemoryStream(buffer))
              {
                  using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read))
                  {
                      using (StreamReader srEncrypt = new StreamReader(csEncrypt))
                      {
                          return srEncrypt.ReadToEnd();
                      }
                  }
              }
          }
      }        
  }

2.客户端(JS)#

定义Key/IV:

const key = CryptoJS.enc.Utf8.parse("1234567890000000");
const iv = CryptoJS.enc.Utf8.parse("1234567890000000");

加密方法:

//**************************************************************
//*字符串/对象加密
//*   0:需要解密的字符串或对象
//****************************************************************/
function Encrypt(o) {
   if (typeof (o) === "string") {
        if (o) {
            var srcs = CryptoJS.enc.Utf8.parse(o);
            return CryptoJS.AES.encrypt(srcs, key, {
                keySize: 128 / 8,
                iv: iv,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            }).toString();
        }
    }
    else if (typeof (o) === "object") {
        for (var _o in o) {
            if (o[_o]) {
                var srcs = CryptoJS.enc.Utf8.parse(o[_o]);
                o[_o] = CryptoJS.AES.encrypt(srcs, key, {
                    keySize: 128 / 8,
                    iv: iv,
                    mode: CryptoJS.mode.CBC,
                    padding: CryptoJS.pad.Pkcs7
                }).toString();
            }
        };

    }
    return o;
}

解密方法:

//**************************************************************
//*字符串解密
//*   str:需要解密的字符串
//****************************************************************/
function Decrypt(str) {
   var decrypt = CryptoJS.AES.decrypt(str, key, {
        keySize: 128 / 8,
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr;
}

注:客户端和服务端的KEY/IV必须保持一致。

扩展部分#

1.前端计算MD5值#

在普通 html 页面直接引入 cdn 的方式来引入 crypto-js:

<script src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

以下是使用CryptoJS.MD5生成字符串的MD5值,并将其转换成小写字符串、大写字符串和base64编码的示例:

  • 将MD5值转换成小写字符串:
var hash = CryptoJS.MD5('hello');
console.log(hash.toString(CryptoJS.enc.Hex)); // 输出:5d41402abc4b2a76b9719d911017c592
console.log(hash.toString(CryptoJS.enc.Latin1)); // 输出:]A@\¬K*h¹qÚ|Y
console.log(hash.toString(CryptoJS.enc.Utf8)); // 输出:]A@\¬K*h¹qÚ|Y
console.log(hash.toString(CryptoJS.enc.Base64)); // 输出:XUFBArxLK2y5ccmRGAF8Wg==
console.log(hash.toString()); // 输出:5d41402abc4b2a76b9719d911017c592
  • 将MD5值转换成大写字符串:
var hash = CryptoJS.MD5('hello');
console.log(hash.toString(CryptoJS.enc.Hex).toUpperCase()); // 输出:5D41402ABC4B2A76B9719D911017C592
console.log(hash.toString(CryptoJS.enc.Latin1).toUpperCase()); // 输出:]A@\¬K*H¹QÚ|Y
console.log(hash.toString(CryptoJS.enc.Utf8).toUpperCase()); // 输出:]A@\¬K*H¹QÚ|Y
console.log(hash.toString(CryptoJS.enc.Base64).toUpperCase()); // 输出:XUFBARXLK2Y5CCMRGAF8WQ==
console.log(hash.toString().toUpperCase()); // 输出:5D41402ABC4B2A76B9719D911017C592
  • 将MD5值转换成base64编码:
var hash = CryptoJS.MD5('hello');
console.log(hash.toString(CryptoJS.enc.Base64)); // 输出:XUFBArxLK2y5ccmRGAF8Wg==

2.CryptoJS默认编码格式#

CryptoJS默认使用UTF-8编码格式处理字符串,在使用MD5算法加密字符串时,可以直接传入原始字符串,CryptoJS会自动将其转换成UTF-8编码的字节数组。

如果需要使用其他编码格式,可以在调用加密函数之前,手动将字符串转换成指定编码的字节数组,然后再传入加密函数进行处理。例如,将字符串转换成Latin1编码的字节数组:

var str = 'hello';
var latin1 = CryptoJS.enc.Latin1.parse(str);
var hash = CryptoJS.MD5(latin1);
console.log(hash.toString()); // 输出:13d2eaa6f3d80ca58f37c2597efec15f

注:在使用不同编码格式时,输出结果可能会不同,需要根据具体场景选择合适的编码方式。

参考资料#

posted @   二次元攻城狮  阅读(261)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
历史上的今天:
2020-06-13 C#使用Stateless和箭头控件实现状态机的控制及显示
  1. 1 烟花易冷 小柔Channel
  2. 2 红颜如霜 江壹纯
  3. 3 不谓侠 小桃Channel
  4. 4 小小恋歌 新坦结衣
  5. 5 神预言 袁娅维TIARAY
红颜如霜 - 江壹纯
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示
主题色彩