C# 加密总结 一些常见的加密方法

一 散列数据 代码如下:

[csharp][/csharp]

view plaincopyprint?

  1. private static string CalculateSHA512Hash(string input)
  2.         {
  3.             byte[] inputBytes = Encoding.UTF8.GetBytes(input);
  4.             SHA512Managed sha512 = new SHA512Managed();
  5.             byte[] outputBytes = sha512.ComputeHash(inputBytes);
  6.             return Convert.ToBase64String(outputBytes);
  7.         }

原始散列对于彩虹表来说也存在漏洞,在彩虹表中,表内的每一条记录都是一串明文对应一种加密算法生成的一串密文。加盐就是指在密码中加入一个盐,这样可以提高密码散列的安全性。修改后的代码如下:

[csharp][/csharp]

view plaincopyprint?

  1. private static string CalculateSHA512Hash(string input,string salt)
  2.       {
  3.           byte[] saltBytes = Convert.FromBase64String(salt);
  4.           byte[] inputBytes = Encoding.UTF8.GetBytes(input);
  5.           byte[] inputWithSaltBytes = new byte[saltBytes.Length + inputBytes.Length];
  6.           Array.Copy(inputBytes, 0, inputWithSaltBytes, 0, inputBytes.Length);
  7.           Array.Copy(saltBytes, 0, inputWithSaltBytes, inputBytes.Length, saltBytes.Length);
  8.           SHA512Managed sha512 = new SHA512Managed();
  9.           byte[] outputBytes = sha512.ComputeHash(inputWithSaltBytes);
  10.           return Convert.ToBase64String(outputBytes);
  11.       }
  12.       private static string GetSalt(int minSaltSize, int maxSaltSize)
  13.       {
  14.           Random random = new Random();
  15.           int saltSize = random.Next(minSaltSize, maxSaltSize);
  16.           byte[] saltBytes = new byte[saltSize];
  17.           RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  18.           rng.GetNonZeroBytes(saltBytes);
  19.           return Convert.ToBase64String(saltBytes);
  20.       }

二 对称加密

[csharp][/csharp]

view plaincopyprint?

  1. private static string Encrypt(string input, byte[] key, byte[] iv)
  2.       {
  3.           byte[] inputBytes = Encoding.UTF8.GetBytes(input);
  4.           RijndaelManaged rijndael = new RijndaelManaged();
  5.           ICryptoTransform transform = rijndael.CreateEncryptor(key, iv);
  6.           byte[] encrytData = null;
  7.           using (MemoryStream outputStream = new MemoryStream())
  8.           {
  9.               using (CryptoStream inputStream = new CryptoStream(outputStream, transform, CryptoStreamMode.Write))
  10.               {
  11.                   inputStream.Write(inputBytes, 0, inputBytes.Length);
  12.                   inputStream.FlushFinalBlock();
  13.                   encrytData = outputStream.ToArray();
  14.               }
  15.           }
  16.           return Convert.ToBase64String(encrytData);
  17.       }
  18.       private static string Decrypt(string input, byte[] key, byte[] iv)
  19.       {
  20.           byte[] inputBytes=Convert.FromBase64String(input);
  21.           RijndaelManaged rijndael = new RijndaelManaged();
  22.           ICryptoTransform transform = rijndael.CreateDecryptor(key, iv);
  23.           byte[] decryptByte;
  24.           using (MemoryStream outputStream=new MemoryStream())
  25.           {
  26.               using (CryptoStream inputStream=new CryptoStream(outputStream,transform,CryptoStreamMode.Write))
  27.               {
  28.                   inputStream.Write(inputBytes, 0, inputBytes.Length);
  29.                   inputStream.FlushFinalBlock();
  30.                   decryptByte = outputStream.ToArray();
  31.               }
  32.           }
  33.           return Encoding.UTF8.GetString(decryptByte);
  34.       }
  35.       private static void GetKeyAndIVFromPasswordAndSalt(string password, byte[] salt, SymmetricAlgorithm symmetricAlgorithm,
  36.           ref byte[] key, ref byte[] iv)
  37.       {
  38.           Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt);
  39.           key = rfc2898DeriveBytes.GetBytes(symmetricAlgorithm.KeySize / 8);
  40.           iv = rfc2898DeriveBytes.GetBytes(symmetricAlgorithm.BlockSize / 8);
  41.       }
  42.       private static string GetSalt(int minSaltSize, int maxSaltSize)
  43.       {
  44.           Random random = new Random();
  45.           int saltSize = random.Next(minSaltSize, maxSaltSize);
  46.           byte[] saltBytes = new byte[saltSize];
  47.           RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  48.           rng.GetNonZeroBytes(saltBytes);
  49.           return Convert.ToBase64String(saltBytes);
  50.       }

