我一直在谷歌搜索只是为了一个简单的加密和解密方法来存储密码。我不是在寻找一种非常复杂的加密技术,所以我想这就是让它很难找到的原因。
有没有人可以与我分享任何简单的加密和解密方法?
答案 0 :(得分:3)
例如,您应该使用SHA256哈希密码。要检查密码有效性,请对从用户收到的密码进行哈希处理,并将其与存储在数据库中的哈希值进行比较。
也就是说,您应该确保通过SSL发送密码或者可以捕获密码。如果您自己的操作系统不安全,则密码可能会在到达时以明文形式捕获。
当您的网站位于Intranet上时,最好使用Windows集成身份验证。对于互联网,OAuth可能被证明是更好的选择。
感谢@philsoady指出https://security.stackexchange.com/questions/35250/hmacsha512-versus-rfc2898derivebytes-for-password-hash进一步阅读。
答案 1 :(得分:1)
如果使用加密,则需要密钥。可以使用此密钥并将其用于解密密码。最有可能的是,组织内的人员可以访问此密钥。这意味着每个人都有可能知道您的用户密码。
哈希设计为单向线性变换。因此,您无法倒退并获得实际密码。可以通过以下方式演示一个简单的哈希算法:使用将密码除以6的其余部分。假设您的密码为10.您将在数据库中存储4,因为10/6的余数为4。如果您在数据库中看到4,你不能倒退并弄清楚你有10,因为它也可能是4或16(或无限多的其他)。但是,通过传入10,您可以验证这与存储在数据库中的4相同。您可能会注意到这里存在的固有缺陷。如果您使用16作为密码,它仍将在数据库中匹配。这被称为碰撞。
建议您使用大于SHA128(128位输出)的散列算法,因为在您发现碰撞之前搜索是不可行的。 SHA算法是为速度而设计的,所以这些对你来说仍然足够快(你说它很轻)。另外,有些人会生成一组已知的流行密码及其哈希值(通常称为rainbow tables
),用于快速交叉引用存储的值。
为了更加安全,请为每个用户创建一个唯一值(通常称为salt
),在散列之前应将其附加到密码的开头或结尾。例如,salt值为salt
,密码为password
,因此我们将哈希saltpassword
并存储结果。然后,当用户再次登录时,我们会将生成的哈希与存储的值进行比较。这个更好的原因是在两个用户拥有相同密码的情况下,它们将具有两个不同的唯一哈希值。
一个小代码示例:
using System.Security.Cryptography;
private string HashPassword(string password, string salt)
{
string hashedString = CryptoConfig.CreateFromName("SHA256")
.ComputeHash(salt+password);
return hashedString;
}
基本上,使用加密意味着可以发现密码。使用散列意味着你无法找到它们是什么,只是找到一个潜在的碰撞(除非你真的很幸运)。
答案 2 :(得分:1)
正如oscar132在评论中解释的那样,你不应该尝试重塑会员资格。
ASP.NET有一个非常好的成员资格提供程序作为默认选项,不需要那么多配置。它拥有良好密码管理所需的一切:用户管理,密码重置,集成Web控制,......
它也不会使用非常不安全的加密方法,而是使用已推荐的SHA256方法对密码进行哈希处理,并选择使用自定义提供程序来增强加密算法,如PBKDF2或bcrypt。
即使您的项目已在进行中,添加对它的支持并不难。 Visual Studio默认支持将asp.net网站升级为实现成员资格的asp.net Web表单应用程序。
答案 3 :(得分:1)
真的不是一个问题,但是其他人会发现这个问题。 有些人会做和做。这里可能缺少本土种植的网站。
如果认真的应用程序考虑使用SCyrpt for c# 标准c#中的最低来编码密码应该是这样的 以下使用Rfc2898。
a)将编码密码和随机SALT存储在您的数据库中 b)使用至少250毫秒的成本 c)将用户提供的密码与存储的SALT比较到相同的例程并比较哈希值。
private string PasswordEncode(string password, byte[] salt ) {
var deriver2898 = new Rfc2898DeriveBytes(password, salt,64000); // approx 300msecs
byte[] hash = deriver2898.GetBytes(20); //
// return hash;
// If you dont like storing bytes, use a string
return Convert.ToBase64String(hash);
}
// himalayan pink rock salt... the best kind
public byte[] GenerateSalt(int size = 64) {
using (var crypto = new RNGCryptoServiceProvider()) {
var bytes = new byte[size];
crypto.GetBytes(bytes); //get a bucket of very random bytes
return bytes;
}
}
如果您在此阶段仍然确信您需要加密,那么请使用Microsoft的一种对称算法。 EG AesManaged
/// <summary>
/// Encrypt using preferred provider.
/// </summary>
/// <typeparam name="T">AesManaged,TripleDESCryptoServiceProvider,RijndaelManaged</typeparam>
/// <param name="value">Value to be encrypted</param>
/// <param name="decryptionKey">secret key .. see machine key descryptionKey</param>
/// <param name="salt">salt for process</param>
/// <returns></returns>
public string Encrypt<T>(string value, string salt, string decryptionKey)
where T : SymmetricAlgorithm, new() {
var derivedKey = GenerateKey(decryptionKey, salt);
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = derivedKey.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIv = derivedKey.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIv);
using (var buffer = new MemoryStream()) {
using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write)) {
using (var writer = new StreamWriter(stream, Encoding.Unicode)) {
writer.Write(value);
}
}
// before finished with the buffer return, now as the stream is now closed
return Convert.ToBase64String(buffer.ToArray());
}
}
public string Decrypt<T>(string text, string salt, string decryptionKey)
where T : SymmetricAlgorithm, new() {
// could catch errors here, and return a null string. ?
// "CryptographicException: Padding is invalid and cannot be removed"
// can occur if there is a coding problem , such as invalid key or salt passed to this routine.
var derivedKey = GenerateKey(decryptionKey, salt);
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = derivedKey.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIv = derivedKey.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateDecryptor(rgbKey, rgbIv);
using (var buffer = new MemoryStream(Convert.FromBase64String(text))) {
using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Read)) {
using (var reader = new StreamReader(stream, Encoding.Unicode)) {
return reader.ReadToEnd(); // error here implies wrong keys supplied , and code or environment problem.. NASTY issue
}
}
}
}
public DeriveBytes GenerateKey(string salt, string decryptionKey) {
// generate the key from the shared secret and the salt
var saltAsByteArray = salt.UTF8StringToByteArray();
var key = new Rfc2898DeriveBytes(decryptionKey, saltAsByteArray);
return key;
}
示例调用:加密和解密。另外,请考虑how to get machine key and use as key here
Encrypt<AesManaged>(password, salt, decryptionKey);
Decrypt<AesManaged>(encryptedPassword, salt, decryptionKey);