黑马程序员数据加密学习

孤街浪徒 提交于 2020-03-04 12:14:32

---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------

对称加密算法:对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信性至关重要。对称加密算法的优点在于加解密的高速度和使用长密钥时的难破解性。不足之处是,交易双方都使用同样钥匙,安全性得不到保证。

非对称加密算法:非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

加密模式:

电子密码本(Electronic Code Book,ECB):在 ECB 模式中,每块明文都是独立于其他块加密的。虽然这样做比较高效(可以并行执行多个数据块的加密)但这种方法有一个很大的问题。例如,在 ECB 模式中,对相同明文块的加密总是产生相同的密文块,这为某些类型的密码分析攻击打开了方便之门。ECB 方式通常被认为不适合保护敏感数据。 

密码块链接(Cipher Block Chaining,CBC):在 CBC 模式中,文本块是连续加密的,在加密当前明文块之前,用前一次块加密的结果修改当前明文块。这个过程改进了加密的一些特征(例如,相同的明文块不会产生相同的密文块),但是由于其加密过程是连续的,CBC 方式不支持加密的并行化。CBC 方式使用一个称作初始化向量(Initialization Vector,IV)的附加文本来开始链接过程。IV 用于修改被加密的第一个明文块。

密码反馈(Cipher Feedback,CFB):在 CFB 模式中,先加密前一个块,然后将得到的结果与明文相结合产生当前块,从而有效地改变用于加密当前块的密钥。这里密钥的值是不断变化的,这个过程与流加密类似,但是性能则远不如流加密。与 CBC 方式一样,这里要使用一个初始化向量作为加密过程的种子。

输出反馈(Output Feedback,OFB):在 OFB 方式中,使用一个种子或 IV 来开始加密过程。加密种子后,将加密结果与明文块结合产生密文。之后被加密的种子再度被加密,如此重复此过程,直到遍及全部明文。同样,结果类似于流加密

密码文本窃用(Cipher Text Steal):模式处理任何长度的纯文本并产生长度与纯文本长度匹配的密码文本。除了最后两个纯文本块外,对于所有其他块,此模式与CBC模式的行为相同。

DES:数据加密标准(DES,Data Encryption Standard)是一种使用密钥加密的块密码,它基于使用56位密钥的对称算法。DES现在已经不被视为一种安全的加密算法,主要因为它使用的56位密钥过短。为了提供实用所需的安全性,可以使用DES的派生算法3DES来进行加密,在2001年,DES作为一个标准已经被高级加密标准(AES)所取代。

        /// <summary>
        /// 使用DES加密字符串
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <param name="key">加密密匙</param>
        /// <returns>加密后的字符串</returns>
        private static string EncryptByDES(string source, string key)
        {
            byte[] input = Encoding.Default.GetBytes(key);
            byte[] temp = new byte[16] { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };
            if (input.Length > 16)
            {
                Console.WriteLine("只能输入8个汉字或者16个字符!");
                return null;
            }
            input.CopyTo(temp, 0);
            DESCryptoServiceProvider cryptoService = new DESCryptoServiceProvider();//实例化DES加密服务类
              cryptoService.Mode = CipherMode.CBC;//使用的加密模式
              cryptoService.IV = temp.Take(8).ToArray();//定义偏移量
              cryptoService.Key = temp.Skip(8).ToArray();//定义密钥
              ICryptoTransform encryptor = cryptoService.CreateEncryptor();//使用加密服务对象创建一个对流执行加密转换的加密器
              byte[] byteArr = Encoding.Default.GetBytes(source);//把源字符串放到字节数组中
              return Convert.ToBase64String(encryptor.TransformFinalBlock(byteArr, 0, byteArr.Length));//使用加密器加密数据
        }
        /// <summary>
        /// 使用DES解密字符串
         /// </summary>
        /// <param name="source">要解密的字符串</param>
        /// <param name="key">解密密匙</param>
        /// <returns>解密后的字符串</returns>
        private static string DecryptByDES(string source, string key)
        {
            byte[] input = Encoding.Default.GetBytes(key);
            byte[] temp = new byte[16] { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };
            if (input.Length > 16)
            {
                Console.WriteLine("错误的密匙");
                return null;
            }
            input.CopyTo(temp, 0);
            DESCryptoServiceProvider cryptoService = new DESCryptoServiceProvider();
            cryptoService.Mode = CipherMode.CBC;
            cryptoService.IV = temp.Take(8).ToArray();
            cryptoService.Key = temp.Skip(8).ToArray();
            byte[] byteArr = Convert.FromBase64String(source);//把源字符串放到字节数组中
              ICryptoTransform decryptor = cryptoService.CreateDecryptor();//使用加密服务对象创建一个对流执行解密转换的解密器
              return Encoding.Default.GetString(decryptor.TransformFinalBlock(byteArr, 0, byteArr.Length));//使用解密器解密数据,密匙错误会抛异常
        }

