现在我正在制作一个将在 C# .Net 中执行常见任务的库。基本上我的目标是 C# 的初学者,以便他们可以从我的库中受益并使用它来最大程度地减少他们遇到的困难。我目前正在向我的库中添加加密功能,并且取得了一些成功。但我的加密标准不是很困难和复杂。以便将来任何黑客都可以闯入并解密重要数据(即密码等)。所以请告诉我如何编写自己的复杂标准来加密密码。该库旨在免费提供给初学者。
谢谢
现在我正在制作一个将在 C# .Net 中执行常见任务的库。基本上我的目标是 C# 的初学者,以便他们可以从我的库中受益并使用它来最大程度地减少他们遇到的困难。我目前正在向我的库中添加加密功能,并且取得了一些成功。但我的加密标准不是很困难和复杂。以便将来任何黑客都可以闯入并解密重要数据(即密码等)。所以请告诉我如何编写自己的复杂标准来加密密码。该库旨在免费提供给初学者。
谢谢
我建议您不要编写自己的加密引擎,没有很好的理由,因为已经有很多加密引擎了 - 作为开始,请查看Enterprise Library中的加密 API 。它对初学者很友好。
如果您仍然决定自己编写,请查看 Enterprise Library 和其他类似BouncyCastle的框架,了解其他框架是如何组合在一起的 - 您会学到很多东西,这是尝试和改进现有框架的最佳方式。
当有很多现有的图书馆时,不要去你自己的图书馆。您不会从中受益,也将毫无用处。一句谚语:不要为了喝杯茶而买食堂。
您可以围绕 .NET 加密方法编写易于使用的包装器。
Aes 示例(我自己的包装器):
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Synercoding.CodeGuard;
namespace Synercoding.Encryption.Symmetrical
{
/// <summary>
/// A class to Encrypt and Decrypt with Rijndael AES encryption
/// </summary>
public sealed class AesEncryption : IDisposable
{
private byte[] m_salt;
private RijndaelManaged m_aesAlg = new RijndaelManaged(); // RijndaelManaged object used to encrypt/decrypt the data.
/// <summary>
/// Create a new AesEncryption object with the standard salt
/// </summary>
public AesEncryption() : this("850nW94vN39iUx") { }
/// <summary>
/// Create a new AesEncryption object with the specified salt
/// </summary>
/// <param name="salt">The salt used for salting the key. Must be atleast 8 chars long</param>
public AesEncryption(string salt)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(salt), "param salt can't be null or empty.");
Guard.Requires<ArgumentException>(salt.Length >= 8, "param salt must be atleast 8 chars long.");
m_salt = Encoding.ASCII.GetBytes(salt);
}
/// <summary>
/// The salt in ASCII string format
/// </summary>
public string SaltString
{
get
{
return Encoding.ASCII.GetString(m_salt);
}
}
/// <summary>
/// The salt that is used for the key and IV generation.
/// </summary>
public byte[] Salt
{
get
{
return m_salt;
}
}
/// <summary>
/// Encrypt the given string using AES. The string can be decrypted using
/// DecryptStringAES(). The sharedSecret parameters must match.
/// </summary>
/// <param name="plainText">The text to encrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for encryption.</param>
public string EncryptStringAES(string plainText, string sharedSecret)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(plainText), "param plainText can't be null or empty");
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(sharedSecret), "param sharedSecret can't be null or empty");
Guard.Requires<InvalidOperationException>(m_aesAlg != null, "this object is already disposed");
string outStr = null; // Encrypted string to return
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, Salt);
m_aesAlg.Key = key.GetBytes(m_aesAlg.KeySize / 8);
m_aesAlg.IV = key.GetBytes(m_aesAlg.BlockSize / 8);
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = m_aesAlg.CreateEncryptor(m_aesAlg.Key, m_aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
outStr = Convert.ToBase64String(msEncrypt.ToArray());
}
// Return the encrypted bytes from the memory stream.
return outStr;
}
/// <summary>
/// Decrypt the given string. Assumes the string was encrypted using
/// EncryptStringAES(), using an identical sharedSecret.
/// </summary>
/// <param name="cipherText">The text to decrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for decryption.</param>
public string DecryptStringAES(string cipherText, string sharedSecret)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(cipherText), "param cipherText can't be null or empty");
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(sharedSecret), "param sharedSecret can't be null or empty");
Guard.Requires<InvalidOperationException>(m_aesAlg != null, "this object is already disposed");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, Salt);
m_aesAlg.Key = key.GetBytes(m_aesAlg.KeySize / 8);
m_aesAlg.IV = key.GetBytes(m_aesAlg.BlockSize / 8);
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = m_aesAlg.CreateDecryptor(m_aesAlg.Key, m_aesAlg.IV);
// Create the streams used for decryption.
byte[] bytes = Convert.FromBase64String(cipherText);
using (MemoryStream msDecrypt = new MemoryStream(bytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
return plaintext;
}
public void Dispose()
{
if (m_aesAlg != null)
{
m_aesAlg.Clear();
m_aesAlg.Dispose();
m_aesAlg = null;
}
}
}
}
MD5(哈希)示例:
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Synercoding.CodeGuard;
namespace Synercoding.Encryption.Hashing
{
/// <summary>
/// Class to verify and generate MD5 hashes
/// </summary>
public static class MD5Hash
{
/// <summary>
/// Creates a MD5 hexadecimal string based on the input
/// </summary>
/// <param name="input">The string to hash</param>
/// <returns>A MD5 hex string</returns>
public static string GetHash(string input)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
using (MD5 md5Hash = MD5.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
/// <summary>
/// Creates a MD5 hexadecimal string based on the input
/// </summary>
/// <param name="input">The string to hash</param>
/// <returns>A MD5 hash in byte format</returns>
public static byte[] GetByteHash(string input)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
byte[] data;
using (MD5 md5Hash = MD5.Create())
{
// Convert the input string to a byte array and compute the hash.
data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
}
return data;
}
/// <summary>
/// Verifies the input with the hash.
/// </summary>
/// <param name="input">The input to compare</param>
/// <param name="hash">The hash to compare the input with</param>
/// <returns>True is the input validates.</returns>
public static bool VerifyHash(string input, string hash)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(hash), "param hash can't be null or empty");
Guard.Requires<ArgumentNullException>(hash.Length == 32, "param hash must be 32 chars long");
// Hash the input.
string hashOfInput = GetHash(input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
if (0 == comparer.Compare(hashOfInput, hash))
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Verifies the input with the hash.
/// </summary>
/// <param name="input">The input to compare</param>
/// <param name="hash">The hash to compare the input with</param>
/// <returns>True is the input validates.</returns>
public static bool VerifyHash(string input, byte[] hash)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
Guard.Requires<ArgumentNullException>(hash != null, "param hash can't be null");
Guard.Requires<ArgumentNullException>(hash.Length == 128 / 8, "param hash must be 128bits (16 bytes) long");
// Hash the input.
byte[] hashOfInput = GetByteHash(input);
if (hashOfInput.SequenceEqual(hash))
{
return true;
}
else
{
return false;
}
}
}
}
SHA512(哈希)示例:
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Synercoding.CodeGuard;
namespace Synercoding.Encryption.Hashing
{
/// <summary>
/// Class to verify and generate SHA512 hashes
/// </summary>
public static class SHA512Hash
{
/// <summary>
/// Creates a SHA512 hexadecimal string based on the input
/// </summary>
/// <param name="input">The string to hash</param>
/// <returns>A SHA512 hex string</returns>
public static string GetHash(string input)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
using (SHA512 SHA512Hash = SHA512.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = SHA512Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
/// <summary>
/// Creates a SHA512 hash based on the input
/// </summary>
/// <param name="input">The string to hash</param>
/// <returns>A SHA512 hash in byte format</returns>
public static byte[] GetByteHash(string input)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
byte[] data;
using (SHA512 SHA512Hash = SHA512.Create())
{
// Convert the input string to a byte array and compute the hash.
data = SHA512Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
}
return data;
}
/// <summary>
/// Verifies the input with the hash.
/// </summary>
/// <param name="input">The input to compare</param>
/// <param name="hash">The hash to compare the input with</param>
/// <returns>True is the input validates.</returns>
public static bool VerifyHash(string input, string hash)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(hash), "param hash can't be null or empty");
Guard.Requires<ArgumentNullException>(hash.Length == 128, "param hash must be 128 chars long");
// Hash the input.
string hashOfInput = GetHash(input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
if (0 == comparer.Compare(hashOfInput, hash))
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Verifies the input with the hash.
/// </summary>
/// <param name="input">The input to compare</param>
/// <param name="hash">The hash to compare the input with</param>
/// <returns>True is the input validates.</returns>
public static bool VerifyHash(string input, byte[] hash)
{
Guard.Requires<ArgumentNullException>(!string.IsNullOrEmpty(input), "param input can't be null or empty");
Guard.Requires<ArgumentNullException>(hash != null, "param hash can't be null");
Guard.Requires<ArgumentNullException>(hash.Length == 512 / 8, "param hash must be 512bits (64 bytes) long");
// Hash the input.
byte[] hashOfInput = GetByteHash(input);
if (hashOfInput.SequenceEqual(hash))
{
return true;
}
else
{
return false;
}
}
}
}
出于教学目的,您可以使用 .net 文件加密系统(非常简单!!)
System.IO.File.Encrypt("file.txt")
System.IO.File.Decrypt("file.txt")
文件可以仅从同一台机器解密。