C#常用的加密解密方法

Posted change_from_now

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#常用的加密解密方法相关的知识,希望对你有一定的参考价值。

开篇

C#内置很多加密解密的方法,有MD5,SHA1,base64等。这里会简单介绍下这几个方法以及用法,不过不会深入研究每种加密方法的原理,高手请绕行。
这几个加密解密会分为两类说,一类是只有加密,没有解密类型的MD5,SHA1。此类加密常用在数据校验。一类是有加密,有解密类型的base64,DES,RSA。此类加密常用在数据传输。

数据校验型

MD5
Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)。
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
p.s.内容来自百度百科。

MD5主要是用来做数据校验的。拿网上下载软件来说,有很多软件在下载的时候都会提供一个MD5校验码,就是用来校验软件是否被他人修改过。还有就是用户账号系统,用户注册后,数据库存储的不是明文密码,而是MD5码。

测试代码
演示如何获取一个字符串的MD5 hash以及校验MD5 hash。

using System;
using System.Security.Cryptography;
using System.Text;

namespace MD5Test
{
    class Program
    {
        static void Main(string[] args)
        {
            string source = "Happy Birthday!";

            string hash = GetMd5Hash(source);
            Console.WriteLine("The MD5 hash of " + source + " is: " + hash);

            Console.WriteLine("Verifying the hash ...");

            if (VerifyMd5Hash(source, hash))
            {
                Console.WriteLine("The hashes are the same.");
            }
            else
            {
                Console.WriteLine("The hashes are not same.");
            }

            Console.ReadKey();
        }

        /// <summary>
        /// 获取一个字符串的32位16进制字符串格式MD5码
        /// </summary>
        /// <param name="input">原字符串</param>
        /// <returns></returns>
        static string GetMd5Hash(string input)
        {
            MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();

            byte[] inputBytes = Encoding.Default.GetBytes(input);

            byte[] data = md5Hasher.ComputeHash(inputBytes);

            StringBuilder sBuilder = new StringBuilder();

            //将data中的每个字符都转换为16进制的
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            return sBuilder.ToString();
        }

        /// <summary>
        /// 验证Md5 hash
        /// </summary>
        /// <param name="input">原字符串</param>
        /// <param name="hash">原字符串的md5码</param>
        /// <returns></returns>
        static bool VerifyMd5Hash(string input, string hash)
        {
            string hashOfInput = GetMd5Hash(input);

            StringComparer comparer = StringComparer.OrdinalIgnoreCase;

            if (0 == comparer.Compare(hashOfInput, hash))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

SHA1
安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准 (Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。 SHA1有如下特性:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要,(但会有1x10 ^ 48分之一的机率出现相同的消息摘要,一般使用时忽略)。
p.s.内容摘自百度百科

sha1和md5的用途类似,用来验证数据。

测试代码
演示通过sha1获取一个字符串的hash 并作验证。

using System;
using System.Security.Cryptography;
using System.Text;

namespace SHA1Test
{
    class Program
    {
        static void Main(string[] args)
        {
            string source = "Happy Birthday!";
            string hash = GetSha1Hash(source);
            Console.WriteLine("The SHA1 Hash of " + source + " is: " + hash);

            Console.WriteLine("Verifying the hash....");

            if (VerifySha1Hash(source, hash))
            {
                Console.WriteLine("The hashes are the same...");
            }
            else
            {
                Console.WriteLine("The Hashes are not same...");
            }
            Console.ReadKey();
        }

        static string GetSha1Hash(string input)
        {
            byte[] inputBytes = Encoding.Default.GetBytes(input);

            SHA1 sha = new SHA1CryptoServiceProvider();

            byte[] result = sha.ComputeHash(inputBytes);

            StringBuilder sBuilder = new StringBuilder();

            for (int i = 0; i < result.Length; i++)
            {
                sBuilder.Append(result[i].ToString("x2"));
            }

            return sBuilder.ToString();
        }

        static bool VerifySha1Hash(string input, string hash)
        {
            string hashOfInput = GetSha1Hash(input);

            StringComparer comparer = StringComparer.OrdinalIgnoreCase;

            if (0 == comparer.Compare(hashOfInput, hash))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

加密数据传输

这个类型的加密可以解密,主要用来把加密后的数据进行传输,对方收到数据后进行解密。

base64
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到
p.s.内容摘自百度百科。

测试代码

using System;
using System.Text;

namespace Base64Test
{
    class Program
    {
        static void Main(string[] args)
        {
            string source = "Happy Birthday!";
            string encryStr = EncryptBase64(source);

            Console.WriteLine("原数据:" + source);

            Console.WriteLine("加密后的数据:" + encryStr);

            string decryStr = DecryptBase64(encryStr);

            Console.WriteLine("解密后的数据:" + decryStr);

            Console.ReadKey();
        }

        /// <summary>
        /// base64加密
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        static string EncryptBase64(string input)
        {
            byte[] inputBytes = Encoding.UTF8.GetBytes(input);

            return Convert.ToBase64String(inputBytes);
        }

        /// <summary>
        /// base64解密
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        static string DecryptBase64(string input)
        {
            byte[] inputBytes = Convert.FromBase64String(input);

            return Encoding.UTF8.GetString(inputBytes);
        }
    }
}

base64的加密解密规则比较固定,所以破解也容易,在网上找个在线base64解密就可以破解加密后的内容,所以敏感数据不推荐使用base64。

DES
对称加密算法
DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DSA),已与作为标准的DES区分开来。
p.s.内容摘自百度百科

测试代码

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace DESTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string key = "The_key!";

            string source = "Happy Birthday!";

            Console.WriteLine("Source  string: " + source);

            string encryptStr = EncryptDES(source, key);
            Console.WriteLine("Encrypt string: " + encryptStr);

            string decryptStr = DecryptDES(encryptStr, key);
            Console.WriteLine("Decrypt string: " + decryptStr);

            Console.ReadKey();
        }

        /// <summary>
        /// 进行DES加密
        /// </summary>
        /// <param name="pToEncrypt">要加密的字符串</param>
        /// <param name="key">密钥,必须为8位</param>
        /// <returns>以Base64格式返回的加密字符串</returns>
        static string EncryptDES(string pToEncrypt, string sKey)
        {
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                byte[] inputByteArray = Encoding.UTF8.GetBytes(pToEncrypt);
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                }
                string str = Convert.ToBase64String(ms.ToArray());
                ms.Close();
                return str;
            }
        }

        static string DecryptDES(string pToDecrypt, string sKey)
        {
            byte[] inputByteArray = Convert.FromBase64String(pToDecrypt);
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                MemoryStream ms = new MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                }
                string str = Encoding.UTF8.GetString(ms.ToArray());
                ms.Close();
                return str;
            }
        }
    }
}

