C#加密知识(Windows数据保护、对称加密、非对称加密等)

.NET的加密方式有以下几种
1.Windows数据保护
特点:管理秘钥数量是0,速度快,由用户的密码决定强度,备注:使用隐式生成的密钥对字节数组进行加密和解密。
以下代码简单演示了加密和解密的过程,注意要添加引用System.Security.dll

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

 byte[] original = { 1, 2, 3, 4, 5, 6 };
                DataProtectionScope scope = DataProtectionScope.CurrentUser;
                byte[] encrypted = ProtectedData.Protect(original, null, scope);//加密
                Console.WriteLine("encrypted:");
                foreach (byte b in encrypted)
                {
                    Console.WriteLine(b.ToString() + " ");  
                }

                byte[] decrypted = ProtectedData.Unprotect(encrypted, null, scope);//解密
                Console.WriteLine("decrypted:" + BitConverter.ToString(decrypted));

DataProtectionScope可以选择CurrentUser或者LocalMachine。若使用CurrentUser则密钥会从当前登录用户的凭据中生成,若使用LocalMachine,则会使用一个本机范围的密钥,而该密钥对所有用户共享,所以一般使用CurrentUser。
2.散列法(Hash加密算法)
散列法提供一种单向加密的方式,也就是说无法根据密文推导出明文,非常适用于在数据库中存储密码。有MD5和SHA256的ComputeHash方法可以生成散列码。
以下代码简单演示了加密的过程:

byte[] data = System.Text.Encoding.UTF8.GetBytes("stRhon%pword");
                byte[] hash = SHA256.Create().ComputeHash(data);
                foreach (byte c in hash)
                {
                    Console.WriteLine(c.ToString() + " "); 
                }

以下是安全等级由低到高的排序,运算速度有快到慢。
MD(16) → SHA1(20) → SHA256(32) → SHA384(48) → SHA512(64)
如果要存储密码或其他稿安全等级的敏感数据,至少使用SHA256。
注意:它们需要强制采用高密码强度的策略来防止字典攻击的威胁,例如采用Rfc2898DeriveBytes类

3.对称加密
对称加密算法在加密和解密时使用相同的密钥,Framework提供4种对称加密算法如Rijindael,Aes。

 #region 对称加密/解密算法
                byte[] key = { 145, 12, 32, 245, 98, 132, 98, 214, 6, 77, 131, 44, 221, 3, 9, 50 };//密钥Rijndael和Aes支持16字节,24字节,和32字节的对称密钥长度
                byte[] iv = { 15, 122, 132, 5, 93, 198, 44, 31, 9, 39, 241, 49, 250, 188, 80, 7 };//初始化向量,密码的一部分,传输加密信息是,IV以明文的方式
                byte[] data = { 1, 2, 3, 4, 5, 6 };//这些是要加密的数据
                using (SymmetricAlgorithm algorithm = Aes.Create())
                using (ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv))
                using (Stream f = File.Create("encrypted.bin"))
                using (Stream c = new CryptoStream(f, encryptor, CryptoStreamMode.Write))
                    c.Write(data, 0, data.Length);

                //解密
                byte[] key2 = { 145, 12, 32, 245, 98, 132, 98, 214, 6, 77, 131, 44, 221, 3, 9, 50 };//密钥Rijndael和Aes支持16字节,24字节,和32字节的对称密钥长度
                byte[] iv2 = { 15, 122, 132, 5, 93, 198, 44, 31, 9, 39, 241, 49, 250, 188, 80, 7 };//初始化向量,密码的一部分,传输加密信息是,IV以明文的方式
                byte[] decrypted = new byte[6];
                using (SymmetricAlgorithm algorithm2 = Aes.Create())
                using (ICryptoTransform decryptor = algorithm2.CreateDecryptor(key2, iv2))
                using (Stream f2 = File.OpenRead("encrypted.bin"))
                using (Stream c2 = new CryptoStream(f2, decryptor, CryptoStreamMode.Read))
                    for (int b; (b = c2.ReadByte()) >   0; )
                        Console.WriteLine(b + " ");

                Console.ReadLine();
                #endregion

可以使用System.Cryptography命名空间下的RandomNumberGenerator来生成随机密钥或IV,具有密码学强度。

byte[] key = new byte[16];
byte[] IV = new byte[16];
RandomNumberGenerator rand= RandomNumberGenerator.Create();
rand.GetBytes(key);
rand.GetBytes(IV);

