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.png

Rijndael算法

Rijndael算法是由比利时学者Joan Daemen和Vincent Rijmen所提出的,算法的名字就由两位作者的名字组合而成。Rijndael的优势在于集安全性、性能、效率、可实现性及灵活性与一体。

背景

由于在HTTP中参数都是通过URL或者Body进行传输的,那么就存在信息的暴露问题,这时候很多敏感的信息就需要进行加密,防止敏感信息泄露。

具体实现

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)

  • 使用包

    npm install crypto-js
  • 定义Key/IV

    const key = CryptoJS.enc.Utf8.parse("1234567890000000");
    const iv = CryptoJS.enc.Utf8.parse("1234567890000000");
    注意:客户端和服务端的KEY/IV必须保持一致
  • 加密方法

    //**************************************************************
    //*字符串/对象加密
    //*   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;
    }

3、展示效果

  • 采用简单的注册信息进行测试
    image.png
  • Js进行加密后的值
    image.png
  • 服务端解密的值与注册的验证码一致
    image.png

参考资料

demo下载地址:https://download.csdn.net/dow...

————————————————
原文链接:https://blog.csdn.net/xhl_jam...


Wonfody
58 声望4 粉丝

像春风里一出梦, 像梦路的一声钟!