33.NET对加密和解密的支持
散列运算
mscorlib.dll下的System.Security.Cryptography下:
抽象类HashAlgorithm
抽象类MD5
MD5CryptoServiceProvider
SHA1
SHA1CryptoServiceProvider密封类:调用Windows Crypto API
SHA1Managed普通类:用托管代码写的
SHA256
SHA256CryptoServiceProvider
SHA256Managed
SHA384
SHA512
□ 对字节数组或流散列运算
class Program
{
static void Main(string[] args)
{
string str = "Hello World";
HashAlgorithm hashAlgorithm = HashAlgorithm.Create(HashAlgorithmType.SHA1);
byte[] data = Encoding.Default.GetBytes(str);
byte[] digest = hashAlgorithm.ComputeHash(data);
foreach (byte b in digest)
{
Console.Write("{0:X}",b);
}
Console.ReadKey();
}
}
public class HashAlgorithmType
{
public const string SHA1 = "SHA1";
public const string SHA256 = "SHA256";
public const string SHA384 = "SHA384";
public const string SHA512 = "SHA512";
public const string MD5 = "MD5";
}
□ 密匙散列运算
string key = "secret key";
byte[] data = Encoding.Default.GetBytes(key);
KeyedHashAlgorithm kha = new HMACSHA1();
byte[] digest = kha.ComputeHash(data);
foreach (byte b in digest)
{
Console.Write("{0:x}",b);
}
对称加密和解密
SymmetricAlgorithm
DES
DESCryptoServiceProvider
TripleDES
TripleDESCryptoServiceProvider
Rijndael
RijindaelManaged
RC2
RC2CryptoServiceProvider
IV:Initialization vector初始化向量:
-为了解决加密字符串加密后仍然有重复部分,引入IV,加密字符串即使有重复,也会被打乱。
-IV值可以随意指定,但长度固定,通常为64位byte类型
-密匙长度也是固定的,通常为128位或196位byte类型
使用Encoding类将字符串转换为byte[]:
-如果使用UTF8,会变长编码
加密解密方法:
-加密方法:CreateEncryptor(),返回ICryptoTransform接口类型
-解密方法:CreateDecryptor(),返回ICrtyptoTransform接口类型
明文流和加密流的转换:
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
class Program
{
static void Main(string[] args)
{
#region 对称加密和解密
string key = "secret key";
string str = "Hello World";
//加密
string encryptedText = SymmetricCryptoHelper.Encrypt(str, key);
Console.WriteLine(encryptedText);
//解密
string clearText = SymmetricCryptoHelper.Decrypt(encryptedText, key);
Console.WriteLine(clearText);
Console.ReadKey();
#endregion
}
}
//对称加密帮助类
public class SymmetricCryptoHelper
{
private ICryptoTransform encryptor; //加密器对象
private ICryptoTransform decryptor; //解密器对象
private const int BufferSize = 1024;
public SymmetricCryptoHelper(string algorithmName, byte[] key)
{
SymmetricAlgorithm provider = SymmetricAlgorithm.Create(algorithmName);
provider.Key = key;
provider.IV = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
encryptor = provider.CreateEncryptor();
decryptor = provider.CreateDecryptor();
}
public SymmetricCryptoHelper(byte[] key) : this("TripleDES", key){}
//加密算法
public string Encrypt(string clearText)
{
//创建明文流
byte[] clearBuffer = Encoding.UTF8.GetBytes(clearText);
//byte[] clearBuffer = Encoding.Default.GetBytes(clearText);
MemoryStream clearStream = new MemoryStream(clearBuffer);
//创建空的密文流
MemoryStream encryptedStream = new MemoryStream();
//明文流和密文流转换流,准备写到密文流中
CryptoStream cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write);
int bytesRead = 0;
byte[] buffer = new byte[BufferSize];
do
{
//读取明文流到buffer中
bytesRead = clearStream.Read(buffer, 0, BufferSize);
//通过CryptoStream将buffer中的明文流字节数组写到明文流中
cryptoStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
cryptoStream.FlushFinalBlock();
//获取加密后的字节数组
buffer = encryptedStream.ToArray();
//将加密后的字节数组转换成字符串
string encryptedText = Convert.ToBase64String(buffer);
return encryptedText;
}
//解密算法
public string Decrypt(string encryptedText)
{
//把加密字符串转换为加密字节数组
byte[] encryptedBuffer = Convert.FromBase64String(encryptedText);
//创建密文流
Stream encryptedStream = new MemoryStream(encryptedBuffer);
//创建空的明文流
MemoryStream clearStream = new MemoryStream();
//创建明文流和密文流的转化流,读取密文流
CryptoStream cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read);
int bytesRead = 0;
byte[] buffer = new byte[BufferSize];
do
{
//通过CryptoStream读取密文流到Buffer
bytesRead = cryptoStream.Read(buffer, 0, BufferSize);
//把Buffer中的密文流写到明文流中
clearStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
//将明文流转换成字节数组
buffer = clearStream.GetBuffer();
string clearText = Encoding.UTF8.GetString(buffer, 0, (int)clearStream.Length);
//string clearText = Encoding.Default.GetString(buffer, 0, (int)clearStream.Length);
return clearText;
}
//密匙加密
public static string Encrypt(string clearText, string key)
{
byte[] keyData = new byte[16]; //TripleDES密匙固定长度为16个字节
//把密匙字符串转换成字节数组
byte[] sourceData = Encoding.Default.GetBytes(key);
int copyBytes = 16;
if (sourceData.Length < 16)
{
copyBytes = sourceData.Length;
}
//把密匙数组复制到keyData字节数组中
Array.Copy(sourceData,keyData,copyBytes);
SymmetricCryptoHelper helper = new SymmetricCryptoHelper(keyData);
return helper.Encrypt(clearText);
}
//密匙解密
public static string Decrypt(string encryptedText, string key)
{
byte[] keyData = new byte[16];
byte[] sourceData = Encoding.Default.GetBytes(key);
int copyBytes = 16;
if (sourceData.Length < 16)
{
copyBytes = sourceData.Length;
}
Array.Copy(sourceData,keyData,copyBytes);
SymmetricCryptoHelper helper = new SymmetricCryptoHelper(keyData);
return helper.Decrypt(encryptedText);
}
}
非对称加密
AsymmetricAlgorithm
RSA
RSACryptoServiceProvider
DSA
DSACryptoServiceProvider:只能进行认证模式,即数字签名
对称加密中的密匙:
密匙为由开发者设定的字符串
非对称加密中的密匙:
● 通常是自动生成,不同的算法有不同的密匙格式
● 在创建RSACryptoServiceProvider实例时,会自动创建一个公/私密匙对。在实例上调用ToXmlString()方法获得。
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
string publicPrivate = provider.ToXmlString(true);//获得公/私匙对
//string publicOnly = provider.ToXmlString(false); //只获得公匙
Console.Write(publicPrivate);
Console.ReadKey();
□ 非对称加密帮助类
//非对称加密帮助类
public class RSACryptoHelper
{
//加密
public static string Encrypt(string publicKeyXml, string plainText)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(publicKeyXml); //使用公匙初始化对象
byte[] plainData = Encoding.Default.GetBytes(plainText);
byte[] encryptedData = provider.Encrypt(plainData, true);
return Convert.ToBase64String(encryptedData);
}
//解密
public static string Decrypt(string privateKeyXml, string encryptedText)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(privateKeyXml);
byte[] encryptedData = Convert.FromBase64String(encryptedText);
byte[] plainData = provider.Decrypt(encryptedData, true);
string plainText = Encoding.Default.GetString(plainData);
return plainText;
}
}
数字签名
RSACryptoServiceProvider或DSACryptoServiceProvider
SignData()对摘要进行签名,并返回签名后的摘要。
VerifyData()得出本地摘要,并解密传递进来的原始摘要,对比返回bool类型结果。
□ 数字签名帮助类
public class RSACryptoHelper
{
public static string SignData(string plainText, string privateKeyXml)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(privateKeyXml);
byte[] plainData = Encoding.Default.GetBytes(plainText);
//设置获取摘要的算法
HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
//获取签名过的摘要,是使用私匙加密过的摘要
byte[] signedDigest = provider.SignData(plainData, sha1);
return Convert.ToBase64String(signedDigest);
}
public static bool VerifyData(string plainText, string signature, string publicKeyXml)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(publicKeyXml);
byte[] plainData = Encoding.Default.GetBytes(plainText);
byte[] signedDigest = Convert.FromBase64String(signature);
HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
bool isDataIntact = provider.VerifyData(plainData, sha1, signedDigest);
return isDataIntact;
}
//使用SingnHash
public static string SignData2(string plainText, string privateKeyXml)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(privateKeyXml);
byte[] plainData = Encoding.Default.GetBytes(plainText);
//设置获取摘要的算法
HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
//获得原始摘要
byte[] digestData = sha1.ComputeHash(plainData);
//对元素摘要进行签名
byte[] signedDigest = provider.SignHash(digestData, "SHA1");
return Convert.ToBase64String(signedDigest);
}
//使用VerifyHash
public static bool VerifyData2(string plainText, string signedDigest, string publicKeyXml)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(publicKeyXml);
byte[] plainData = Encoding.Default.GetBytes("SHA1");
byte[] signedDigestData = Convert.FromBase64String(signedDigest);
//获得本地摘要
HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");
byte[] digest = sha1.ComputeHash(plainData);
//解密签名
bool isDataIntact = provider.VerifyHash(digest, "SHA1", signedDigestData);
return isDataIntact;
}
}
参考资料:
※ 《.NET之美》--张子阳,感谢写了这么好的书!