调用方式:
byte[] salt = Convert.FromBase64String(GetSalt(9, 18));
string password = “Password”;
byte[] key=new byte[0];
byte[] iv = new byte[0];
GetKeyAndIVFromPasswordAndSalt(password,salt, new RijndaelManaged(), ref key, ref iv);
string input = “Wrox Press”;
string encrytText = Encrypt(input, key, iv);
Console.WriteLine(encrytText);
string decryptText=Decrypt(encrytText,key,iv);
Console.WriteLine(decryptText);

只是简单的加密和解密数据是不够的,我们还需要确保数据不被改变,我们可以创建一个消息认证代码来生成一个加密的散列。

[csharp][/csharp]

view plaincopyprint?

  1. private static string GenerateMac(string input, byte[] key)
  2.       {
  3.           HMACSHA512 hmac = new HMACSHA512(key);
  4.           byte[] data= hmac.ComputeHash(Convert.FromBase64String(input));
  5.           return Convert.ToBase64String(data);
  6.       }
  7.       static bool IsMacValid(string input, byte[] key, string savedMac)
  8.       {
  9.           string recalculateMac = GenerateMac(input, key);
  10.           return recalculateMac.Equals(savedMac);
  11.       }

例如我们对数据库中LicenseNumber加密,那么我们就必须修改表结构,修改后如图:

非对称加密:

[csharp][/csharp]

view plaincopyprint?

  1. private static string Encrypt(string input, string publickey)
  2.        {
  3.            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
  4.            rsa.FromXmlString(publickey);
  5.            byte[] encryptData = rsa.Encrypt(Encoding.UTF8.GetBytes(input), true);
  6.            return Convert.ToBase64String(encryptData);
  7.        }
  8.        private static string Decrypt(string input, string privatekey)
  9.        {
  10.            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
  11.            rsa.FromXmlString(privatekey);
  12.            byte[] dencryptData = rsa.Decrypt(Convert.FromBase64String(input), true);
  13.            return Encoding.UTF8.GetString(dencryptData);
  14.        }
  15.        private static void GetkeyXml(out string publicKey, out string privateKey)
  16.        {
  17.            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
  18.            publicKey = rsa.ToXmlString(false);
  19.            privateKey = rsa.ToXmlString(true);
  20.        }

证书加密:

[csharp][/csharp]