3DES:或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法

        /// <summary>
        /// 使用DES加密字符串
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <param name="key">加密密匙</param>
        /// <returns>加密后的字符串</returns>
        public static string EncryptBy3DES(string source, string key)
        {
            Regex reg = new Regex(@"[\w\W]{0,8}");
            MatchCollection matchs = reg.Matches(key);
            string result = source;
            foreach (Match match in matchs)
            {
                result = EncryptByDES(result, match.ToString());
            }
            return result;
        }
        /// <summary>
        /// 使用DES解密字符串
         /// </summary>
        /// <param name="source">要解密的字符串</param>
        /// <param name="key">解密密匙</param>
        /// <returns>解密后的字符串</returns>
        public static string DecryptBy3DES(string source, string key)
        {
            Regex reg = new Regex(@"[\w\W]{0,8}");
            MatchCollection matchs = reg.Matches(key);
            string result = source;
            for (int i = matchs.Count - 1; i >= 0; i--)
            {
                result = DecryptByDES(result, matchs[i].ToString());
            }
            return result;
        }

散列:Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

散列函数的性质:

所有散列函数都有如下一个基本特性:如果两个散列值是不相同的(根据同一函数),那么这两个散列值的原始输入也是不相同的。这个特性是散列函数具有确定性的结果。但另一方面,散列函数的输入和输出不是一一对应的,如果两个散列值相同,两个输入值很可能是相同的,但并不能绝对肯定二者一定相等。输入一些数据计算出散列值,然后部分改变输入值,一个具有强混淆特性的散列函数会产生一个完全不同的散列值。 典型的散列函数都有无限定义域,比如任意长度的字节字符串,和有限的值域,比如固定长度的比特串。在某些情况下,散列函数可以设计成具有相同大小的定义域和值域间的一一对应。一一对应的散列函数也称为排列。可逆性可以通过使用一系列的对于输入值的可逆“混合”运算而得到

SHA-1及其他: SHA1对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。散列是一种单向算法,一旦数据被转换,将无法再获得其原始值,只能对加密后的数据进行比较。

MD5: MD5是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。

        /// <summary>
        /// 使用SHA1加密
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string EncryptBySHA1(string source)
        {
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            byte[] byteArr = sha1.ComputeHash(Encoding.Default.GetBytes(source));
            sha1.Clear();
            return Convert.ToBase64String(byteArr);
        }
        /// <summary>
        /// 使用SHA256加密
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string EncryptBySHA256(string source)
        {
            SHA256 sha256 = new SHA256CryptoServiceProvider();
            byte[] byteArr = sha256.ComputeHash(Encoding.Default.GetBytes(source));
            sha256.Clear();
            return Convert.ToBase64String(byteArr);
        }
        /// <summary>
        /// 使用SHA384加密
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string EncryptBySHA384(string source)
        {
            SHA384 sha384 = new SHA384CryptoServiceProvider();
            byte[] byteArr = sha384.ComputeHash(Encoding.Default.GetBytes(source));
            sha384.Clear();
            return Convert.ToBase64String(byteArr);
        }
        /// <summary>
        /// 使用SHA512加密
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string EncryptBySHA512(string source)
        {
            SHA512 sha512 = new SHA512CryptoServiceProvider();
            byte[] byteArr = sha512.ComputeHash(Encoding.Default.GetBytes(source));
            sha512.Clear();
            return Convert.ToBase64String(byteArr);
        }
        /// <summary>
        /// 使用MD5加密
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string EncryptByMD5(string source)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] byteArr = md5.ComputeHash(Encoding.Default.GetBytes(source));
            md5.Clear();
            return Convert.ToBase64String(byteArr);
        }

