1 .Net Framework1.1中常见加密算法
加密类(可以从密文中还原出原始信息)
DES,TripleDES,RC2,RC4,Rijndael(AES)
消息摘要类(不能从消息摘要中还原出原始信息,只能用于数据校验)
MD5,SHA1,SHA256,SHA384,SHA512
2 加密知识简介
如果以密钥为标准,可将密码系统分为单钥密码(又称为对称密码或私钥密码)体系和双钥密码(又称为非对称密码或公钥密码)体系。所谓密钥差不多可以理解成密码。
在单钥体制下,加密密钥和解密密钥是一样的,如果加密密钥丢失,信息也就失去了保密性。而在双钥体制下,加密密钥与解密密钥是不同的,此时根本就不需要安全信道来传送密钥,而只需利用本地密钥发生器产生解密密钥即可。
双钥密码是1976年W.Diffie和M.E.Heilinan提出的一种新型密码体制。由于双钥密码体制的加密和解密不同,且能公开加密密钥,而仅需保密解密密钥,所以双钥密码不存在密钥管理问题。双钥密码还有一个优点是可以拥有数字签名等新功能。最有名的双钥密码体系是1977年由Rivest,Shamir和Ad1eman人提出的RSA密码体制。双钥密码的缺点是:双钥密码算法一般比较复杂,加解密速度慢。
因此,网络中的加密普遍采用双钥和单钥密码相结合的混合加密体制,即加解密时采用单钥密码,密钥传送则采用双钥密码。这样既解决了密钥管理的困难,又解决了加解密速度的问题。目前看来,这种方法好象也只能这样了。你可以在下面的连接中找到一些密码学的基础知识。
http://www.chinaitpower.com/A/2002-01-02/9726.html
http://dev.csdn.net/article/13/13370.shtm
如果你想了解各种算法的介绍和实现细节,可以从下面的链接得到一些信息
DES: http://www.itl.nist.gov/fipspubs/fip46-2.htm
http://www.iusmentis.com/technology/encryption/des/
TripleDES: http://www.zvon.org/tmRFC/RFC3217/Output/chapter1.html
RC2: http://www.zvon.org/tmRFC/RFC2268/Output/index.html
RC4: http://www.wisdom.weizmann.ac.il/~itsik/RC4/rc4.html
AES: http://csrc.nist.gov/encryption/aes/rijndael/rijndael.pdf
http://fp.gladman.plus.com/aes/aes.zip
3 常用对称加密算法简介
DES是最有影响的单钥密码算法,由美国国家标准局在1977年颁布。它的特点是无论加密还是解密都使用同一个密钥,因此,此密码体制的安全性就是密钥的安全。如果密钥泄露,则此密码系统便被攻破。它的优点是:安全性高。加解密速度快。缺点是:1)随着网络规模的扩大,密钥的管理成为一个难点;2)无法解决消息确认问题;3)缺乏自动检测密钥泄露的能力。现在DES算法已经不再安全,用一台20万美元的设备可在56小时之内将56位DES破译(详见:www.eff.org)。
DES是一种古老的算法,现在已经有些过时了;TripleDES也比较古老了,但是现在还是比较安全的;RC2也是一种比较老的算法,但现在还是比较有用;AES是一种较新的算法,现在也非常流行。这几种算法在.Net Framework1.1中已经有了实现,我们只需要调用即可。
RC4算法是在.Net Framework2.0中新增的。它们的基本特点如下面的表所示。
尽管RC4在.Net Framework2.0里面才提供了实现,但是SourceForge上面有了一个C#的实现,你可以用在自己的Web工程里面。你可以参考我前面一篇文章得到RC4的代码。
算法 |
Key(密钥) |
向量 |
对称加密 |
.Net Framework |
地位 |
DES |
8字节 |
8字节 |
是 |
1.1 |
老,过时 |
TripleDES |
16字节或24字节 |
8字节 |
是 |
1.1 |
老,有用 |
RC2 |
Any |
8字节 |
是 |
1.1 |
老,有用 |
RC4 |
Any |
? |
是 |
2.0 |
新,有用 |
AES |
16字节,24字节或32字节 |
16字节 |
是 |
1.1 |
新,流行 |
4 常用hash加密算法简介
关于MD5和SHA1等的介绍和实现可以参看本博客中其它的文章,在这儿我只提供一个在.Net Framework中引用实现的例子。
5 代码实例:调用常用加密算法的实例
6 代码实例:调用常用哈希算法的实例
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class
EncryptClass
{
private string mKey = string
.Empty;
private
ServiceProviderEnum mAlgorithm;
private
SymmetricAlgorithm mCryptoService;
private void
SetLegalIV()
{
//
对称算法的初始化向量
//
对于DES, TripleDES, RC2向量的长度为8字节
//
对于Rijndael算法,向量长度为16字节
//
可以人工输入,也可以随机生成,方法是:des.GenerateIV();
//
在这儿为了简单起见,我们使用固定的值,
//也可以按照调整key的办法来调整向量。
switch
(mAlgorithm)
{
case
ServiceProviderEnum.Rijndael:
mCryptoService.IV = new byte[] {0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9, 0x5, 0x46, 0x9c, 0xea, 0xa8, 0x4b, 0x73,0xcc
};
break
;
default
:
mCryptoService.IV = new byte[] {0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9
};
break
;
}
}
public enum ServiceProviderEnum: int
{
//
.Net Framework1.1中支持的对称加密算法
Rijndael,
RC2,
DES,
TripleDES
}
//加密使用的Key
public string
Key
{
get
{
return
mKey;
}
set
{
mKey
=
value;
}
}
// 设定缺省的加密算法为Rijndael(AES)
public
EncryptClass()
{
mCryptoService = new
RijndaelManaged();
mCryptoService.Mode =
CipherMode.CBC;
mAlgorithm =
ServiceProviderEnum.Rijndael;
}
// 利用ServiceProviderEnum来选择一种加密算法
public
EncryptClass(ServiceProviderEnum serviceProvider)
{
switch
(serviceProvider)
{
case
ServiceProviderEnum.Rijndael:
mCryptoService = new
RijndaelManaged();
mAlgorithm =
ServiceProviderEnum.Rijndael;
break
;
case
ServiceProviderEnum.RC2:
mCryptoService = new
RC2CryptoServiceProvider();
mAlgorithm =
ServiceProviderEnum.RC2;
break
;
case
ServiceProviderEnum.DES:
mCryptoService = new
DESCryptoServiceProvider();
mAlgorithm =
ServiceProviderEnum.DES;
break
;
case
ServiceProviderEnum.TripleDES:
mCryptoService = new
TripleDESCryptoServiceProvider();
mAlgorithm =
ServiceProviderEnum.TripleDES;
break
;
}
mCryptoService.Mode =
CipherMode.CBC;
}
//利用算法名来选择加密算法
public EncryptClass(string
serviceProviderName)
{
try
{
switch
(serviceProviderName.ToLower())
{
case "rijndael"
:
serviceProviderName = "Rijndael"
;
mAlgorithm =
ServiceProviderEnum.Rijndael;
break
;
case "rc2"
:
serviceProviderName = "RC2"
;
mAlgorithm =
ServiceProviderEnum.RC2;
break
;
case "des"
:
serviceProviderName = "DES"
;
mAlgorithm =
ServiceProviderEnum.DES;
break
;
case "tripledes"
:
serviceProviderName = "TripleDES"
;
mAlgorithm =
ServiceProviderEnum.TripleDES;
break
;
}
mCryptoService =
(SymmetricAlgorithm)CryptoConfig.CreateFromName(serviceProviderName);
mCryptoService.Mode =
CipherMode.CBC;
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public byte
[] GetLegalKey()
{
//
对称算法的机密密钥的长度如下:
//
对于DES算法,密钥长度为8字节
//
对于TripleDES算法,密钥长度为16或者24字节
//
对于Rijndael算法,密钥长度为16,24或者32字节
//
可以人工输入,也可以随机生成,方法是:des.GenerateKey();
//对于不符合要求的key,就需要调整其内容
if (mCryptoService.LegalKeySizes.Length > 0
)
{
// 用位来表示key的大小
int keySize = mKey.Length * 8
;
int minSize = mCryptoService.LegalKeySizes[0
].MinSize;
int maxSize = mCryptoService.LegalKeySizes[0
].MaxSize;
int skipSize = mCryptoService.LegalKeySizes[0
].SkipSize;
if (keySize >
maxSize)
{
// 去除多余的部分
mKey = mKey.Substring(0, maxSize / 8
);
}
else if (keySize <
maxSize)
{
// 设定有效大小
int validSize = (keySize <= minSize)? minSize : (keySize - keySize % skipSize) +
skipSize;
if (keySize <
validSize)
{
// 使用*来填补不足的部分
mKey = mKey.PadRight(validSize / 8, '*'
);
}
}
}
PasswordDeriveBytes key = new PasswordDeriveBytes(mKey, ASCIIEncoding.ASCII.GetBytes(string
.Empty));
return
key.GetBytes(mKey.Length);
}
public string Encrypt(string
plainText)
{
byte[] cryptoByte = null
;
try
{
byte[] plainByte =
System.Text.UTF8Encoding.UTF8.GetBytes(plainText);
byte[] keyByte =
GetLegalKey();
// 设定key和向量
mCryptoService.Key =
keyByte;
SetLegalIV();
// 加密对象
ICryptoTransform cryptoTransform =
mCryptoService.CreateEncryptor();
// 内存流对象
MemoryStream ms = new
MemoryStream();
// 初始化加密流
CryptoStream cs = new
CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write);
// 将加密后的数据写入加密流
cs.Write(plainByte, 0
, plainByte.Length);
cs.FlushFinalBlock();
cs.Close();
// 得到加密后的数据
cryptoByte =
ms.ToArray();
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
return null
;
}
// 将数据转换成base64字符串
return Convert.ToBase64String(cryptoByte, 0, cryptoByte.GetLength(0
));
}
//解密的时候用的key和向量必须和加密的时候用的一样
public string Decrypt(string
cryptoText)
{
// 从base64字符串转换成字节
if(cryptoText == null
)
return null
;
byte[] cryptoByte =
Convert.FromBase64String(cryptoText);
byte[] keyByte =
GetLegalKey();
//设定key和向量
mCryptoService.Key =
keyByte;
SetLegalIV();
// 解密对象
ICryptoTransform cryptoTransform =
mCryptoService.CreateDecryptor();
try
{
// 内存流对象
MemoryStream ms = new MemoryStream(cryptoByte, 0
, cryptoByte.Length);
// 初始化一个解密流对象
CryptoStream cs = new
CryptoStream(ms, cryptoTransform, CryptoStreamMode.Read);
// 从解密流对象中得到解密后的数据
StreamReader sr = new
StreamReader(cs);
return
sr.ReadToEnd();
}
catch
{
return null
;
}
}
public static void Main(string
[] args)
{
string plainText = "a example 小朋友"
;
string key = "wqdj~yriu!@*k0_^fa7431%p$#=@hd+&"
;
string testEnc = null
;
string testDec = null
;
Console.WriteLine("Plain text: " +
plainText);
Console.WriteLine("Key: " + key + "/n"
);
EncryptClass enc1 = new
EncryptClass();
enc1.Key =
key;
testEnc =
enc1.Encrypt(plainText);
testDec =
enc1.Decrypt(testEnc);
Console.WriteLine("Use Encrypt algorithm: " +
enc1.mAlgorithm);
Console.WriteLine("Encrypted text: " +
testEnc);
Console.WriteLine("Decrypted text: " + testDec+"/n"
);
EncryptClass enc2 = new
EncryptClass(ServiceProviderEnum.TripleDES);
enc2.Key =
key;
testEnc =
enc2.Encrypt(plainText);
testDec =
enc2.Decrypt(testEnc);
Console.WriteLine("Use Encrypt algorithm: " +
enc2.mAlgorithm);
Console.WriteLine("Encrypted text: " +
testEnc);
Console.WriteLine("Decrypted text: " + testDec+"/n"
);
EncryptClass enc3 = new EncryptClass("rc2"
);
enc3.Key =
key;
testEnc =
enc3.Encrypt(plainText);
testDec =
enc3.Decrypt(testEnc);
Console.WriteLine("Use Encrypt algorithm: " +
enc3.mAlgorithm);
Console.WriteLine("Encrypted text: " +
testEnc);
Console.WriteLine("Decrypted text: " + testDec+"/n"
);
Console.Read();
}
}
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class
Hash
{
private
HashAlgorithm mCryptoService;
private
ServiceProviderEnum mAlgorithm;
public enum ServiceProviderEnum: int
{
//
支持的hash算法
SHA1,
SHA256,
SHA384,
SHA512,
MD5
}
public
Hash()
{
// 缺省的hash算法
mCryptoService = new
SHA1Managed();
mAlgorithm =
ServiceProviderEnum.SHA1;
}
public
Hash(ServiceProviderEnum serviceProvider)
{
//根据ServiceProviderEnum选择一个hash算法
switch
(serviceProvider)
{
case
ServiceProviderEnum.MD5:
mAlgorithm =
ServiceProviderEnum.MD5;
mCryptoService = new
MD5CryptoServiceProvider();
break
;
case
ServiceProviderEnum.SHA1:
mAlgorithm =
ServiceProviderEnum.SHA1;
mCryptoService = new
SHA1Managed();
break
;
case
ServiceProviderEnum.SHA256:
mAlgorithm =
ServiceProviderEnum.SHA256;
mCryptoService = new
SHA256Managed();
break
;
case
ServiceProviderEnum.SHA384:
mAlgorithm =
ServiceProviderEnum.SHA384;
mCryptoService = new
SHA384Managed();
break
;
case
ServiceProviderEnum.SHA512:
mAlgorithm =
ServiceProviderEnum.SHA512;
mCryptoService = new
SHA512Managed();
break
;
}
}
public Hash(string
serviceProviderName)
{
try
{
//根据hash算法的名字选择hash算法
switch
(serviceProviderName.ToUpper())
{
case "MD5"
:
serviceProviderName = "MD5"
;
mAlgorithm =
ServiceProviderEnum.MD5;
break
;
case "SHA1"
:
serviceProviderName = "SHA1"
;
mAlgorithm =
ServiceProviderEnum.SHA1;
break
;
case "SHA256"
:
serviceProviderName = "SHA256"
;
mAlgorithm =
ServiceProviderEnum.SHA256;
break
;
case "SHA384"
:
serviceProviderName = "SHA384"
;
mAlgorithm =
ServiceProviderEnum.SHA384;
break
;
case "SHA512"
:
serviceProviderName = "SHA512"
;
mAlgorithm =
ServiceProviderEnum.SHA512;
break
;
}
mCryptoService =
(HashAlgorithm)CryptoConfig.CreateFromName(serviceProviderName);
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
//hash一个文件
public string HashFile(string
filePath)
{
string hashCode = null
;
try
{
FileStream fs
=
File.Open(filePath,FileMode.Open,FileAccess.Read);
byte[] encodedBytes = this
.mCryptoService.ComputeHash(fs);
hashCode = BitConverter.ToString(encodedBytes).Replace("-", ""
);
fs.Close();
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
}
return
hashCode;
}
//hash一个字符串
public string HashString(string
originalPassword)
{
byte
[] originalBytes;
byte
[] encodedBytes;
string hashCode = null
;
try
{
originalBytes
=
System.Text.UTF8Encoding.UTF8.GetBytes(originalPassword);
encodedBytes = this
.mCryptoService.ComputeHash(originalBytes);
hashCode = BitConverter.ToString(encodedBytes).Replace("-", ""
);
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
}
return
hashCode;
}
public static void Main(string
[] args)
{
string plainText = "a example 小朋友 *&HHF"
;
string filePath = @"C:/WINDOWS/system32/notepad.exe"
;
string hashText = null
;
string hashFile = null
;
Console.WriteLine("Plain text: " +
plainText);
Hash hash = new Hash("md5"
);
hashText =
hash.HashString(plainText);
hashFile =
hash.HashFile(filePath);
Console.WriteLine("Use Hash algorithm: " +
hash.mAlgorithm);
Console.WriteLine("Hash code for text: " +
hashText);
Console.WriteLine("Hash code for file: " + hashFile+"/n"
);
Hash hash1 = new
Hash();
hashText =
hash1.HashString(plainText);
hashFile =
hash1.HashFile(filePath);
Console.WriteLine("Use Hash algorithm: " +
hash1.mAlgorithm);
Console.WriteLine("Hash code for text: " +
hashText);
Console.WriteLine("Hash code for file: " + hashFile+"/n"
);
Hash hash2 = new
Hash(ServiceProviderEnum.SHA384);
hashText =
hash2.HashString(plainText);
hashFile =
hash2.HashFile(filePath);
Console.WriteLine("Use Hash algorithm: " +
hash2.mAlgorithm);
Console.WriteLine("Hash code for text: " +
hashText);
Console.WriteLine("Hash code for file: " + hashFile+"/n"
);
Hash hash3 = new Hash("sha512"
);
hashText =
hash3.HashString(plainText);
hashFile =
hash3.HashFile(filePath);
Console.WriteLine("Use Hash algorithm: " +
hash3.mAlgorithm);
Console.WriteLine("Hash code for text: " +
hashText);
Console.WriteLine("Hash code for file: " + hashFile+"/n"
);
Console.Read();
}
}