【问题标题】:Compare two hashed password using same salt using SHA-256 algorith in Java, Spring security?使用 Java 中的 SHA-256 算法比较两个使用相同盐的哈希密码,Spring 安全性?
【发布时间】:2023-04-03 00:02:01
【问题描述】:

在需要检查来自 UI 表单(即 Authentication 对象)的密码的情况下,我需要一些指导,我需要使用 SHA-256 + constant salt(在进行比较之前)和密码来自 DB(DB还具有使用 Spring Security 的哈希密码 + salt)。

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

【问题讨论】:

  • 我不确定你在问什么。您使用字符串相等比较密码。 dbPassword.equals(inputPassword),两者都是加盐和散列的。
  • 我正在寻找使用 SHA-256 算法比较从相同盐生成的两个不同哈希值。请用代码指导。谢谢,内哈
  • 提供一个例子,因为这个问题看起来很混乱。如果 SHA-256 的输入不同,则输出也会不同。 SHA-256 没有“盐”,而 HMAC 有,请解释一下盐。请提供一些代码。

标签: java spring-security sha256


【解决方案1】:

您可以简单地比较两个密码字符串passwordA.equals(passwordB) ...

这有一些安全缺陷:

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

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

  3. 使用标准工具来做与安全相关的事情可能是明智的(即使它们看起来很简单)。 Spring security 有很多工具可以为您做到这一点。例如,看看BCryptPasswordEncoder。出于安全目的使用经过良好测试和维护的框架始终是一个好主意。

     BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
     String hashedPassword = passwordEncoder.encode(password);
     ...
     boolean result = passwordEncoder.matches(rawPassword, hashedPassword);
    

另外:使用适当的密码哈希算法! See this Answer on SO for some proposals

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

【讨论】:

    【解决方案2】:

    在我看来,您希望比较使用相同盐创建的两个单独的散列值。我对吗 ?如果是,那么这里是引用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..
    

    【讨论】:

    • 请添加关于盐如何与密码一起使用的说明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 2014-08-19
    • 1970-01-01
    • 2010-09-28
    相关资源
    最近更新 更多