c#加密方式

一、c#中的对称加密概述 对称加密算法在加密和解密时使用相同的密钥。Framework提供了四种对称加密算法。AES、DES、Rijndael、RC2。 DES: 全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(

一、c#中的对称加密概述 

        对称加密算法在加密和解密时使用相同的密钥。Framework提供了四种对称加密算法。AES、DES、Rijndael、RC2。

        DES:全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。

        RC2:RC2是由著名密码学家Ron Rivest设计的一种传统对称分组加密算法,它可作为DES算法的建议替代算法。

        Rijndael:这个类从.NET Framework 1.0开始就已经存在了。

        Aes:这个类是在.NET Framework 3.5中引入的。

        这些算法中Rijndael算法是最优秀的。Rijndael即快速又安全。它拥有两个实现:

        Rijndael和Aes这两个实现几乎是等价的,但是Aes不允许通过更改块尺寸来削弱加密强度。CLR安全团队推荐使用Aes类。

        Rijndael和Aes支持16字节、24字节和32字节的对称密钥长度:这几种长度目前均认为是安全的。

        关于AES加密算法的细节,可参考下面这篇文章。

AES加密算法的详细介绍与实现_TimeShatter的博客-CSDN博客_aes加密AES简介高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图: 下面简单介绍下各个部分的作用与意义:明文P 没有经过加密的数据。密钥K 用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生https://blog.csdn.net/qq_28205153/article/details/55798628

二、加解密示例

//加密
byte[] key = { 99, 66, 33, 11, 8, 6,59,68,21,25,36,21,24,6,6,6 };
byte[] iv = { 99, 66, 33, 11,5,5,5,5,5,6,6,6,5,5,5,9 };
byte[] data = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
using (SymmetricAlgorithm symmetric = Aes.Create())
{
    using (ICryptoTransform tran = symmetric.CreateEncryptor(key, iv))
    {
        using (Stream f = File.Create("aes.txt"))
        {
            using (Stream c = new CryptoStream(f, tran, CryptoStreamMode.Write))
            {
                c.Write(data, 0, data.Length);
            }
        }
    }
}

//解密
using (SymmetricAlgorithm symmetric = Aes.Create())
{
    using (ICryptoTransform tran = symmetric.CreateDecryptor(key, iv))
    {
        using (Stream f = File.OpenRead("aes.txt"))
        {
            using (Stream c = new CryptoStream(f, tran, CryptoStreamMode.Read))
            {
                for(int b; (b=c.ReadByte())>-1;)
                {
                    Console.WriteLine(b + " ");
                }
            }
        }
    }
}

        如果使用错误的密钥进行解密,则CryptoStream会抛出CryptographicException,而捕获该异常是测试密钥是否正确的唯一途径。

        除了密钥之外,示例中还生成了一个初始化向量(Initialization Vector, IV)。这16字节的序列也是密码的一部分(和密钥相似),但它并不是保密的。当传输加密信息时,IV会以明文的方式进行传输(可能是在消息的头部进行传输),但每一段信息中其值都不相同。这样即使有些消息的未加密版本都是类似的,但是加密后的信息也会难以识别。

        如果无须IV的保护,可令16字节密钥和IV的值相同。但是,使用相同的IV发送多条消息会削弱密码的安全性并使破解的可能性大大增加。

        CryptoStream则像是管道工,它关注于流的处理。因此我们可以将Aes替换为另一种对称加密算法而仍旧使用CryptoStream。

        CryptoStream是双向的。因此可以使用CryptoStreamMode.Read来读取流,也可以使用CryptoStreamMode.Write来写入流。加密器和解密器,与读取和写入可以形成四种组合。这些组合可能会令人茫然!为了帮助理解,可以将读取理解为“拉”,而将写入理解为“推”。如果仍旧有疑问则可以首先用Write操作进行加密,而用Read操作进行解密,这种组合是最自然也最常见的。 

        请使用System.Cryptography命名空间下的RandomNumberGenerator来生成随机密钥或IV。此类随机数生成器生成的数字是真正难以预测的,或称为具备密码学强度的(而System.Random则无法保证这一点)。以下是一个示例:

//随机生成密钥
byte[] key_random = new byte[16];
byte[] iv_random = new byte[16];
RandomNumberGenerator rand = RandomNumberGenerator.Create();
//随机生成一个key
rand.GetBytes(key_random);
//随机生成一个iv
rand.GetBytes(iv_random);

        如果不指定密钥和IV,则加密算法会自动生成密码学强度的随机数作为密钥和IV。这些值可以通过Aes对象的Key和IV属性进行查看。

三、内存加密

        我们可以使用MemoryStream完全将加密和解密放在内存中。

public class AesTools
    {
        static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
        {
            using (SymmetricAlgorithm symmetric = Aes.Create())
            {
                symmetric.KeySize = 128;
                symmetric.BlockSize = 128;
                symmetric.Mode = CipherMode.CBC;
                symmetric.Padding = PaddingMode.PKCS7;
                using (ICryptoTransform tran = symmetric.CreateEncryptor(key, iv))
                {
                    return EnCrypt(data, tran);
                }
            }
        }

        static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
        {
            using (SymmetricAlgorithm symmetric = Aes.Create())
            {
                symmetric.KeySize = 128;
                symmetric.BlockSize = 128;
                symmetric.Mode = CipherMode.CBC;
                symmetric.Padding = PaddingMode.PKCS7;
                using (ICryptoTransform tran = symmetric.CreateDecryptor(key, iv))
                {
                    return DeCrypt(data, tran);
                }
            }
        }

        static byte[] EnCrypt(byte[] data, ICryptoTransform tran)
        {
            return tran.TransformFinalBlock(data, 0, data.Length);
        }

        static byte[] DeCrypt(byte[] data, ICryptoTransform tran)
        {
            return tran.TransformFinalBlock(data, 0, data.Length);
        }

        public static string Encrypt(string data, byte[] key, byte[] iv)
        {
            return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(data), key, iv));
        }

        public static string Decrypt(string data, byte[] key, byte[] iv)
        {
            return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(data), key, iv));
        }
    }

        测试代码

//随机生成密钥
byte[] key_random = new byte[16];
byte[] iv_random = new byte[16];
RandomNumberGenerator rand = RandomNumberGenerator.Create();
//随机生成一个key
rand.GetBytes(key_random);
//随机生成一个iv
rand.GetBytes(iv_random);

string encrypted = AesTools.Encrypt("yeah小小的猫咪", key_random, iv_random);
Console.WriteLine(encrypted);

string decrypted = AesTools.Decrypt(encrypted, key_random, iv_random);
Console.WriteLine(decrypted);

        可以看到如下输出 

四、串联加密流

        CryptoStream是一个装饰器,它可以将其他的流串联起来。以下示例会先将压缩的加密文本写入文件,之后再从该文件中读取这些内容。

         所有名称为单个字符的变量都是链条的一部分。而那些algorithm、encryptor和decryptor将协助CryptoStream进行加密工作。

        不论流的大小如何,上述串联加密流的方式只会占用很少的内存。

串联加密和压缩流
知秋君
上一篇 2024-07-11 13:02
下一篇 2024-07-11 12:36

相关推荐