这是在Db中加密和存储密码的方法吗?

有几种方式(即使在这里也是如此)并且他们都提到在数据库上保存密码的最佳方法是保存密码,而不是密码,而是存储盐渍密码的哈希值

我的问题很简单,把一些代码放在上面,这是正确的方法吗?

string username = "myUsr"; string password = "myPwd"; DateTime createDate = DateTime.UtcNow; // Salt it string saltedPwd = String.Concat(password, createDate.Ticks.ToString()); // Hash it HMACSHA1 hash = new HMACSHA1(Encoding.Unicode.GetBytes(Helper.EncryptKey)); string encodedPwd = Convert.ToBase64String( hash.ComputeHash(Encoding.Unicode.GetBytes(saltedPwd))); // Create User in the database db.CreateUser(username, encodedPwd, createDate); 

数据库用户表

 user_id | username | password | create_date | last_access | active 

并在登录时使用再次执行该过程并检查encodedPwd是否与提供的盐渍密码相同。

我唯一担心的是, 这是加密密码的最佳方法吗? 是否可以使用创建日期(因为它总会改变,我读到每次编码密码时最好总是使用不同的salt

或者salt应该是一个完全不同的变量?

您的实现可能已经足够好了,但是使用具有更多熵的盐会更好:您当前使用的滴答值始终处于相对较小的范围内。

我建议使用像PBKDF2这样的东西来为你做,通过Rfc2898DeriveBytes

 string username = "myUsr"; string password = "myPwd"; using (var deriveBytes = new Rfc2898DeriveBytes(password, 20)) // 20-byte salt { byte[] salt = deriveBytes.Salt; byte[] key = deriveBytes.GetBytes(20); // 20-byte key string encodedSalt = Convert.ToBase64String(salt); string encodedKey = Convert.ToBase64String(key); // store encodedSalt and encodedKey in database // you could optionally skip the encoding and store the byte arrays directly db.CreateUser(username, encodedSalt, encodedKey); } 

并进行身份validation……

 string username = "myUsr"; string password = "myPwd"; string encodedSalt, encodedKey; // load encodedSalt and encodedKey from database for the given username byte[] salt = Convert.FromBase64String(encodedSalt); byte[] key = Convert.FromBase64String(encodedKey); using (var deriveBytes = new Rfc2898DeriveBytes(password, salt)) { byte[] testKey = deriveBytes.GetBytes(20); // 20-byte key if (!testKey.SequenceEqual(key)) throw new InvalidOperationException("Password is invalid!"); } 

我想知道为什么没人提到BCrypt 。 C#有一个随时可用的实现。 请参阅http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx

如果有针对您的问题的校对解决方案,请不要重新发明轮子。

你的方法完全没问题,但是假设某人有你的数据库,但不是你的代码库。 他们基本上可以弄清楚你只是简单地连接密码和创建日期,他们可以对所有密码进行反向工程。

您可能希望进一步注入仅存在于代码库中的唯一字符串,以获得额外的保护。

 string username = "myUsr"; string password = "myPwd"; DateTime createDate = DateTime.UtcNow; // Salt it string saltedPwd = String.Concat(password, SomeOtherClass.StaticKey, createDate.Ticks.ToString()); public class SomeOtherClass { public static string StaticKey = "#$%#$%superuniqueblahal$#%@#$43580"; // should probably be const/readonly, but whatever } 

你怎么试试: ProtectedData.Protect方法?

此方法可用于加密密码 ,密钥或连接字符串等数据。 optionalEntropy参数使您可以添加数据以增加加密的复杂性 ; 指定null,没有额外的复杂性。 如果提供,则在使用Unprotect方法解密数据时也必须使用此信息。

我认为使用CreateDate的想法非常强大,但是当有人窃取你的数据库和代码时,你的盐就会暴露出来。 基于“没有人可以扼杀我的代码”的安全性是不好的安全性。

您可以简单地对密码进行双重哈希…并在第一次散列时使用salt。

 string Flavor(string passwd) { string fhash = Str2SHA1(passwd); string salt = fhash[2] + fhash [10] + fhash[1]; // or whatever... string realhash = Str2SHA1(hash + salt); } string Str2Sha1(string str){ ... }