2017年10月19日 星期四

Published 星期四, 10月 19, 2017 by with 0 comment

C# AES encrypt/decrypt and Base64 encode/decode

範例檔案: 這裡下載
純執行檔:這裡下載

有興趣研究 AES 加解密 與 Base64 編解碼 的可以研究一下
因為用到了AES 元件,所以只適用 .NET 3.5 以上

畫面如下:

為什麼 AES 和 BASE64 寫在一起?
因為 AES 加密後的內容是 ASCII 碼,很多是無法以明文顯示的,因此會再編碼成BASE64以便傳遞或攜帶。反過來說,接收到AES的密碼通常會以BASE64編成居多,所以必須解碼後再進行AES解密環原本文。


Base64編碼:
要引用 using System;

//將文字內容(明文)轉成base64文字(編碼)
tbB64_2.Text = Convert.ToBase64String(Encoding.Default.GetBytes(tbB64_1.Text));

Base64解碼:
要引用 using System;

//將base64編碼文字轉回明文(解碼)
tbB64_1.Text = Encoding.Default.GetString(Convert.FromBase64String(tbB64_2.Text));

AES加密:
要引用 using System.Security.Cryptography;

static byte[] EncryptionByAES(string plainText, byte[] key, byte[] IV)
{
  byte[] encrypted;
  //檢查參數
  if (plainText == null || plainText.Length <= 0)
     throw new ArgumentNullException("沒有要加密的文字");
  if (key == null || key.Length <= 0)
     throw new ArgumentNullException("沒有提供金鑰");
  if (IV == null || IV.Length <= 0)
      throw new ArgumentNullException("沒有提供IV");
  //這裡使用Aes創建編譯物件
  using (Aes aes = Aes.Create())
  {
      aes.Key = key;
      aes.IV = IV;

      //創建密碼編譯轉換運算
      ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
      //使用記憶體串流來儲存結果,
      //如果要使用byte來儲存,就必須先提供byte[]空間長度 encryp = Convert.FromBase64String(plainText);
      using (MemoryStream mEncrypt = new MemoryStream())
      {
           //使用CryptoStream創建編碼轉換方法
           using (CryptoStream cEncrypt = new CryptoStream(mEncrypt, encryptor, CryptoStreamMode.Write))
           {
               //以編碼轉換方法處理資料流
               using (StreamWriter swStream = new StreamWriter(cEncrypt))
               {
                   //寫入資料流 >> mEncrypt
                   swStream.Write(plainText);
               }
               //輸出轉換成byte[]形式
               encrypted = mEncrypt.ToArray();
           }
      }
  }
  return encrypted;
}

AES解密:
要引用 using System.Security.Cryptography;

static string DecryptionByAES(byte[] cipherText, byte[] key , byte[] IV)
{
    string decrypted;

    //檢查參數
    if (cipherText == null || cipherText.Length <= 0)
        throw new ArgumentNullException("沒有要解密的內容");
    if (key == null || key.Length <= 0)
        throw new ArgumentNullException("沒有提供金鑰");
    if (IV == null || IV.Length <= 0)
        throw new ArgumentNullException("沒有提供IV");

    //這裡使用Aes創建編譯物件
    using (Aes aes = Aes.Create())
    {
        aes.Key = key;
        aes.IV = IV;

        //創建密碼解譯轉換運算
        ICryptoTransform encryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        //先把密文byte放到記憶體串流,再用decrypt方法(解碼)讀取去
        using (MemoryStream mDecrypt = new MemoryStream(cipherText))
        {
            //使用CryptoStream創建解碼轉換方法
            using (CryptoStream cDecrypt = new CryptoStream(mDecrypt, encryptor, CryptoStreamMode.Read))
            {
                //以解碼轉換方法處理資料流
                using (StreamReader swStream = new StreamReader(cDecrypt))
                {
                    //讀出資料流(同時解碼)
                    decrypted = swStream.ReadToEnd();
                }
            }
        }
    }
    return decrypted;
}

AES的金鑰(KEY)和向量(IV):
  大部分使用金鑰都會使用同一把金鑰,也就是加密者和解密者必須共用一把KEY來處理,這個又稱對稱型金鑰加密(Symmetric Key Encryption),這裡也只討論這種加密方式。

  AES加解密過程必須同時使用到 KEY (秘密金鑰) IV (對稱演算法的初始化向量 (initialization vector)),一般使用的情況下,並不會特別指定使用 IV 值,因此在這個範例裡面 IV 的直是透過 KEY 以 MD5 的 Hash 產生(一般常見做法)就可以了

using(MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
    iv = md5.ComputeHash(key);
}




    email this       edit

0 個回應: