无法将C#加密/哈希转换为Android的Java加密/哈希
我目前有一个为我的网站做哈希的代码,它用盐哈希,所以密码是不可逆的
目前,它是100%为我的网站是使用ASP编码工作。净(C#)
这是我的密码
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));
}
}
当iam登录时,我使用它的方式是从数据库中的帐户获取存储的SALT,并将该SALT用于当前的“ComputeHash”
在我得到一个计算出的哈希值后,我只是检查它是否与数据库中的哈希值匹配
示例:Password=SaltedHash(PasswordTxt)
然后我用SQL查询将其与我当前的哈希进行比较,它的效果是100%
仅供参考——所有SALT都是随机生成的,并存储在数据库中
现在。。。我正在制作一个安卓应用程序,它使用完全相同的东西,但不幸的是,每当我试图让它工作时,它都会给我一个不同的哈希值
这是我目前的代码
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);
try
{
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();
}
}
这一个被设计成完全相同的工作方式,但不幸的是,出于某种原因,我一直得到不同的哈希值,有人能帮我指出我的java代码有什么问题吗
这已经花了我20周的时间,我仍然无法让它正常工作。。。。我不想改变/修改C代码。。。由于数据库中存在大量当前哈希密码
更新
我忘了说我的盐量是“70”
这是我用来在C中生成随机salt的代码#
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);
}
更新
我对JAVA代码做了一些调整,现在散列看起来更像C#生成的散列,只是没有那么准确,我将继续工作
public String SaltedHash(String password)
{
Hash = new String(Base64.encodeToString(ComputeHash(password.toCharArray(), Salt.getBytes()), Base64.DEFAULT));
return Hash;
}
# 1 楼答案
rfc2898DeriveBytes.GetBytes(256)
意味着您将获得256个字节new PBEKeySpec(password, salt, 1000, 256)
意味着您将获得256位将其更改为
rfc2898DeriveBytes.GetBytes(32)
,因为256字节太大了,安全性改进实际上可能是负面的。更重要的是,在计算的哈希和存储的哈希之间实现一个恒定时间比较函数。如果不这样做,可能会强行输入密码另一个问题是,在C#(
var saltBytes = Convert.FromBase64String(salt);
)中解码Base64中的salt,但在Java(Salt.getBytes()
)中使用默认字符编码(可能是UTF-8)来解码salt。您必须使用相同的解码,这意味着您必须在Java中从Base64解码