net加密基礎(chǔ)1-對(duì)稱加密
2012-02-04 21:43 海不是藍(lán) 閱讀(1814) 評(píng)論(2) 收藏 舉報(bào)|
.NET中常用的3個(gè)密碼術(shù)命名空間 |
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;
它們依次的大概作用解釋:
1.System.Security.Cryptography
包含所有加密任務(wù)的核心類
2.System.Security.Cryptography.Xml
包含結(jié)合使用System.Security.Cryptography類,對(duì)XML文檔部分內(nèi)容進(jìn)行加密和簽名的類
3.System.Security.Cryptography.X509Certificates
包含允許檢索證書信息的類
System.Security.Cryptography的3層模型

第一層:第一層是一組抽象類,它們表示加密算法的類型,用于完成特定的加密任務(wù)。
第二層:表示包含特定加密算法的類,由第一層派生而來,它們也是抽象類,例如DES算法類。
第三層:就是加密的實(shí)現(xiàn)方案。都是由算法類派生而來。
構(gòu)建塊
NET系統(tǒng)使用基于流的體系結(jié)構(gòu)來加密和解密,這樣就可以方便的對(duì)來自不同數(shù)據(jù)源的不同數(shù)據(jù)類型進(jìn)行加密處理。
它是如何工作的?ICryptoTransform接口和CryptoStream類
ICryptoTransform接口
由可以執(zhí)行塊加密轉(zhuǎn)換的類實(shí)現(xiàn),可以是加密,解密,散列計(jì)算,基于64的編碼/解碼或格式化操作。
DES des = DES.Create();
ICryptoTransform ic = des.CreateEncryptor();
這個(gè)接口的詳細(xì)解釋請(qǐng)去msdn觀看。多數(shù)情況我們用CryptoStream類替換這個(gè)接口。
CryptoStream類
這個(gè)類是個(gè)重點(diǎn),它包裝了,并使用ICryptoTransform 在后臺(tái)執(zhí)行操作。
優(yōu)點(diǎn)是它采用了緩沖訪問,使用它就可以進(jìn)行加密。不用擔(dān)心算法所需要塊的大小。
另外一個(gè)優(yōu)點(diǎn)是它包裝了普通NET Stream派生類,所以它可以很方便的和各種流進(jìn)行操作。
下面介紹下加密算法的分類
|
對(duì)稱密碼算法 |
加密解密都使用相同的密鑰,那么這個(gè)密碼算法就是對(duì)稱密碼算法。
即如果密鑰K用于將明文加密成NajDs78a,那么密鑰K也就用解密NajDs78a。
由于加密解密都采用相同的密鑰,所以有時(shí)候稱為同一密鑰和單密鑰。
對(duì)稱密碼算法分為兩大類:
1.塊密碼算法
2.流密碼算法
它們分別用于不同的應(yīng)用程序領(lǐng)域。
NET中提供的對(duì)稱算法
|
算 法 |
抽象算法類 |
默認(rèn)實(shí)現(xiàn)類 |
有效密鑰大小 |
默認(rèn)密鑰大小 |
|
DES |
DES |
DESCryptoServiceProvider |
64位 |
64 |
|
TripleDES |
TripleDES |
TripleDESCryptoServiceProvider
|
128,192 |
192 |
|
RC2 |
RC2 |
RC2CryptoServiceProvider
|
40-128 |
128 |
|
Rijndael |
Rijndael |
RijndaelManaged
|
128,192,256 |
256 |
大多數(shù)情況可以使用Rijndael作為默認(rèn)推薦的算法.
|
SymmetricAlgorithm類 |
上面所有的對(duì)稱加密類都是繼承SymmetricAlgorithm類。
幾個(gè)重要的屬性
|
屬性 |
說明 |
|
BlockSize |
使用該算法在一次操作中可以加密或解密的數(shù)據(jù)基本單位。 |
|
Key |
用于加密或解密數(shù)據(jù)的秘密值。 |
|
KeySize |
分配給秘密密鑰的位數(shù)。 |
|
IV |
初始化向量,提供加密過程額外輸入并提高安全性,初始化向量與密鑰一樣,加密者和解密者都必須知道,不過,它不需要保密。 重點(diǎn):IV的長(zhǎng)度總是和BlockSize 數(shù)據(jù)塊的長(zhǎng)度一樣! |
|
LegalBlockSizes |
獲取對(duì)稱算法支持的塊大小。 |
|
LegalKeySizes |
獲取對(duì)稱算法支持的密鑰大小。 |
|
非對(duì)稱密碼算法 |
net加密基礎(chǔ)-非對(duì)稱加密中介紹。
|
使用對(duì)稱加密DES算法 |
1.創(chuàng)建DES對(duì)象
DES des = DES.Create();
然后我們就要設(shè)置密鑰Key和初始化向量IV。
2.設(shè)置密鑰Key和初始化向量IV
我們先看看Net中對(duì)Key和IV的定義
// Fields
private static KeySizes[] s_legalBlockSizes = new KeySizes[] { new KeySizes(0x40, 0x40, 0) };
private static KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(0x40, 0x40, 0) };
s_legalBlockSizes是BlockSize ,也就是加密或解密的數(shù)據(jù)塊。
s_legalKeySizes 就是密鑰。
再看看KeySizes的定義
public KeySizes(int minSize, int maxSize, int skipSize)
{
this.m_minSize = minSize;
this.m_maxSize = maxSize;
this.m_skipSize = skipSize;
}
通過上面我們知道了DES算法的數(shù)據(jù)塊大小為0x40位,也就是64位,轉(zhuǎn)換成byte數(shù)組就是長(zhǎng)度為8。也就是64除以8=8個(gè)字節(jié)大小。
上面我們提到過IV的長(zhǎng)度總是和BlockSize 數(shù)據(jù)塊的長(zhǎng)度一樣!
所以我們使用DES算法的時(shí)候IV的長(zhǎng)度應(yīng)該為8個(gè)長(zhǎng)度的byte數(shù)組。
同理,使用DES算法的密鑰Key的長(zhǎng)度為8個(gè)長(zhǎng)度的byte數(shù)組。
注意KeySizes定義了最大和最小!只是這里DES算法最大最小都是一樣的
碼如果在使用加密算法的時(shí)候不按照算法要求設(shè)置Key長(zhǎng)度和IV長(zhǎng)度,就會(huì)拋出異常!