DES加密解密需要提供一个key,双方可以约定一个共同的key使用。

RSA
非对称加密算法
大名鼎鼎的RSA算法 ->_->,此处没有介绍,自行百度,Google。
只说明,RSA需要两把key,即密钥,一个public key进行加密,一个private key用来解密。也可称为公钥,私钥。
测试代码
演示如何生成公钥,私钥,以及使用公钥加密,私钥解密。

using System;
using System.Security.Cryptography;
using System.Text;

namespace RSATest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                UnicodeEncoding byteConverter = new UnicodeEncoding();

                byte[] dataToEncrypt = byteConverter.GetBytes("Happy Birthday!");
                byte[] encryptedData;
                byte[] decryptedData;

                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    //数据加密 获取public key信息
                    //(using RSACryptoServiceProvider.ExportParameters(false)
                    encryptedData = EncryptRSA(dataToEncrypt, rsa.ExportParameters(false), false);

                    //数据解密,获取private key信息
                    //(using RSACryptoServiceProvider.ExportParameters(true))
                    decryptedData = DecryptRSA(encryptedData, rsa.ExportParameters(true), false);
                    Console.WriteLine("Decrypted String: " + byteConverter.GetString(decryptedData));
                }

                Console.ReadKey();
            }
            catch (ArgumentNullException)
            {
               Console.WriteLine("Encryption failed!");
            }
        }

        /// <summary>
        /// 加密数据
        /// </summary>
        /// <param name="dataToEncrypt">要加密的byte数组</param>
        /// <param name="rsaKeyInfo"></param>
        /// <param name="doOAEPadding"></param>
        /// <returns></returns>
        static byte[] EncryptRSA(byte[] dataToEncrypt, RSAParameters rsaKeyInfo, bool doOAEPadding)
        {
            try
            {
                byte[] encryptedData;

                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    //导入RSA key信息,这里导入公钥信息
                    rsa.ImportParameters(rsaKeyInfo);

                    //加密传入的byte数组,并指定OAEP padding
                    //OAEP padding只可用在微软Window xp及以后的系统中
                    encryptedData = rsa.Encrypt(dataToEncrypt, doOAEPadding);
                }

                return encryptedData;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        /// <summary>
        /// 解密数据
        /// </summary>
        /// <param name="dataToDecrypt"></param>
        /// <param name="rsaKeyInfo"></param>
        /// <param name="doOAEPPadding"></param>
        /// <returns></returns>
        static byte[] DecryptRSA(byte[] dataToDecrypt, RSAParameters rsaKeyInfo, bool doOAEPPadding)
        {
            try
            {
                byte[] decryptedData;

                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    rsa.ImportParameters(rsaKeyInfo);

                    decryptedData = rsa.Decrypt(dataToDecrypt, doOAEPPadding);
                }

                return decryptedData;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }
    }
}

网上他人写的使用xml形式的密钥加密解密