AES:密码学中的高级加密标准(Advanced Encryption Standard,AES)是一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。高级加密标准已然成为对称密钥加密中最流行的算法之一。它可以使用128、192 和 256 位密钥。(16字节、24字节、32字节)

        /// <summary>
        /// 使用AES加密字符串
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <param name="key">加密密匙</param>
        /// <returns>加密后的字符串</returns>
        private static string EncryptAES(string source, string key)
        {
            byte[] input = Encoding.Default.GetBytes(key);
            byte[] temp = new byte[32] { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };
            input.CopyTo(temp, 0);
            RijndaelManaged aes = new RijndaelManaged();
            aes.Mode = CipherMode.CBC;
            aes.Key = temp.Take(16).ToArray();
            aes.IV = temp.Skip(16).ToArray();
            ICryptoTransform cTransform = aes.CreateEncryptor();
            byte[] byteArr = Encoding.Default.GetBytes(source);
            return Convert.ToBase64String(cTransform.TransformFinalBlock(byteArr, 0, byteArr.Length));
        }
        /// <summary>
        /// 使用AES解密字符串
         /// </summary>
        /// <param name="source">要解密的字符串</param>
        /// <param name="key">解密密匙</param>
        /// <returns>解密后的字符串</returns>
        private static string DecryptAES(string source, string key)
        {
            byte[] input = Encoding.Default.GetBytes(key);
            byte[] temp = new byte[32] { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };
            input.CopyTo(temp, 0);
            RijndaelManaged aes = new RijndaelManaged();
            aes.Mode = CipherMode.CBC;
            aes.Key = temp.Take(16).ToArray();
            aes.IV = temp.Skip(16).ToArray();
            ICryptoTransform cTransform = aes.CreateDecryptor();
            byte[] byteArr = Convert.FromBase64String(source);
            return Encoding.Default.GetString(cTransform.TransformFinalBlock(byteArr, 0, byteArr.Length));
        }

RSA:RSA加密算法是一种非对称加密算法,只有短的RSA钥匙才可能被强力方式破解。还没有任何可靠的攻击RSA算法的方式,只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被破解的。RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现在的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。由于进行的都是大数计算,使得RSA最快的情况也比DES慢上好几倍,无论是软件还是硬件实现。速度一直是RSA的缺陷。

        /// <summary>
        /// 使用RSA加密字符串
         /// </summary>
        /// <param name="source">要加密的字符串</param>
        /// <param name="publicKey">生成的公匙</param>
        /// <param name="privateKey">生成的私匙</param>
        /// <returns>加密后的字符串</returns>
        public static string EncryptByRSA(string source, out string publicKey, out string privateKey)
        {
          RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();//实例化RSA加密服务类
            publicKey = Convert.ToBase64String(RSA.ExportCspBlob(false));//使用RSA加密服务生成公匙
            privateKey = Convert.ToBase64String(RSA.ExportCspBlob(true));//使用RSA加密服务生成私匙
            byte[] byteArr = RSA.Encrypt(Encoding.Default.GetBytes(source),true);//使用RSA加密数据
            return Convert.ToBase64String(byteArr);
        }
        /// <summary>
        /// 使用RSA解密字符串
         /// </summary>
        /// <param name="source">要解密的字符串</param>
        /// <param name="privateKey">使用的私匙</param>
        /// <returns>解密后的字符串</returns>
        public static string DecryptByRSA(string source, string privateKey)
        {
          RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
          byte[] publicKey = Convert.FromBase64String(privateKey);//使用私匙生成公匙
            RSA.ImportCspBlob(publicKey);//导入公匙信息
            return Encoding.Default.GetString(RSA.Decrypt(Convert.FromBase64String(source), true));//使用RSA解密数据
        }

 

---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!