static void Main()
{
//假設(shè)這里是加密客戶
DES des = DES.Create();
Encoding e = Encoding.UTF8;
//注意下面的Key和IV都是設(shè)置為64位長(zhǎng)度的,轉(zhuǎn)換以后就是長(zhǎng)度為8的byte數(shù)組
string str = DEScryptor(des, "我是明文", e, "ujd87yr4", "ujd87yr4");
Console.WriteLine("密文:{0}", str);
//假設(shè)這里是解密客戶
DES des1 = DES.Create();
Console.WriteLine("明文:{0}", DESDecryptor(des1, str, e, "ujd87yr4", "ujd87yr4"));
Console.Read();
}
/// <summary>
/// DES對(duì)稱加密算法
/// </summary>
/// <typeparam name="T">對(duì)稱加密算法類型</typeparam>
/// <param name="Encryptor">加密算法實(shí)例對(duì)象</param>
/// <param name="EncryptString">待加密的字符</param>
/// <param name="encd">待加密的字符編碼</param>
/// <param name="Key">加密算法密鑰</param>
/// <param name="IV">加密算法初始化向量</param>
/// <returns></returns>
public static string DEScryptor(DES Encryptor, string EncryptString, Encoding encd, string Key, string IV)
{
if (string.IsNullOrEmpty(EncryptString)
|| string.IsNullOrEmpty(Key)
|| string.IsNullOrEmpty(IV))
throw new ArgumentNullException("參數(shù)不正確!");
CryptoStream cs = null;
Encoding ec = encd ?? Encoding.Default;
Byte[] StrBytes = ec.GetBytes(EncryptString);
Byte[] KeyBytes = Encoding.ASCII.GetBytes(Key);
Byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
try
{
MemoryStream ms = new MemoryStream();
cs = new CryptoStream(ms, Encryptor.CreateEncryptor(KeyBytes, IVBytes), CryptoStreamMode.Write);
cs.Write(StrBytes, 0, StrBytes.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
catch (CryptographicException ex)
{
throw new ArgumentException(ex.Message);
}
finally
{
if (cs != null)
cs.Close();
}
}
/// <summary>
/// DES對(duì)稱解密算法
/// </summary>
/// <typeparam name="T">對(duì)稱解密算法類型</typeparam>
/// <param name="Decryptor">對(duì)稱解密算法實(shí)例對(duì)象</param>
/// <param name="DecryptorString">代解密的字符串</param>
/// <param name="encd">輸出的解密字符串編碼</param>
/// <param name="Key">解密密鑰</param>
/// <param name="IV">解密初始化向量</param>
/// <returns></returns>
public static string DESDecryptor(DES Decryptor, string DecryptorString, Encoding encd, string Key, string IV)
{
if (string.IsNullOrEmpty(DecryptorString)
|| string.IsNullOrEmpty(Key)
|| string.IsNullOrEmpty(IV))
throw new ArgumentNullException("參數(shù)不正確!");
CryptoStream cs = null;
Encoding ec = encd ?? Encoding.Default;
Byte[] StrBytes = Convert.FromBase64String(DecryptorString);
Byte[] KeyBytes = Encoding.ASCII.GetBytes(Key);
Byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
try
{
MemoryStream ms = new MemoryStream();
cs = new CryptoStream(ms, Decryptor.CreateDecryptor(KeyBytes, IVBytes), CryptoStreamMode.Write);
cs.Write(StrBytes, 0, StrBytes.Length);
cs.FlushFinalBlock();
return ec.GetString(ms.ToArray());
}
catch (CryptographicException ex)
{
throw new ArgumentException(ex.Message);
}
finally
{
if (cs != null)
cs.Close();
}
}

|
其它對(duì)稱算法介紹 |
微軟是將Rijndael作為默認(rèn)推薦的算法,
通過Reflector這個(gè)工具我們可以查看它的Key長(zhǎng)度等信息
// Fields
private static KeySizes[] s_legalBlockSizes = new KeySizes[] { new KeySizes(0x80, 0x100, 0x40) };
private static KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(0x80, 0x100, 0x40) };
所以Rijndael加密算法的密鑰Key的長(zhǎng)度有2個(gè)合法的,最小是長(zhǎng)度為16的byte數(shù)組,最大為32長(zhǎng)度的byte數(shù)組。
IV的長(zhǎng)度和Key一樣,小是長(zhǎng)度為16的byte數(shù)組,最大為32長(zhǎng)度的byte數(shù)組
TripleDES加密算法
// Fields
private static KeySizes[] s_legalBlockSizes = new KeySizes[] { new KeySizes(0x40, 0x40, 0) };
private static KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(0x80, 0xc0, 0x40) };
RC2加密算法
// Fields
protected int EffectiveKeySizeValue;
private static KeySizes[] s_legalBlockSizes = new KeySizes[] { new KeySizes(0x40, 0x40, 0) };
private static KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(40, 0x400, 8) };
為了方便使用,我寫了個(gè)對(duì)稱加密的泛型方法
static void Main()
{
//假設(shè)這里是加密客戶
Rijndael rj = Rijndael.Create();
Encoding e = Encoding.UTF8;
//注意下面的Key和IV都是設(shè)置為128位長(zhǎng)度的,轉(zhuǎn)換以后就是長(zhǎng)度為16的byte數(shù)組
string str = SymmetryEncryptor<Rijndael>(rj, "我是明文", e, "ujd87yr4sdf34rt5", "ujd87yr4sdf34rt5");
Console.WriteLine("密文:{0}", str);
//假設(shè)這里是解密客戶
Rijndael rj1 = Rijndael.Create();
Console.WriteLine("明文:{0}", SymmetryDecryptor<Rijndael>(rj1, str, e, "ujd87yr4sdf34rt5", "ujd87yr4sdf34rt5"));
Console.Read();
}
/// <summary>
/// 對(duì)稱加密算法
/// </summary>
/// <typeparam name="T">對(duì)稱加密算法類型</typeparam>
/// <param name="Encryptor">加密算法實(shí)例對(duì)象</param>
/// <param name="EncryptString">待加密的字符</param>
/// <param name="encd">待加密的字符編碼</param>
/// <param name="Key">加密算法密鑰</param>
/// <param name="IV">加密算法初始化向量</param>
/// <returns></returns>
public static string SymmetryEncryptor<T>(T Encryptor, string EncryptString, Encoding encd, string Key, string IV)
where T : SymmetricAlgorithm
{
if (string.IsNullOrEmpty(EncryptString)
|| string.IsNullOrEmpty(Key)
|| string.IsNullOrEmpty(IV))
throw new ArgumentNullException("參數(shù)不正確!");
CryptoStream cs = null;
Encoding ec = encd ?? Encoding.Default;
Byte[] StrBytes = ec.GetBytes(EncryptString);
Byte[] KeyBytes = Encoding.ASCII.GetBytes(Key);
Byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
try
{
MemoryStream ms = new MemoryStream();
cs = new CryptoStream(ms, Encryptor.CreateEncryptor(KeyBytes, IVBytes), CryptoStreamMode.Write);
cs.Write(StrBytes, 0, StrBytes.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
catch (CryptographicException ex)
{
throw new ArgumentException(ex.Message);
}
finally
{
if (cs != null)
cs.Close();
}
}
/// <summary>
/// 對(duì)稱解密算法
/// </summary>
/// <typeparam name="T">對(duì)稱解密算法類型</typeparam>
/// <param name="Decryptor">對(duì)稱解密算法實(shí)例對(duì)象</param>
/// <param name="DecryptorString">代解密的字符串</param>
/// <param name="encd">輸出的解密字符串編碼</param>
/// <param name="Key">解密密鑰</param>
/// <param name="IV">解密初始化向量</param>
/// <returns></returns>
public static string SymmetryDecryptor<T>(T Decryptor, string DecryptorString, Encoding encd, string Key, string IV)
where T : SymmetricAlgorithm
{
if (string.IsNullOrEmpty(DecryptorString)
|| string.IsNullOrEmpty(Key)
|| string.IsNullOrEmpty(IV))
throw new ArgumentNullException("參數(shù)不正確!");
CryptoStream cs = null;
Encoding ec = encd ?? Encoding.Default;
Byte[] StrBytes = Convert.FromBase64String(DecryptorString);
Byte[] KeyBytes = Encoding.ASCII.GetBytes(Key);
Byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
try
{
MemoryStream ms = new MemoryStream();
cs = new CryptoStream(ms, Decryptor.CreateDecryptor(KeyBytes, IVBytes), CryptoStreamMode.Write);
cs.Write(StrBytes, 0, StrBytes.Length);
cs.FlushFinalBlock();
return ec.GetString(ms.ToArray());
}
catch (CryptographicException ex)
{
throw new ArgumentException(ex.Message);
}
finally
{
if (cs != null)
cs.Close();
}
}
|
作者:海不是藍(lán) 博客:http://www.rzrgm.cn/hailan2012/ 郵箱:hailan2012@sina.com 本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。 |
浙公網(wǎng)安備 33010602011771號(hào)