–生成xml格式的密钥
生成的密钥会以xml的格式放在你工程bin\Debug目录下。

        /// <summary>
        /// 生成RSA public key private key
        /// </summary>
        public static void GenerateRSAKey()
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            using (StreamWriter writer = new StreamWriter("Privatekey.xml"))
            {
                writer.WriteLine(rsa.ToXmlString(true));
            }

            using (StreamWriter writer = new StreamWriter("PublicKey.xml"))
            {
                 writer.WriteLine(rsa.ToXmlString(false));
            }
        }

–使用xml格式密钥加密解密
方便测试就直接把public key private key写在代码里了

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace RSAXmlTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string source = "Happy Birthday!";
            string encryptedStr = EncryptRSA("", source);
            Console.WriteLine("Encrypted String: = " + encryptedStr);
            string decryptedStr = DecryptRSA("", encryptedStr);
            Console.WriteLine("Decrypted String: = " + decryptedStr);

            Console.ReadKey();
        }

        /// <summary>
        /// 生成RSA public key private key
        /// </summary>
        public static void GenerateRSAKey()
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            using (StreamWriter writer = new StreamWriter("Privatekey.xml"))
            {
                writer.WriteLine(rsa.ToXmlString(true));
            }

            using (StreamWriter writer = new StreamWriter("PublicKey.xml"))
            {
                writer.WriteLine(rsa.ToXmlString(false));
            }
        }

        /// <summary>
        /// RSA Encrypt
        /// </summary>
        /// <param name="publickey"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string EncryptRSA(string publickey, string content)
        {
            publickey = @"<RSAKeyValue><Modulus>pHfhtj8f/50PMyRq1MjcmbOSvrIIXRihzLTmr
ZKyo3o9ID6XEc5p4Tyjz9fbwYc8asfAF4GYJ3C/hPLvMST9M9WMKnT+sEsItG6jSVTSM0N580ORIusJRsoVBB
gqczr0hNvaGmDxOvGeomqF1P/8tNQzY8L3a/szdrOSa0v6kW0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(publickey);
            var cipherBytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);

            return Convert.ToBase64String(cipherBytes);

        }

        public static string DecryptRSA(string privatekey, string content)
        {
            privatekey = @"<RSAKeyValue><Modulus>pHfhtj8f/50PMyRq1MjcmbOSvrIIXRihzLTmrZKyo3o9ID6XEc5p4Tyjz9fb
wYc8asfAF4GYJ3C/hPLvMST9M9WMKnT+sEsItG6jSVTSM0N580ORIusJRsoVBBgqczr0hNvaGmDxOvGeomqF1P/8tNQzY8L3a/szdrOSa0v6k
W0=</Modulus><Exponent>AQAB</Exponent><P>yDpRsxc+bee57XNa6mb3it9rkmqdWMn5H/8Q0Ql2/quFwPhU6DFxSAx02ueijLkAN4qN
31ggxLi0fFMYmqKFqw==</P><Q>0kem35FBODvc83JpxeksQ0BJ4x/qV1FPZnEeTuP9ckEjv5+WeKVnWv3Phx/WDDEC+N6pYX+NZYYOiTjjL+
l9Rw==</Q><DP>g0Z5OkoLDFPZeu0etoA73DkPdjegYg5J38iDZgomkmIyl4o5YOLJussv8jXcRRcmJUQaMEy/bzsKWljA0OGtcQ==</DP><DQ>OQQoo
TIXhxHkRTZeq8UftVR3NFhxCCAJ8XL2jtmO3S4AbXLuL+RZc/iiDrd5KHEZpzVopAEb680/n8GHCHS8/Q==</DQ><InverseQ>H0C+3yD6o+hBz
4BrMe/e5cxrIXMe+zOEHdQ/wgwswdZz8YHLe3Y9maOcyWPMKNCKkFIaMQ4D6zaNh7h8JQyFDQ==</InverseQ><D>ChGdmH1K2M8Yh1M01Ljeg7
mYduMKKHDoNVKwRwx5GHfUvPmeYNexm1MNqen9wsS9vSfKqcwkSlELvviEdKf4D3z8n2TLTaHhHCsTFC2VTM75ar+g0rYL34ofa25hhZOzlKLrB
vRk3FBFPKO2ekyEVEQojdfPJUOUOr/UfKHm6J0=</D></RSAKeyValue>";

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(privatekey);
            var cipherbytes = rsa.Decrypt(Convert.FromBase64String(content), false);

            return Encoding.UTF8.GetString(cipherbytes);
        }
    }
}

以上是关于C#常用的加密解密方法的主要内容,如果未能解决你的问题,请参考以下文章

C#代码加密字符串,与SQL加密结果不一致

C# 常用加密方式

用C#实现MD5的加密(转载)

C# MD5 加密

C# MD5 加密

Asp.net的MD5加密,可怎么解密呢?(C#)