java - 无法将 C# 加密/哈希转换为适用于 Android 的 Java 加密/哈希

标签 java c# android encryption hash

我目前有一个用于为我的网站制作哈希的代码,该代码使用 SALT 进行哈希处理,因此密码是不可逆的......

目前它是 100% 为我的网站工作,它是使用 ASP.NET(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));
    }
}

我在登录时使用它的方式是从数据库中的帐户获取存储的 SALT,并将该 SALT 用于当前“C​​omputeHash”

在我得到计算出的散列后,我只是检查它是否与数据库中的散列相匹配......

示例:密码 = 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);
    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();
    }
}

这个设计的工作方式完全相同,但不幸的是,由于某种原因我不断得到不同的 HASH,有人可以帮我指出我的 Java 代码有什么问题吗?

这已经花了我 2 周的时间,但我仍然无法使其正常工作......而且我不想更改/修改 C# 代码......由于数据库中当前散列密码的数量很大。 ..

更新

我忘了说我的盐量是“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);
}

更新

我对 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 解码。

关于java - 无法将 C# 加密/哈希转换为适用于 Android 的 Java 加密/哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43561598/

相关文章:

java - 如何在多线程java中插入数据库

c# - Entity Framework ,更新相关对象时出现问题

java - 在java中从csv中读取带逗号的值

javascript - 使用 WebView 获取 android 的 JavaScript 值

android - OnClick 不会在自定义 Button 类中触发,而是在父类中触发

java - 测试文件系统交互 : Setting file permissions

java - 如何在Java中为框架设置图标?

java - LibGdx:使用手势监听器

c# - 如何使用不明确的泛型参数指定 C# 返回值?

c# - C# GUI 类如何从工作类接收定期更新?