目錄一、數(shù)據(jù)加密標準 - Data Encryption Standard(DES)二、高級加密標準 - Advanced Encryption Standard(AES)三、消息摘要算法第五版 - Message-Digest Algorithm 5(MD5)四、安全哈希算法 - Secure Hash Algorithm(SHA1)五、公鑰加密算法(RSA)六、干擾項 - 鹽(Salt)七、RSA密鑰格式Pkcs8八、源碼下載
數(shù)據(jù)加密標準 - Data Encryption Standard(DES)簡介DES全稱為Data Encryption Standard,即數(shù)據(jù)加密標準,是一種使用密鑰加密的塊算法,1976年被美國聯(lián)邦政府的國家標準局確定為聯(lián)邦資料處理標準(FIPS),隨后在國際上廣泛流傳開來。
核心代碼public class DesCryptoUtil : IDesCryptoUtil { /// <summary> /// The key, length is 8, generated on https://www./strings/ /// You can also use the GenerateKey method in the DESCryptoServiceProvider to generate the key. /// </summary> private static readonly byte[] Key = Encoding.ASCII.GetBytes("0e3Nl9Z9"); /// <summary> /// The iv, length is 8, generated on https://www./strings/ /// You can also use the GenerateIV method in the DESCryptoServiceProvider to generate the iv. /// </summary> private static readonly byte[] Iv = Encoding.ASCII.GetBytes("62EcX79F"); public byte[] Encrypt(byte[] plainBytes) { using (var provider = new DESCryptoServiceProvider()) { provider.Key = Key; provider.IV = Iv; using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, provider.CreateEncryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(plainBytes, 0, plainBytes.Length); cryptoStream.FlushFinalBlock(); } return memoryStream.ToArray(); } } } public byte[] Decrypt(byte[] encryptedBytes) { using (var provider = new DESCryptoServiceProvider()) { provider.Key = Key; provider.IV = Iv; using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, provider.CreateDecryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(encryptedBytes, 0, encryptedBytes.Length); cryptoStream.FlushFinalBlock(); } return memoryStream.ToArray(); } } } }
調(diào)用示例[TestCase("123456")] [TestCase("abcdef")] public void Encrypt(string plainText) { var plainBytes = Encoding.UTF8.GetBytes(plainText); var encryptedBytes = _desCryptoUtil.Encrypt(plainBytes); var encryptedText = Convert.ToBase64String(encryptedBytes); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); } [TestCase("ecIwYJUsLa0=")] [TestCase("iPsXCjS+O0c=")] public void Decrypt(string encryptedText) { var encryptedBytes = Convert.FromBase64String(encryptedText); var plainBytes = _desCryptoUtil.Decrypt(encryptedBytes); var plainText = Encoding.UTF8.GetString(plainBytes); Console.WriteLine("Encrypted text:{0}, plain text:{1}", encryptedText, plainText); }
高級加密標準 - Advanced Encryption Standard(AES)簡介高級加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標準。這個標準用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。經(jīng)過五年的甄選流程,高級加密標準由美國國家標準與技術(shù)研究院(NIST)于2001年11月26日發(fā)布于FIPS PUB 197,并在2002年5月26日成為有效的標準。2006年,高級加密標準已然成為對稱密鑰加密中最流行的算法之一。
核心代碼public class AesCryptoUtil : IAesCryptoUtil { /// <summary> /// A system key and the length should be 16. /// You can use tool to generate the string on https://www./strings/ or other website. /// </summary> private const string SystemKeyPart = "84ImUeBn432oPkqo"; /// <summary> /// A custom key and the lenth should between 4 and 16. You can use the project name as the custom key. /// </summary> private const string UserKeyPart = "AecCrypto"; /// <summary> /// The combine key. /// </summary> private static readonly byte[] Key = Encoding.ASCII.GetBytes(UserKeyPart.PadRight(16, '#') + SystemKeyPart); /// <summary> /// Please indicate a random string here, and the length must be 16. /// You can use tool to generate the string on https://www./strings/ or other website. /// </summary> private static readonly byte[] Iv = Encoding.ASCII.GetBytes("bCNtStALc7bRqREq"); public byte[] Encrypt(byte[] plainBytes) { return Encrypt(plainBytes, CipherMode.CBC, PaddingMode.PKCS7); } public byte[] Decrypt(byte[] encryptedBytes) { return Decrypt(encryptedBytes, CipherMode.CBC, PaddingMode.PKCS7); } private static byte[] Encrypt(byte[] plainBytes, CipherMode cipher, PaddingMode padding) { using (var aes = Rijndael.Create()) { aes.Mode = cipher; aes.Padding = padding; using (var transform = aes.CreateEncryptor(Key, Iv)) { var encryptedBytes = transform.TransformFinalBlock(plainBytes, 0, plainBytes.Length); return encryptedBytes; } } } private static byte[] Decrypt(byte[] encryptedBytes, CipherMode cipher, PaddingMode padding) { using (var aes = Rijndael.Create()) { aes.Mode = cipher; aes.Padding = padding; using (var transform = aes.CreateDecryptor(Key, Iv)) { var plainBytes = transform.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); return plainBytes; } } } }
調(diào)用示例[TestCase("123456")] [TestCase("abcdef")] public void Encrypt(string plainText) { var plainBytes = Encoding.UTF8.GetBytes(plainText); var encryptedBytes = _aesCryptoUtil.Encrypt(plainBytes); var encryptedText = Convert.ToBase64String(encryptedBytes); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); } [TestCase("HDHlYOQuENPmtjFKvLZIEA==")] [TestCase("YO3ErLZ5/izaDgD0M0uYDg==")] public void Decrypt(string encryptedText) { var encryptedBytes = Convert.FromBase64String(encryptedText); var plainBytes = _aesCryptoUtil.Decrypt(encryptedBytes); var plainText = Encoding.UTF8.GetString(plainBytes); Console.WriteLine("Encrypted text:{0}, plain text:{1}", encryptedText, plainText); }
消息摘要算法第五版 - Message-Digest Algorithm 5(MD5)簡介MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現(xiàn)。將數(shù)據(jù)(如漢字)運算為另一固定長度值,是雜湊算法的基礎(chǔ)原理,MD5的前身有MD2、MD3和MD4。
MD5算法具有以下特點: 注:MD5常用于密碼加密。
核心代碼
調(diào)用示例[TestCase("123456")] [TestCase("abcdef")] public void Encrypt(string plainText) { var plainBytes = Encoding.UTF8.GetBytes(plainText); var encryptedBytes = _md5CryptoUtil.Encrypt(plainBytes); var stringBuilder = new StringBuilder(); foreach (var b in encryptedBytes) { stringBuilder.AppendFormat("{0:X2}", b); } var encryptedText = stringBuilder.ToString(); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); }
安全哈希算法 - Secure Hash Algorithm(SHA1)簡介安全哈希算法(Secure Hash Algorithm)主要適用于數(shù)字簽名標準 (Digital Signature Standard DSS)里面定義的數(shù)字簽名算法(Digital Signature Algorithm DSA)。對于長度小于2^64位的消息,SHA1會產(chǎn)生一個160位的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數(shù)據(jù)的完整性。在傳輸?shù)倪^程中,數(shù)據(jù)很可能會發(fā)生變化,那么這時候就會產(chǎn)生不同的消息摘要。 SHA1有如下特性:不可以從消息摘要中復原信息;兩個不同的消息不會產(chǎn)生同樣的消息摘要,(但會有1x10 ^ 48分之一的機率出現(xiàn)相同的消息摘要,一般使用時忽略)。
核心代碼
調(diào)用示例[TestCase("123456")] [TestCase("abcdef")] public void Encrypt(string plainText) { var plainBytes = _bytesUtil.FromString(plainText); var encryptedBytes = _sha1CryptoUtil.Encrypt(plainBytes); var encryptedText = _bytesUtil.ToHex(encryptedBytes); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); }
公鑰加密算法(RSA)簡介RSA公鑰加密算法是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。 RSA是目前最有影響力的公鑰加密算法,它能夠抵抗到目前為止已知的絕大多數(shù)密碼攻擊,已被ISO推薦為公鑰數(shù)據(jù)加密標準。 RSA算法基于一個十分簡單的數(shù)論事實:將兩個大素數(shù)相乘十分容易,但是想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰。
核心代碼public class RsaCryptoUtil : IRsaCryptoUtil { public RsaKey GenerateKeys() { using (var rsa = new RSACryptoServiceProvider()) { var key = new RsaKey { Private = rsa.ToXmlString(true), Public = rsa.ToXmlString(false) }; return key; } } public byte[] Sign(byte[] bytes, string privateKey) { using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(privateKey); var signature = rsa.SignData(bytes, new MD5CryptoServiceProvider()); return signature; } } public bool Verify(byte[] bytes, byte[] signature, string publicKey) { using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(publicKey); return rsa.VerifyData(bytes, new MD5CryptoServiceProvider(), signature); } } public byte[] Encrypt(byte[] plainBytes, string publicKey) { using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(publicKey); var encryptedBytes = rsa.Encrypt(plainBytes, false); return encryptedBytes; } } public byte[] Decrypt(byte[] encryptedBytes, string privateKey) { using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(privateKey); var decryptedBytes = rsa.Decrypt(encryptedBytes, false); return decryptedBytes; } } }
調(diào)用示例[TestCase("123456")] [TestCase("abcdef")] public void Sign(string text) { var bytes = _bytesUtil.FromString(text); var signatureBytes = _rsaCryptoUtil.Sign(bytes, _key.Private); var signature = _bytesUtil.ToBase64(signatureBytes); Console.WriteLine("Text:{0}, signature:{1}", text, signature); } [TestCase("123456", "T5BS2WHA2ZvDexuEIPRSbnB7SlC1blNPi4BGcwiGovE54bmAiLIqf6p9dmsMMS+wgyKX2JPKkiNKtzts+q1yVmosqqjcmrNZbP+YF9YNqbO4Da0CJRjH1rwCa+XC7cJFKIDn85KQqtLpdr7yong0SjtXA+cDMD3dP9RoZLb+k/k=")] [TestCase("abcdef", "Gxf9LGx2AFmW114ex7nemDXIiEXkYmBA4bR0SMWp4M/uule171rtPIyZlX17CeNM2kmNKtxYAqsJj0Pfxb1znydtNLo/lFNkZDZkxAMx7uTLdw9Os4g5ZKXKkBbYi3aYBNY0bbICfetGRNGaGU4p8HlKm+KrijbURBKH6wE1DyI=")] public void Verify(string text, string signature) { var bytes = _bytesUtil.FromString(text); var signatureBytes = _bytesUtil.FromBase64(signature); var isVerified = _rsaCryptoUtil.Verify(bytes, signatureBytes, _key.Public); Console.WriteLine("Text:{0}, signature:{1}, is verified:{2}", text, signature, isVerified); } [TestCase("123456")] [TestCase("abcdef")] public void Encrypt(string plainText) { var plainBytes = _bytesUtil.FromString(plainText); var encryptedBytes = _rsaCryptoUtil.Encrypt(plainBytes, _key.Public); var encryptedText = _bytesUtil.ToBase64(encryptedBytes); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); } [TestCase("ZfT/2r0VqY6LX8eL+rfgufT/q+kMZsvRcDK6NafoHb+zvBN5KNxI5MAIG07Oqe3EiRH3yXrjKnePUiVvPJGW40xHm6S2yRBar61ZB3DONavwjlKQBBPGJNuW1S8aevdxFIGHazFjzv7FMCcJaAFrnNlZlkdsk67z0FbubPylPbY=")] [TestCase("m8rS9i1DGE6MqW0L6vcS+lthiBzFTWrfK4XS97TDyC8t0xecNsLteIGEDgrzUMVf9j0ue0HpGHslYiOUAiX1wnFcVM0aX3SAZ1NmsIFEoYhz3av3lPj/tX9Ccirn7YhQw/N5BHwxPYT3ZcRfy+ozVXBo0EFDNGoJMcysfA0u5Uk=")] public void Decrypt(string encryptedText) { var encryptedBytes = _bytesUtil.FromBase64(encryptedText); var plainBytes = _rsaCryptoUtil.Decrypt(encryptedBytes, _key.Private); var plainText = _bytesUtil.ToString(plainBytes); Console.WriteLine("Encrypted text:{0}, plain text:{1}", encryptedText, plainText); }
干擾項 - 鹽(Salt)簡介相同的明文用同樣的加密方法(如MD5)進行加密會得到相同的密文。 如用MD5的方式加密“123456”,你總會得到密文“E10ADC3949BA59ABBE56E057F20F883E”。 那么,當數(shù)據(jù)庫信息泄漏時,如果你的密碼設(shè)置的比較簡單,對方是很容易猜到你的密碼,或者通過彩虹表來破解你的密碼。 因此,你需要在明文中添加干擾項-鹽(Salt)。 對于加鹽的方式,我認為有兩種。 1.對于只加密,但不解密的算法,如MD5,SHA1。我們需要把鹽和密文都存在數(shù)據(jù)庫中,用戶輸入密碼時,我們把用戶密碼和鹽組成新的明文,進行加密,然后得到密文,最后對比該密文是否與庫中密文匹配。 2.對于可加解密的算法,我們可以定義一些規(guī)則,如明文前加長度為3的鹽,在明文后加長度為5的鹽,然后進行加密。解密的時候可以按預先設(shè)置的規(guī)則把鹽去掉就能得到真正的明文。
核心代碼
調(diào)用示例MD5 [TestCase("123456")] [TestCase("abcdef")] public void EncryptWithSalt(string plainText) { var plainBytes = _bytesUtil.FromString(plainText); var headSalt = _saltUtil.GenerateSalt(SaltSetting.HeadSize); var tailSalt = _saltUtil.GenerateSalt(SaltSetting.TailSize); var plainBytesWithSalts = _bytesUtil.Combine(headSalt, plainBytes, tailSalt); var encryptedBytes = _md5CryptoUtil.Encrypt(plainBytesWithSalts); var encryptedText = _bytesUtil.ToHex(encryptedBytes); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); }
AES [TestCase("123456")] [TestCase("abcdef")] public void EncryptWithSalt(string plainText) { var plainBytes = _bytesUtil.FromString(plainText); var headSalt = _saltUtil.GenerateSalt(SaltSetting.HeadSize); var tailSalt = _saltUtil.GenerateSalt(SaltSetting.TailSize); var plainBytesWithSalts = _bytesUtil.Combine(headSalt, plainBytes, tailSalt); var encryptedBytes = _aesCryptoUtil.Encrypt(plainBytesWithSalts); var encryptedText = _bytesUtil.ToBase64(encryptedBytes); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); } [TestCase("Leu9NnY9qA3/9u5uUZoXGQ==")] [TestCase("eqcbaEOL9mHlQh3ERnGNeA==")] public void DecryptWithSalt(string encryptedText) { var encryptedBytes = _bytesUtil.FromBase64(encryptedText); var plainBytesWithSalts = _aesCryptoUtil.Decrypt(encryptedBytes); var plainBytes = plainBytesWithSalts.Skip(SaltSetting.HeadSize).Take(plainBytesWithSalts.Length - SaltSetting.HeadSize - SaltSetting.TailSize).ToArray(); var plainText = _bytesUtil.ToString(plainBytes); Console.WriteLine("Encrypted text:{0}, plain text:{1}", encryptedText, plainText); }
RSA密鑰格式Pkcs8簡介對于RSA密鑰的格式,不同的語言是不同的,如C#是xml格式,Java是二進制流,其他語言又可能是另外一種格式。為了解決這個問題,一種統(tǒng)一的密鑰格式Pkcs8應運而生。
核心代碼public class RsaPkcs8CryptoUtil : IRsaCryptoUtil { public RsaKey GenerateKeys() { using (var rsa = new RSACryptoServiceProvider()) { var keyPair = DotNetUtilities.GetRsaKeyPair(rsa); var key = new RsaKey { Private = GeneratePrivateKey(keyPair.Private), Public = GeneratePublicKey(keyPair.Public) }; return key; } } public byte[] Sign(byte[] bytes, string privateKey) { using (var rsa = new RSACryptoServiceProvider()) { var key = ParsePrivateKey(privateKey); rsa.ImportParameters(key); var signature = rsa.SignData(bytes, new MD5CryptoServiceProvider()); return signature; } } public bool Verify(byte[] bytes, byte[] signature, string publicKey) { using (var rsa = new RSACryptoServiceProvider()) { var key = ParsePublicKey(publicKey); rsa.ImportParameters(key); return rsa.VerifyData(bytes, new MD5CryptoServiceProvider(), signature); } } public byte[] Encrypt(byte[] plainBytes, string publicKey) { using (var rsa = new RSACryptoServiceProvider()) { var key = ParsePublicKey(publicKey); rsa.ImportParameters(key); var encryptedBytes = rsa.Encrypt(plainBytes, false); return encryptedBytes; } } public byte[] Decrypt(byte[] encryptedBytes, string privateKey) { using (var rsa = new RSACryptoServiceProvider()) { var key = ParsePrivateKey(privateKey); rsa.ImportParameters(key); var decryptedBytes = rsa.Decrypt(encryptedBytes, false); return decryptedBytes; } } private static string GeneratePrivateKey(AsymmetricKeyParameter key) { var builder = new StringBuilder(); using (var writer = new StringWriter(builder)) { var pkcs8Gen = new Pkcs8Generator(key); var pemObj = pkcs8Gen.Generate(); var pemWriter = new PemWriter(writer); pemWriter.WriteObject(pemObj); } return builder.ToString(); } private static string GeneratePublicKey(AsymmetricKeyParameter key) { var builder = new StringBuilder(); using (var writer = new StringWriter(builder)) { var pemWriter = new PemWriter(writer); pemWriter.WriteObject(key); } return builder.ToString(); } private static RSAParameters ParsePrivateKey(string privateKey) { using (var reader = new StringReader(privateKey)) { var pemReader = new PemReader(reader); var key = (RsaPrivateCrtKeyParameters)pemReader.ReadObject(); var parameter = new RSAParameters { Modulus = key.Modulus.ToByteArrayUnsigned(), Exponent = key.PublicExponent.ToByteArrayUnsigned(), D = key.Exponent.ToByteArrayUnsigned(), P = key.P.ToByteArrayUnsigned(), Q = key.Q.ToByteArrayUnsigned(), DP = key.DP.ToByteArrayUnsigned(), DQ = key.DQ.ToByteArrayUnsigned(), InverseQ = key.QInv.ToByteArrayUnsigned() }; return parameter; } } private static RSAParameters ParsePublicKey(string publicKey) { using (var reader = new StringReader(publicKey)) { var pemReader = new PemReader(reader); var key = (RsaKeyParameters)pemReader.ReadObject(); var parameter = new RSAParameters { Modulus = key.Modulus.ToByteArrayUnsigned(), Exponent = key.Exponent.ToByteArrayUnsigned() }; return parameter; } } }
調(diào)用示例[TestCase("123456")] [TestCase("abcdef")] public void Sign(string text) { var bytes = _bytesUtil.FromString(text); var signatureBytes = _rsaCryptoUtil.Sign(bytes, _key.Private); var signature = _bytesUtil.ToBase64(signatureBytes); Console.WriteLine("Text:{0}, signature:{1}", text, signature); } [TestCase("123456", "Pj4Z4P1ktNM+MLoqO3WUBZogZjVcjz5cvMVBJ741d2wq1X8UuI2AclZueltRahGHURiJ8djTYCSEGG1oHSc1K0ilk4lz40HFu1mqv65bwglqKrX2ks1wnwnBHusbfiu4HYXNy5HN/fcjB1ah8MxZSofxaGth1xAygY9bKkIBFS0=")] [TestCase("abcdef", "UUOTnyWRU/b4CvALxw4VHusKBXjv32RTjuTVyZHeBaQKvlqVuMCwrdey0Z9wrh20GRspA2Je3uUfbFSxYStDnzVsXJLB3wtNvWX+NcE+h1g1LXijnediJKn6uh4UorCpVru0tZX3XrMJPeY5u8+ZBFMUP8zw078t7w1c60XpioQ=")] public void Verify(string text, string signature) { var bytes = _bytesUtil.FromString(text); var signatureBytes = _bytesUtil.FromBase64(signature); var isVerified = _rsaCryptoUtil.Verify(bytes, signatureBytes, _key.Public); Console.WriteLine("Text:{0}, signature:{1}, is verified:{2}", text, signature, isVerified); } [TestCase("123456")] [TestCase("abcdef")] public void Encrypt(string plainText) { var plainBytes = _bytesUtil.FromString(plainText); var encryptedBytes = _rsaCryptoUtil.Encrypt(plainBytes, _key.Public); var encryptedText = _bytesUtil.ToBase64(encryptedBytes); Console.WriteLine("Plain text:{0}, encrypted text:{1}", plainText, encryptedText); } [TestCase("Ku82IhLYSuthVU1uN5NvUAFImWLwqaHmSuWA8dlTBLjYcJdGJmfY/BMK4JULBUauFDIyYHkFZ2j2oK+lQDw2UuXWbojLrnPZAvAbW+HB/5nuCS1mElVJr7YTq3tHb2mjcwAKx2qSnWgDO9V8akCnMMNVGLg9IN5gnjctlgu44iU=")] [TestCase("hBWYekZUiEiPgQTgVtVB+Ax1UOa6tKkVk4UMU2CjwFpYoOndtJu/Frs/woRdvfJBZbD/lmMOpGoK35mlX9Y0RKrZdLRM0RG8/maiQQFWCM3ELgBWqYkdVLc4RQULxfWaVFuQolXWwVk+gCUaWeCaaMEBZ28dXiUP7npaWexEcB8=")] public void Decrypt(string encryptedText) { var encryptedBytes = _bytesUtil.FromBase64(encryptedText); var plainBytes = _rsaCryptoUtil.Decrypt(encryptedBytes, _key.Private); var plainText = _bytesUtil.ToString(plainBytes); Console.WriteLine("Encrypted text:{0}, plain text:{1}", encryptedText, plainText); }
|
|