【问题标题】:Checking user password on Android在 Android 上检查用户密码
【发布时间】:2016-02-19 11:59:47
【问题描述】:

我正在为我正在开发的 Android 应用程序编写密码安全实用程序类。目前,它生成一个盐,然后使用该盐和密码作为参数生成一个散列。我需要一种方法,将存储在数据库中的哈希值与用户尝试登录时创建的哈希值进行比较。我应该使用Arrays.equals() 比较两个字节数组吗? 还是应该将byte[] dbHashString passwordbyte[] salt 作为参数并从那里开始?

这是目前为止的代码。

package fitfast.security;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Arrays;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public final class Authenticator {

    private static final int length = 512;
    private static final int iterations = 60000;

    public static byte[] generateHash(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
        String algorithm = "PBKDF2WithHmacSHA512";
        KeySpec sp = new PBEKeySpec(password.toCharArray(), salt, iterations, length);
        SecretKeyFactory kf = SecretKeyFactory.getInstance(algorithm);
        return kf.generateSecret(sp).getEncoded();
    }

    public static byte[] generateSalt() throws NoSuchAlgorithmException {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        byte[] salt = new byte[8];
        sr.nextBytes(salt);
        return salt;
    }

    public static boolean check(byte[] hash, String password, byte[] salt) {

        //code goes here

    }

}

【问题讨论】:

    标签: java cryptography passwords pbkdf2


    【解决方案1】:

    我会说Arrays.equals() 将是要走的路。类似的东西

    public static boolean check(byte[] hash, String password, byte[] salt) {
    
       return Arrays.equals(hash, generateHash(password,salt));
    
    }
    

    【讨论】:

      【解决方案2】:

      虽然机会非常渺茫,但攻击者可能能够利用Arrays.equals 比较两个哈希的方式。该函数以迭代方式工作,并在找到不同字节后立即返回。攻击者可能会尝试不同的密码并观察不同的响应时间。这将意味着哈希的第一个字节匹配(假设 PBKDF2 始终采用相同的时间)。这可以重复多次,直到匹配的密码被暴力破解。

      有多种以时间常数方式比较数组的方法。我喜欢对两个数组的每个字节进行异或运算,并将结果字节数组或运算成一个字节。如果该字节为 0,则两个数组相等:

      public static boolean check(byte[] hash, String password, byte[] salt) {
          byte[] generatedHash = generateHash(password,salt);
          byte result = (byte)0;
          for(int i = 0; i < hash.length; i++) {
              result |= hash[i] ^ generatedHash[i];
          }
          return result == (byte)0;
      }
      

      【讨论】:

      • 啊,是的。我已经读到这是一个潜在的问题。谢谢你的建议!
      猜你喜欢
      • 2016-12-13
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 2013-02-06
      • 1970-01-01
      • 2010-09-28
      • 2018-09-24
      相关资源
      最近更新 更多