net加密基础1-对称加密
2012-02-04 21:43 海不是蓝 阅读(1799) 评论(2) 编辑 收藏 举报
.NET中常用的3个密码术命名空间 |
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;
它们依次的大概作用解释:
1.System.Security.Cryptography
包含所有加密任务的核心类
2.System.Security.Cryptography.Xml
包含结合使用System.Security.Cryptography类,对XML文档部分内容进行加密和签名的类
3.System.Security.Cryptography.X509Certificates
包含允许检索证书信息的类
System.Security.Cryptography的3层模型
第一层:第一层是一组抽象类,它们表示加密算法的类型,用于完成特定的加密任务。
第二层:表示包含特定加密算法的类,由第一层派生而来,它们也是抽象类,例如DES算法类。
第三层:就是加密的实现方案。都是由算法类派生而来。
构建块
NET系统使用基于流的体系结构来加密和解密,这样就可以方便的对来自不同数据源的不同数据类型进行加密处理。
它是如何工作的?ICryptoTransform接口和CryptoStream类
ICryptoTransform接口
由可以执行块加密转换的类实现,可以是加密,解密,散列计算,基于64的编码/解码或格式化操作。
DES des = DES.Create();
ICryptoTransform ic = des.CreateEncryptor();
这个接口的详细解释请去msdn观看。多数情况我们用CryptoStream类替换这个接口。
CryptoStream类
这个类是个重点,它包装了,并使用ICryptoTransform 在后台执行操作。
优点是它采用了缓冲访问,使用它就可以进行加密。不用担心算法所需要块的大小。
另外一个优点是它包装了普通NET Stream派生类,所以它可以很方便的和各种流进行操作。
下面介绍下加密算法的分类
对称密码算法 |
加密解密都使用相同的密钥,那么这个密码算法就是对称密码算法。
即如果密钥K用于将明文加密成NajDs78a,那么密钥K也就用解密NajDs78a。
由于加密解密都采用相同的密钥,所以有时候称为同一密钥和单密钥。
对称密码算法分为两大类:
1.块密码算法
2.流密码算法
它们分别用于不同的应用程序领域。
NET中提供的对称算法
算 法 |
抽象算法类 |
默认实现类 |
有效密钥大小 |
默认密钥大小 |
DES |
DES |
DESCryptoServiceProvider |
64位 |
64 |
TripleDES |
TripleDES |
TripleDESCryptoServiceProvider
|
128,192 |
192 |
RC2 |
RC2 |
RC2CryptoServiceProvider
|
40-128 |
128 |
Rijndael |
Rijndael |
RijndaelManaged
|
128,192,256 |
256 |
大多数情况可以使用Rijndael作为默认推荐的算法.
SymmetricAlgorithm类 |
上面所有的对称加密类都是继承SymmetricAlgorithm类。
几个重要的属性
属性 |
说明 |
BlockSize |
使用该算法在一次操作中可以加密或解密的数据基本单位。 |
Key |
用于加密或解密数据的秘密值。 |
KeySize |
分配给秘密密钥的位数。 |
IV |
初始化向量,提供加密过程额外输入并提高安全性,初始化向量与密钥一样,加密者和解密者都必须知道,不过,它不需要保密。 重点:IV的长度总是和BlockSize 数据块的长度一样! |
LegalBlockSizes |
获取对称算法支持的块大小。 |
LegalKeySizes |
获取对称算法支持的密钥大小。 |
非对称密码算法 |
net加密基础-非对称加密中介绍。
使用对称加密DES算法 |
1.创建DES对象
DES des = DES.Create();
然后我们就要设置密钥Key和初始化向量IV。
2.设置密钥Key和初始化向量IV
我们先看看Net中对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 ,也就是加密或解密的数据块。
s_legalKeySizes 就是密钥。
再看看KeySizes的定义
public KeySizes(int minSize, int maxSize, int skipSize)
{
this.m_minSize = minSize;
this.m_maxSize = maxSize;
this.m_skipSize = skipSize;
}
通过上面我们知道了DES算法的数据块大小为0x40位,也就是64位,转换成byte数组就是长度为8。也就是64除以8=8个字节大小。
上面我们提到过IV的长度总是和BlockSize 数据块的长度一样!
所以我们使用DES算法的时候IV的长度应该为8个长度的byte数组。
同理,使用DES算法的密钥Key的长度为8个长度的byte数组。
注意KeySizes定义了最大和最小!只是这里DES算法最大最小都是一样的
码如果在使用加密算法的时候不按照算法要求设置Key长度和IV长度,就会抛出异常!
static void Main()
{
//假设这里是加密客户
DES des = DES.Create();
Encoding e = Encoding.UTF8;
//注意下面的Key和IV都是设置为64位长度的,转换以后就是长度为8的byte数组
string str = DEScryptor(des, "我是明文", e, "ujd87yr4", "ujd87yr4");
Console.WriteLine("密文:{0}", str);
//假设这里是解密客户
DES des1 = DES.Create();
Console.WriteLine("明文:{0}", DESDecryptor(des1, str, e, "ujd87yr4", "ujd87yr4"));
Console.Read();
}
/// <summary>
/// DES对称加密算法
/// </summary>
/// <typeparam name="T">对称加密算法类型</typeparam>
/// <param name="Encryptor">加密算法实例对象</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("参数不正确!");
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对称解密算法
/// </summary>
/// <typeparam name="T">对称解密算法类型</typeparam>
/// <param name="Decryptor">对称解密算法实例对象</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("参数不正确!");
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();
}
}
其它对称算法介绍 |
微软是将Rijndael作为默认推荐的算法,
通过Reflector这个工具我们可以查看它的Key长度等信息
// 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的长度有2个合法的,最小是长度为16的byte数组,最大为32长度的byte数组。
IV的长度和Key一样,小是长度为16的byte数组,最大为32长度的byte数组
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) };
为了方便使用,我写了个对称加密的泛型方法
static void Main()
{
//假设这里是加密客户
Rijndael rj = Rijndael.Create();
Encoding e = Encoding.UTF8;
//注意下面的Key和IV都是设置为128位长度的,转换以后就是长度为16的byte数组
string str = SymmetryEncryptor<Rijndael>(rj, "我是明文", e, "ujd87yr4sdf34rt5", "ujd87yr4sdf34rt5");
Console.WriteLine("密文:{0}", str);
//假设这里是解密客户
Rijndael rj1 = Rijndael.Create();
Console.WriteLine("明文:{0}", SymmetryDecryptor<Rijndael>(rj1, str, e, "ujd87yr4sdf34rt5", "ujd87yr4sdf34rt5"));
Console.Read();
}
/// <summary>
/// 对称加密算法
/// </summary>
/// <typeparam name="T">对称加密算法类型</typeparam>
/// <param name="Encryptor">加密算法实例对象</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("参数不正确!");
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>
/// 对称解密算法
/// </summary>
/// <typeparam name="T">对称解密算法类型</typeparam>
/// <param name="Decryptor">对称解密算法实例对象</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("参数不正确!");
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();
}
}
作者:海不是蓝 博客:http://www.cnblogs.com/hailan2012/ 邮箱:hailan2012@sina.com 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 |