3.1 内存加密
字节数组的形式演示:

 public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
        {
            using(Aes algorithm=Aes.Create())
            using(ICryptoTransform encryptor = algorithm.CreateEncryptor(key,iv))
            return Crypt(data,encryptor);

        }
        public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
        {
            using(Aes algorithm=Aes.Create())
            using(ICryptoTransform decryptor = algorithm.CreateDecryptor(key,iv))
                return Crypt(data, decryptor);
        }
        static byte[] Crypt(byte[] data, ICryptoTransform cryptor)
        {
            MemoryStream m = new MemoryStream();
            using (Stream c = new CryptoStream(m, cryptor, CryptoStreamMode.Write))
                c.Write(data, 0, data.Length);
            return m.ToArray();
        }
 #region 内存加密
  byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6, 4, 5, 6, 8 };//要加密的对象
                byte[] kv = new byte[16];
                byte[] iv = new byte[16];
                RandomNumberGenerator.Create().GetBytes(kv);
                RandomNumberGenerator.Create().GetBytes(iv);//kv和iv最好不要相同
                byte[] encrypted = Encrypt(data, kv, iv);
                Console.WriteLine("encrpted: ");
                Console.WriteLine(BitConverter.ToString(encrypted));

                byte[] decrypted = Decrypt(encrypted, kv, iv);
                Console.WriteLine("decrpted: ");
                Console.WriteLine(BitConverter.ToString(decrypted));
                Console.ReadLine();
                #endregion

4.非对称加密
非对称加密需要专门制作一对密钥,这个密钥包含一个公钥和私钥,其中公钥加密信息,私钥解密信息。
注意:公钥加密算法要求加密的信息小于密钥的长度,更适合加密少量数据,如果试图加密的数据大于密钥长度的一半,则会抛出异常。
4.1 RSA类
.NET Framework 提供很多非对称加密算法,其中以RSA算法最为流行,如下所示。

 #region 非对称加密
                byte[] data = { 1, 2, 3, 4, 5 };
                using (var ras = new RSACryptoServiceProvider())
                {
                    /* 
                     * 并没有指定公钥和私钥,加密程序默认使用1024位长度自动生成一个密钥对 
                     * 当然也可以设置 var ras = new RSACryptoServiceProvider(2048)             
                     */

                    byte[] encrypted = ras.Encrypt(data, true);
                    byte[] decrypted = ras.Decrypt(encrypted, true);
                    Console.WriteLine(BitConverter.ToString(encrypted));
                    Console.WriteLine(BitConverter.ToString(decrypted));
                }

                #endregion
//创建一个密钥对,并将其存储到磁盘上
                using (var rsa = new RSACryptoServiceProvider())
                {
                  /*没有现成的密钥对,因此在调用ToXmlString会强制生成一个新的密钥对*/
                    File.WriteAllText("PublicKeyOnly.xml", rsa.ToXmlString(false));//仅包含公钥
                    File.WriteAllText("PublicPrivate.xml", rsa.ToXmlString(true));
                }
                //以下是加载上述代码生成的密钥对,然后对信息进行加密和解密。
                byte[] data = Encoding.UTF8.GetBytes("123456789");
                string publicKeyOnly = File.ReadAllText("PublicKeyOnly.xml");
                string publicPrivate = File.ReadAllText("PublicPrivate.xml");
                byte[] encrypted, decrypted;
                using (var rsaPublicOnly = new RSACryptoServiceProvider())
                {
                    rsaPublicOnly.FromXmlString(publicKeyOnly);
                    encrypted = rsaPublicOnly.Encrypt(data, true);//加密
                }
                using (var rsaPublicPrivate = new RSACryptoServiceProvider())
                {
                    rsaPublicPrivate.FromXmlString(publicPrivate);
                    decrypted = rsaPublicPrivate.Decrypt(encrypted, true);//解密
                    Console.WriteLine(BitConverter.ToString(decrypted));
                }

4.2 数字签名
公钥算法可以对消息或文档进行数字签名。但这个散列值会用私钥进行加密从而防止伪造,而公钥用来验证这个数字签名。

byte[] data = Encoding.UTF8.GetBytes("Message to sign");
                byte[] publicKey;
                byte[] signnature;
                object hasher = SHA1.Create();
                using (var publicprivate = new RSACryptoServiceProvider())
                {
                    signnature = publicprivate.SignData(data, hasher);
                    publicKey = publicprivate.ExportCspBlob(false);// public key                   
                }
                using (var publicOnly = new RSACryptoServiceProvider())
                {
                    publicOnly.ImportCspBlob(publicKey);
                    Console.WriteLine(publicOnly.VerifyData(data,hasher,signnature));
                    data[0] = 0;
                    Console.WriteLine(publicOnly.VerifyData(data, hasher, signnature));
                    signnature = publicOnly.SignData(data, hasher);
                }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值