有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

无法将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) 个答案

  1. # 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解码