view plaincopyprint?

  1. static byte[] SignData(byte[] clearText, X509Certificate2 signingCertificate)
  2.       {
  3.           ContentInfo contentInfo = new ContentInfo(clearText);
  4.           CmsSigner signer = new CmsSigner(signingCertificate);
  5.           SignedCms signedCms = new SignedCms(contentInfo);
  6.           signedCms.ComputeSignature(signer);
  7.           return signedCms.Encode();
  8.       }
  9.       static byte[] ValidateSignatureAndExtractContent(byte[] signedCmsAsBytes, ICollection<string> signingSubjects)
  10.       {
  11.           SignedCms signedCms = new SignedCms();
  12.           signedCms.Decode(signedCmsAsBytes);
  13.           signedCms.CheckSignature(true);
  14.           foreach (SignerInfo signerInfo in signedCms.SignerInfos)
  15.           {
  16.               X509Certificate2 signingCertificate = signerInfo.Certificate;
  17.               signingSubjects.Add(signingCertificate.Subject);
  18.           }
  19.           return signedCms.ContentInfo.Content;
  20.       }
  21.       static byte[] EncryptWithCertificate(byte[] clearText, X509Certificate2 certificate)
  22.       {
  23.           ContentInfo contentInfo = new ContentInfo(clearText);
  24.           EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo);
  25.           CmsRecipient recipient = new CmsRecipient(certificate);
  26.           envelopedCms.Encrypt(recipient);
  27.           return envelopedCms.Encode();
  28.       }
  29.       static byte[] DecryptWithCertificate(byte[] cipherText)
  30.       {
  31.           EnvelopedCms envelopedCms = new EnvelopedCms();
  32.           envelopedCms.Decode(cipherText);
  33.           envelopedCms.Decrypt();
  34.           return envelopedCms.ContentInfo.Content;
  35.       }
  36.       static X509Certificate2 LoadCertificateFromFile(string filename)
  37.       {
  38.           X509Certificate2 certificate = new X509Certificate2();
  39.           certificate.Import(ReadBinaryFile(filename));
  40.           return certificate;
  41.       }
  42.       static byte[] ReadBinaryFile(string filename)
  43.       {
  44.           FileStream f = new FileStream(filename, FileMode.Open, FileAccess.Read);
  45.           int size = (int)f.Length;
  46.           byte[] data = new byte[size];
  47.           size = f.Read(data, 0, size);
  48.           f.Close();
  49.           return data;
  50.       }
  51.       private static X509Certificate2 GetCertificateBySubjectName(string subjectName)
  52.       {
  53.           X509Store myStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
  54.               myStore.Open(OpenFlags.ReadOnly);
  55.               X509Certificate2Collection certificateCollection = myStore.Certificates.Find(X509FindType.FindBySubjectName, subjectName, true);
  56.               X509Certificate2 myCertificate = certificateCollection[0];
  57.               if (myStore != null)
  58.                   myStore.Close();
  59.               return myCertificate;
  60.       }

调用方式:

string input = “Wrox Press”;
byte[] clearTextAsBytes = Encoding.UTF8.GetBytes(input);
X509Certificate2 serverPublicKeyCertificate = LoadCertificateFromFile(“IISExpress.cer”);
X509Certificate2 signingCertificate = GetCertificateBySubjectName(“test”);
byte[] signedClearText = SignData(clearTextAsBytes, signingCertificate);
byte[] encryptedAndSignedData = EncryptWithCertificate(signedClearText, serverPublicKeyCertificate);

byte[] encodedUnencryptedCms = DecryptWithCertificate(encryptedAndSignedData);
List<string> signingSubjects = new List<string>();
byte[] receivedClearText = ValidateSignatureAndExtractContent(encodedUnencryptedCms, signingSubjects);
string unecnryptedString = Encoding.UTF8.GetString(receivedClearText);
Console.ReadLine();

我的计算机是win8,这里并没有用什么企业级证书,作为测试,我是用win8中IIS来创建自签名证书,然后用mmc来管理证书(http://softbbs.zol.com.cn/1/20_1370.html),所以以上的GetCertificateBySubjectName方法需要修改如下:

private static X509Certificate2 GetCertificateBySubjectName(string subjectName)
{
X509Store myStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
myStore.Open(OpenFlags.ReadOnly);

X509Certificate2Collection certificateCollection = myStore.Certificates.Find(X509FindType.FindBySubjectName, subjectName, true);
X509Certificate2 myCertificate;
if (certificateCollection.Count > 0)
{
myCertificate = certificateCollection[0];
}
else
{
X509Certificate2[] array = new X509Certificate2[myStore.Certificates.Count];
myStore.Certificates.CopyTo(array, 0);
myCertificate = array.FirstOrDefault(x => x.FriendlyName.Equals(subjectName));
}
if (myStore != null)
myStore.Close();
return myCertificate;
}

标签