[食譜好菜] C# DES 對稱加密演算法使用不固定長度的 Key 及 IV 進行加解密

  • 12482
  • 0
  • DES
  • 2018-09-12

DES 加密演算法是一種對稱加密演算法,但是用來加解密的 Key 及 IV 需要固定長度,DES 的 Key 及 IV 長度大小都是固定 8 bytes,也就是說每次加解密的過程中都需要湊足 8 bytes 的 Key 及 IV,多了或少了都不行。

我參考余小章的文章 - [C#.NET] 字串及檔案 利用 DES / AES 演算法加解密,實作如何使用不固定長度的 Key 及 IV 進行 DES 加解密。

加密

如何使用不固定長度的 Key 及 IV,關鍵就在於把不固定轉成固定就行了,下面我使用 MD5CryptoServiceProviderRfc2898DeriveBytes 這兩個類別提供的方法來達成這件事情。

private string EncryptByDES(string source, string key, string iv)
{
    DESCryptoServiceProvider des = new DESCryptoServiceProvider();

    // Rfc2898DeriveBytes 類別可以用來從基底金鑰與其他參數中產生衍生金鑰。
    // 使用 MD5 來 Hash 出 Rfc2898 需要的 Salt。
    Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(key, this.HashByMD5(key));

    // 8 bits = 1 byte,將 KeySize 及 BlockSize 個別除以 8,取得 Rfc2898 產生衍生金鑰的長度。
    des.Key = rfc2898.GetBytes(des.KeySize / 8);
    des.IV = rfc2898.GetBytes(des.BlockSize / 8);

    var dataByteArray = Encoding.UTF8.GetBytes(source);

    // 加密
    using (MemoryStream ms = new MemoryStream())
    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
    {
        cs.Write(dataByteArray, 0, dataByteArray.Length);
        cs.FlushFinalBlock();

        return Convert.ToBase64String(ms.ToArray());
    }
    
    // 或
    var encrypted = des.CreateEncryptor().TransformFinalBlock(dataByteArray, 0, dataByteArray.Length);
    
    return Convert.ToBase64String(encrypted);
}

MD5 Hash 方法

private byte[] HashByMD5(string source)
{
    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
    
    return md5.ComputeHash(Encoding.UTF8.GetBytes(source));
}

解密

解密也一樣,利用 MD5CryptoServiceProvider 及 Rfc2898DeriveBytes 取得 Key 及 IV 後進行解密程序。

private string DecryptByDES(string encrypted, string key, string iv)
{
    DESCryptoServiceProvider des = new DESCryptoServiceProvider();

    // Rfc2898DeriveBytes 類別可以用來從基底金鑰與其他參數中產生衍生金鑰。
    // 使用 MD5 來 Hash 出 Rfc2898 需要的 Salt。
    Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(key, this.HashByMD5(key));

    // 8 bits = 1 byte,將 KeySize 及 BlockSize 個別除以 8,取得 Rfc2898 產生衍生金鑰的長度。
    des.Key = rfc2898.GetBytes(des.KeySize / 8);
    des.IV = rfc2898.GetBytes(des.BlockSize / 8);

    var dataByteArray = Convert.FromBase64String(encrypted);

    // 解密
    using (MemoryStream ms = new MemoryStream())
    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
    {
        cs.Write(dataByteArray, 0, dataByteArray.Length);
        cs.FlushFinalBlock();

        return Encoding.UTF8.GetString(ms.ToArray());
    }
    
    // 或
    var decryped = des.CreateDecryptor().TransformFinalBlock(dataByteArray, 0, dataByteArray.Length);
    
    return Encoding.UTF8.GetString(decryped);
}

 < Source Code >

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學