離過年又近了一天,回家已是近在咫尺,有人歡喜有人愁,因為過幾天就得經曆每年一度的裝逼大戲,親戚朋友加同學的各方顯擺,是以得靠一劑年終獎來裝飾一個安穩的年,在這裡我想起了一個題目“論裝逼的技術性和重要性”。
都是老司機了,不扯淡,站在外面的都進來,然後請後面的把門關一下,我們接着出發。
上一篇主要介紹.NET的散列加密,雜湊演算法主要用于簽名等操作,在我們的項目中,如果對加密沒有特别的要求,一般都是采用的對稱加密方式,因為這種加密方式相較其他加密方式較為簡單,但是這種加密方式比較的高效,是以今天就介紹一下.NET的對稱加密方式。
一.DotNet對稱加密概述:
對稱加密是采用單密鑰加密方式,這也就意味着加密和解密都是用同一個密鑰。根據密碼學的相關定義,對稱加密系統的組成部分有5個,分别是明文空間,密文空間,密鑰空間,加密空間,解密算法。接下來用一個示意圖來表示一下:
DotNet對稱加密算法的核心是一個密碼函數,該函數将固定大小的消息資料塊(純文字)轉換成加密資料庫(加密文本)。轉化為加密文本或重建為純文字都需要密鑰,加密是可逆的,或者說是雙向的過程,可以使用密鑰來反轉加密效果并重建純文字。
大多數對稱加密算法是在不同的密碼模式下運作,在密碼函數處理資料之前,這些模式指定了準備這些資料的不同方式。密碼模式有:電子代碼薄模式,密碼塊連結,密碼回報模式。
有關塊值填充的内容在下面會講解到。
二.DotNet對稱加密類解析:
1.對稱加密分類:
(1).在.NET中對稱加密算法分類有如下結構圖:
(2).對于.NET對稱加密算法的說明如下表格:
算法名稱 | 算法說明 |
DES加密算法 | 采用的是分組加密方式,使用56位密鑰加密64位明文,最後産生64位密文 |
3DES加密算法 | 采用168位的密鑰,三重加密,速度比較的慢 |
TripleDES加密算法 | 用兩個密鑰對資料進行3次加密/解密運算 |
RC2加密算法 | 運用密鑰長度可變,對明文采取64位分組加密 |
RC4加密算法 | 運用一個密鑰長度可變的面向位元組流的加密算法,以随機置換為基礎 |
RC5加密算法 | 運用一種分組長度、密鑰長度、加密疊代輪數都可變的分組加密算法。(包含密鑰擴充、加密算法、解密算法) |
RC6加密算法 | RC6繼承了RC5的循環移位思想,RC6是輸入的明文由原先2個區擴充為4個塊區 |
Rijndael加密算法 | 運用反複運算的加密算法,允許資料區塊及密鑰的長度可變。資料區塊與密鑰長度的變動時各自獨立的 |
2.DotNet對稱加密核心對象解析:
在.NET中對稱算法的層次結構如下圖:
Ⅰ.SymmetricAlgorithm類解析:
SymmetricAlgorithm類允許配置一個算法(選擇大小,填充模式)并建立加密和解密資料的執行個體;不能使用該類和導出實作類來種子直接處理資料。接下來我們具體了解一下SymmetricAlgorithm類的一些方法和屬性。該類是一個抽象類,是所有對稱加密算法基類。在使用派生類時,如果僅在用完對象後強制垃圾回收是不夠的,需要對該對象顯示的調用clear方法,以便在釋放對象之前将對象中所包含的所有敏感資料清除。
(1).IV屬性:擷取或設定對稱算法的初始化向量。
public virtual byte[] IV
{
get
{
if (this.IVValue == null)
this.GenerateIV();
return (byte[]) this.IVValue.Clone();
}
set
{
if (value == null)
throw new ArgumentNullException("value");
if (value.Length != this.BlockSizeValue / 8)
throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidIVSize"));
this.IVValue = (byte[]) value.Clone();
}
}
該屬于使用位元組數組的形式表示Key,該屬性具有get和set屬性,表明該屬性是可讀可寫的,該屬性為虛屬性,可以在子類中重寫。Key屬性是用來擷取或設定對稱算法的密鑰,密鑰即可使用于加密也可以使用于解密。
(2).LegalBlockSizes屬性: 擷取對稱算法支援的塊大小(以位為機關)。
public virtual KeySizes[] LegalBlockSizes
{
get
{
return (KeySizes[]) this.LegalBlockSizesValue.Clone();
}
}
該屬性為虛屬性,在子類中可重寫,該屬性是隻讀屬性。
(3).Create()方法:建立用于執行對稱算法的指定加密對象。
public static SymmetricAlgorithm Create(string algName)
{
return (SymmetricAlgorithm) CryptoConfig.CreateFromName(algName);
}
該方法CryptoConfig.CreateFromName()方法在前面一篇介紹過,在這裡就不做具體的介紹,Create()接收一個SymmetricAlgorithm類型的字元串參數,指定本次System.Security.Cryptography.SymmetricAlgorithm字元串。
(4).Mode屬性:擷取或設定對稱算法的運算模式。
public virtual CipherMode Mode
{
get
{
return this.ModeValue;
}
set
{
if (value < CipherMode.CBC || CipherMode.CFB < value)
throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidCipherMode"));
this.ModeValue = value;
}
}
該屬性是一個虛屬性,擷取和設定密碼代碼,拉取準備資料,由代碼可以看出,該屬性含有一個枚舉類型CipherMode,我們接下來了解一下這個枚舉類型:
CipherMode枚舉類型:指定用于加密的塊加密模式。
[ComVisible(true)]
public enum CipherMode
{
CBC = 1,
ECB = 2,
OFB = 3,
CFB = 4,
CTS = 5
}
CBC(密碼塊鍊):該模式引入類回報;ECB(電子密碼本):該模式分别加密每個塊;OFB(輸出回報):該模式将少量遞增的純文字處理改成密碼文本,而不是以此處理整個塊;CFB(密碼回報):該模式将少量遞增的純文字處理成密碼文本,而不是一次處理整個塊;CTS(密碼文本竊用):該模式處理任何長度的純文字并産生長度與純文字長度比對的密碼文本。
(5).Padding屬性: 擷取或設定對稱算法中使用的填充模式。
public virtual PaddingMode Padding
{
get
{
return this.PaddingValue;
}
set
{
if (value < PaddingMode.None || PaddingMode.ISO10126 < value)
throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidPaddingMode"));
this.PaddingValue = value;
}
}
該屬性是對稱算法中使用的填充模式,預設值為 PKCS7。該屬性可讀可寫,填充資料的部分塊。由該屬性可知一個枚舉類型PaddingMode。
PaddingMode枚舉:指定當消息資料塊較短時要應用的填充類型,比加密操作所需的全部位元組數。
[ComVisible(true)]
public enum PaddingMode
{
None = 1,
PKCS7 = 2,
Zeros = 3,
ANSIX923 = 4,
ISO10126 = 5
}
該枚舉類型有5個成員, None = 1:不填充;PKCS7 = 2:PKCS#7填充字元串由位元組序列組成,每個位元組都是等于添加的填充位元組的總數; Zeros = 3:填充字元串由設定為零的位元組組成; ANSIX923 = 4:ANSI X 923填充字元串由長度前面填充零的位元組序列組成;ISO10126 = 5:ISO10126填充字元串由長度之前的随機資料組成。
Ⅱ.ICryptoTransform:
ICryptoTransform定義基本的加密轉換運算,該接口的執行個體可以将文純文字轉化成加密文本,或者将加密文本轉化為純文字,每一個ICryptoTransform都是單向的,隻能被用于其建立的目的。該接口的屬性和方法如下:
/// <summary>
/// 擷取輸入塊大小。
/// </summary>
int InputBlockSize { get; }
/// <summary>
/// 擷取輸出塊大小。
/// </summary>
int OutputBlockSize { get; }
/// <summary>
/// 擷取一個值,該值訓示是否可以轉換多個塊。
/// </summary>
bool CanTransformMultipleBlocks { get; }
/// <summary>
/// 擷取一個值,該值訓示是否可重複使用目前轉換。
/// </summary>
bool CanReuseTransform { get; }
/// <summary>
/// 轉換輸入位元組數組的指定區域,并将所得到的轉換複制到輸出位元組數組的指定區域。
/// </summary>
int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
/// <summary>
/// 轉換指定位元組數組的指定區域。
/// </summary>
byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount);
ICryptoTransform接口執行個體并不能使用于自己,.NET提供了CryptoStream類,定義将資料流連結到加密轉換的流。建立CryptoStream的執行個體需要一個真實流、ICryptoTransform、CryptoStreamMode枚舉的值。
三.DotNet對稱加密執行個體:
1.DES算法加密執行個體:
/// <summary>
/// 加密資料
/// </summary>
/// <param name="text"></param>
/// <param name="sKey"></param>
/// <returns></returns>
public static string Encrypt(string text, string sKey)
{
if (string.IsNullOrEmpty(text))
{
throw new ArgumentNullException(text);
}
if (string.IsNullOrEmpty(sKey))
{
throw new ArgumentNullException(sKey);
}
MemoryStream ms = null;
DESCryptoServiceProvider des = null;
try
{
des = new DESCryptoServiceProvider();
var inputByteArray = Encoding.Default.GetBytes(text);
var bKey = Encoding.ASCII.GetBytes(Md5Hash(sKey).Substring(0, 8));
des.Key = bKey;
des.IV = bKey;
ms = new MemoryStream();
var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
var ret = new StringBuilder();
foreach (byte b in ms.ToArray())
{
ret.AppendFormat("{0:X2}", b);
}
return ret.ToString();
}
catch (NotSupportedException nsex)
{
throw nsex;
}
catch (ArgumentNullException arnex)
{
throw arnex;
}
catch (EncoderFallbackException efex)
{
throw efex;
}
catch (ArgumentException arex)
{
throw arex;
}
catch (CryptographicException crex)
{
throw crex;
}
finally
{
if (ms != null)
{
ms.Close();
}
if (des != null)
{
des.Clear();
}
}
}
2.DES算法解密執行個體:
/// <summary>
/// 解密資料
/// </summary>
/// <param name="text"></param>
/// <param name="sKey"></param>
/// <returns></returns>
public static string Decrypt(string text, string sKey)
{
if (string.IsNullOrEmpty(text))
{
throw new ArgumentNullException(text);
}
if (string.IsNullOrEmpty(sKey))
{
throw new ArgumentNullException(sKey);
}
MemoryStream ms = null;
DESCryptoServiceProvider des = null;
try
{
des = new DESCryptoServiceProvider();
var len = text.Length / 2;
byte[] inputByteArray = new byte[len];
int x;
for (x = 0; x < len; x++)
{
var i = Convert.ToInt32(text.Substring(x * 2, 2), 16);
inputByteArray[x] = (byte)i;
}
var bKey = Encoding.ASCII.GetBytes(Md5Hash(sKey).Substring(0, 8));
des.Key = bKey;
des.IV = bKey;
ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
return Encoding.Default.GetString(ms.ToArray());
}
catch (NotSupportedException nsex)
{
throw nsex;
}
catch (ArgumentNullException arnex)
{
throw arnex;
}
catch (EncoderFallbackException efex)
{
throw efex;
}
catch (ArgumentException arex)
{
throw arex;
}
catch (CryptographicException crex)
{
throw crex;
}
finally
{
if (ms != null)
{
ms.Close();
}
if (des != null)
{
des.Clear();
}
}
}
四.總結:
這篇博文主要講解.NET的對稱加密方式,從原理上講解和源碼分析,以及提供了對應的執行個體,輔助我們去了解加密。如有錯誤和不足之處,歡迎評批指正。
加密算法系列:
DotNet加密方式解析--散列加密:http://www.cnblogs.com/pengze0902/p/6268700.html
DotNet加密方式解析--對稱加密:http://www.cnblogs.com/pengze0902/p/6268702.html
DotNet加密方式解析--數字簽名:http://www.cnblogs.com/pengze0902/p/6268709.html
DotNet加密方式解析--非對稱加密:http://www.cnblogs.com/pengze0902/p/6268705.html
愛知求真,靜心鑽研,虛心學習,務實創新,細緻平和。