【问题标题】:Unable To Convert C# Encryption/Hashing into Java Encryption/Hashing for Android无法将 C# 加密/哈希转换为 Android 的 Java 加密/哈希
【发布时间】:2017-09-19 13:42:38
【问题描述】:

我目前有一个代码用于为我的网站生成哈希值,它使用 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 用于当前的“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);
    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# 代码...由于数据库中当前散列密码的数量很大。 ..

更新

我忘了说我的 SALT SIZE 是“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# 生成的 Hash,只是不太准确,我会再努力一点

public String SaltedHash(String password)
{
    Hash = new String(Base64.encodeToString(ComputeHash(password.toCharArray(), Salt.getBytes()), Base64.DEFAULT));
    return Hash;
}

【问题讨论】:

  • "示例:Password = SaltedHash(PasswordTxt);" - 至少应该是 == 而不是 =

标签: java c# android encryption 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,但您使用 默认字符编码(可能是 UTF-8)来解码 salt在 Java 中 (Salt.getBytes())。您必须使用相同的解码,这意味着您必须从 Java 中的 Base64 解码。

【讨论】:

  • 有什么方法可以改变 PBEKeySpec 上的字节数?因为如果我在 C# 上更改一个,那会影响成千上万个已经散列的密码,感谢您的努力 :) 现在至少我知道可能导致不匹配,不用担心;)我不反对这个;)
  • 我尝试更改新的 PBEKeySpec(password, salt, 1000, 2048),但它给了我一个新错误,真的很奇怪,2048bits = 256bytes 对吗?
  • @GabrielValdezTimbol 你应该告诉我们新的错误。
  • 我的 SQL 查询出错,它说我有一个“语法错误”,因此,为了缩小范围,我尝试获取 java 给出的 HASH 并查看它是否与C# 手动散列,可惜Java HASH 100% off,而且还有很多“?”
  • 我尝试在将 C# 代码的字节降低到 32 时进行“测试运行”,不幸的是,当我这样做时,由于某种原因哈希仍然不匹配,Java 哈希仍然太短了,我只是在测试环境中试了一下,看看它是否会产生至少一点好的输出
猜你喜欢
  • 2011-09-30
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-20
  • 2011-12-03
  • 2016-10-29
相关资源
最近更新 更多