我目前有一个用于为我的网站制作哈希的代码,该代码使用 SALT 进行哈希处理,因此密码是不可逆的......
目前它是 100% 为我的网站工作,它是使用 ASP.NET(C#) 编码的
đây là mã của tôi
public string SaltedHash(string password)
{
Salt = RandomString;
Hash = ComputeHash(Salt, password);
return Hash;
}
static string ComputeHash(string salt, string password)
{
var saltBytes = Convert.FromBase64String(salt);
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, saltBytes, 1000))
{
return Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256));
}
}
我在登录时使用它的方式是从数据库中的帐户获取存储的 SALT,并将该 SALT 用于当前“ComputeHash”
在我得到计算出的散列后,我只是检查它是否与数据库中的散列相匹配......
示例:密码 = SaltedHash(PasswordTxt);
然后我使用 SQL 查询将它与我当前的哈希进行比较,它 100% 有效
仅供引用 - 所有 SALT 都是随机生成并存储在数据库中
现在...我正在制作一个使用完全相同的东西的 android 应用程序,但不幸的是,每当我尝试让它工作时,它都会给我一个不同的 HASH
这是我当前的代码
public String SaltedHash(String password)
{
Hash = new String(ComputeHash(password.toCharArray(), Salt.getBytes()));
return Hash;
}
public static byte[] ComputeHash(char[] password, byte[] salt)
{
PBEKeySpec spec = new PBEKeySpec(password, salt, 1000, 256);
Arrays.fill(password, Character.MIN_VALUE);
thử
{
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
return skf.generateSecret(spec).getEncoded();
}
catch (NoSuchAlgorithmException | InvalidKeySpecException e)
{
throw new AssertionError("Error while hashing a password: " + e.getMessage(), e);
}
finally
{
spec.clearPassword();
}
}
这个设计的工作方式完全相同,但不幸的是,由于某种原因我不断得到不同的 HASH,有人可以帮我指出我的 Java 代码有什么问题吗?
这已经花了我 2 周的时间,但我仍然无法使其正常工作......而且我不想更改/修改 C# 代码......由于数据库中当前散列密码的数量很大。 ..
gia hạn
我忘了说我的盐量是“70”
这是我用来在 C# 中生成随机盐的代码
void GenerateRandomSalt()
{
//Create and populate random byte array
byte[] randomArray = new byte[70];
//Create random salt and convert to string
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomArray);
RandomString = Convert.ToBase64String(randomArray);
}
gia hạn
我对 JAVA 代码做了一点调整,现在 HASH 看起来更像 C# 生成的哈希,只是不够准确,我会再努力一点
public String SaltedHash(String password)
{
Hash = new String(Base64.encodeToString(ComputeHash(password.toCharArray(), Salt.getBytes()), Base64.DEFAULT));
return Hash;
}
rfc2898DeriveBytes.GetBytes(256)
表示您获得 256 个字节。 new PBEKeySpec(password, salt, 1000, 256)
表示您获得 256 个位。
将其更改为 rfc2898DeriveBytes.GetBytes(32)
,因为 256 字节太大,安全性改进实际上可能是负面的。在计算出的哈希值和存储的哈希值之间实现一个恒定时间的比较函数要重要得多。如果不这样做,则可能会暴力破解密码。
另一个问题是您在 C# 中从 Base64 解码盐 (var saltBytes = Convert.FromBase64String(salt);
),但您使用的是 默认字符编码(可能是 UTF-8)来解码 Java 中的盐 (Salt.getBytes()
)。您必须使用相同的解码,这意味着您必须从 Java 中的 Base64 解码。
Tôi là một lập trình viên xuất sắc, rất giỏi!