没有salt的sha-256并不总是返回相同的哈希值

时间:2016-11-03 10:03:26

标签: java encryption sha256 sha jasypt

有谁能告诉我为什么以下代码并不总是返回相同的哈希? AFAIK哈希可能不同的唯一方法是由于随机盐,但根据文档我通过将盐大小设置为0来禁用盐。

public static void main(String[] args ) {
    char[] password = "test_pass".toCharArray();
    String str = encodePassword(password);

    System.out.printf(
        "Byte digest '%s'\n", 
        String.valueOf(Hex.encodeHex(Base64.decodeBase64(str)))
    );
}

static StandardByteDigester digester = new StandardByteDigester();
{
    digester.setAlgorithm("SHA-256");
    digester.setIterations(100000);
    digester.setSaltSizeBytes(0);
    digester.initialize();
}

public static String encodePassword(char[] rawPass) {
    return new String(Base64.encodeBase64(digester.digest(toBytes(rawPass))));
}

public static byte[] toBytes(char[] ch) { 
    Charset charset = Charset.defaultCharset();
    ByteBuffer buff = charset.encode(CharBuffer.wrap(ch));
    byte[] tmp = new byte[buff.limit()];
    buff.get(tmp);
    return tmp;    
}

1 个答案:

答案 0 :(得分:3)

您的错误与您在实例初始化程序块而非静态初始化程序块中初始化静态字段StandardByteDigester digester这一事实有关,因此它是永远不会打电话,因为你永远不会创建你的类的实例,所以最后它使用默认配置和随机盐。

试试这个:

static {
    digester.setAlgorithm("SHA-256");
    digester.setIterations(100000);
    digester.setSaltSizeBytes(0);
    digester.initialize();
}

如果您的方法encodePassword使用String代替char数组,您的代码可以简化,因为您只需将getBytes(Charset)称为下一个:

public static String encodePassword(String rawPass) {
    return new String(
        Base64.encodeBase64(digester.digest(rawPass.getBytes(StandardCharsets.UTF_8))),
        StandardCharsets.US_ASCII
    );
}

NB:依靠平台的默认字符集不是一个好习惯,因为您的代码将依赖于平台,所以这里基础64个字符都包含在US_ASCII中,让我们使用这个charset进行解码。