使用Java中的SHA-256算法,Spring安全性,使用相同的盐比较两个散列密码?

时间:2015-12-29 17:03:20

标签: java spring-security sha256

我需要一些指导,我需要检查来自UI表单的密码(即Authentication对象),我需要使用SHA-256 + constant salt进行哈希(在进行比较之前)并输入密码使用Spring Security从DB(DB也有密码+盐)。

我希望比较使用相同的 SALT 值生成的这两个不同的散列值。我们如何在java中做到这一点?有人可以分享一下示例代码吗?

2 个答案:

答案 0 :(得分:5)

您只需比较两个密码字符串passwordA.equals(passwordB) ...

这存在一些安全缺陷:

  1. 密码不应作为字符串处理,而应作为字符或字节数组处理:see here why

  2. 同等比较(理论上)容易受到时间攻击的影响:see a discussion about a solution in java

  3. 使用标准工具来做与安全相关的事情(即使它们似乎很简单)也许是明智之举。 Spring安全有很多工具可以帮到你。例如,请查看BCryptPasswordEncoder。出于安全目的使用经过良好测试和维护的框架总是一个好主意。

     BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
     String hashedPassword = passwordEncoder.encode(password);
     ...
     boolean result = passwordEncoder.matches(rawPassword, hashedPassword);
    
  4. :使用正确的密码哈希算法! See this Answer on SO for some proposals

    SHA-256不是其中之一。 Spring Security为您提供了适合工作的工具,因此您可以使用它们。

答案 1 :(得分:0)

在我看来,您希望比较使用相同盐创建的两个单独的散列值。我对吗 ?如果是,那么这是示例程序从https://ashishpshukla.wordpress.com/2010/07/02/sample-java-code-for-password-encryption-using-secure-hash-algorithm-sha-256/

获取参考
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class PasswordEncoder {
    private static PasswordEncoder instance;
    private final static int ITERATION_COUNT = 5;

    private PasswordEncoder() {  }

    public static synchronized PasswordEncoder getInstance() {
        if (instance == null) {
            PasswordEncoder returnPasswordEncoder = new PasswordEncoder();
            return returnPasswordEncoder;
        }
        else
            return instance;
    }

    public synchronized String encode(String password, String saltKey)throws NoSuchAlgorithmException, IOException {
        String encodedPassword = null;
        byte[] salt = base64ToByte(saltKey);

        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        digest.reset();
        digest.update(salt);

        byte[] btPass = digest.digest(password.getBytes("UTF-8"));
        for (int i = 0; i < ITERATION_COUNT; i++) {
            digest.reset();
            btPass = digest.digest(btPass);
        }

        encodedPassword = byteToBase64(btPass);
        return encodedPassword;
    }

    private byte[] base64ToByte(String str) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] returnbyteArray = decoder.decodeBuffer(str);
        return returnbyteArray;
    }

    private String byteToBase64(byte[] bt) {
        BASE64Encoder endecoder = new BASE64Encoder();
        String returnString = endecoder.encode(bt);
        return returnString;
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
        String password = "Secrete@343";
        String saltKey = "PveFT7isDjGYFTaYhc2Fzw==";
        String hash1,hash2 = null;

        // Assume from UI
        PasswordEncoder encoder1 = PasswordEncoder.getInstance();
        hash1 = encoder1.encode(password, saltKey);
        System.out.println(hash1);

        // Assume the same present in db
        PasswordEncoder encoder2 = PasswordEncoder.getInstance();
        hash2 = encoder2.encode(password, saltKey);
        System.out.println(hash2);

        if(hash1.equalsIgnoreCase(hash2))
            System.out.println("Both hash Matches..");
        else
            System.out.println("Hash matches fails..");
    }
}

输出:

8WgbLik5EbdtJY4OWm2ZQ0tHiU2lmvXNVrPhFDz3W2Y=
8WgbLik5EbdtJY4OWm2ZQ0tHiU2lmvXNVrPhFDz3W2Y=
Both hash Matches..