代码之家  ›  专栏  ›  技术社区  ›  anon

我可以使用对象哈希码来存储密码的哈希吗?

  •  8
  • anon  · 技术社区  · 14 年前

    为了保存一个文件,我定义了以下方法

    public int encrypt(String fileName, String password) {
       return (fileName.concat(password)).hashCode();
    }
    

    这将返回存储在文件中的哈希值。每当用户想要访问该文件时,他输入密码,如果生成相同的哈希,他就可以访问该文件。

    我想这不是很安全,但它有多安全?字符串哈希代码生成具有两个不同输入的相同哈希的可能性有多大?

    编辑:

    根据你的回答,我更改了密码:

    public String encrypt(String password) {
            String hash = "";
            try {
                MessageDigest md5 = MessageDigest.getInstance("SHA-512");
                byte [] digest = md5.digest(password.getBytes("UTF-8"));
                hash = Arrays.toString(digest);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return hash;
        }
    

    所以现在应该更好了??

    8 回复  |  直到 14 年前
        1
  •  17
  •   Jon Skeet    14 年前

    这是一个坏主意——您应该像nulluserexception所说的那样使用一个普通的加密散列,如sha-1。

    然而,它 便于携带-文档用于 String.hashCode() 明确说明算法。任何正确实现文档的JRE都应该给出相同的哈希代码。但是,因为这样 hashCode() 他的算法可以工作,很容易找到一个字符串,它可以生成任何特定的哈希代码——甚至是以特定前缀开头的哈希代码——所以知道哈希的攻击者可以非常容易地攻击您的应用程序。加密散列被设计成很难设计密钥来匹配特定散列。

        2
  •  5
  •   tobiasbayer    14 年前

    依靠非加密函数来服务与安全相关的目的通常是一个坏主意。因为您永远无法确定使用哪个实现(并且将来将使用哪个实现)来计算字符串的哈希代码,所以您应该更喜欢加密的安全哈希代码算法。我建议使用sha-1或sha-256。 http://www.bouncycastle.org/ 有许多哈希算法的实现。

        3
  •  5
  •   Gilles 'SO- stop being evil'    14 年前

    String.hashCode 不适用于哈希密码。您需要一个加密哈希。

    字符串代码 设计得非常快。它主要用于哈希表中的键。在这种情况下,偶尔发生碰撞不是问题。加密散列的计算速度较慢,但根据定义,没有人知道如何为良好的加密生成冲突。

    更重要的是,考虑到 password.hashCode() ,有可能找到 password (具有很高的可信度,但由于许多密码具有相同的哈希值,因此不确定)。这不是你想发生的事。另一方面,密码散列的设计使得不可能在知道散列的情况下找到密码(从数学上讲,没有人知道如何在一生中从散列中找到密码)。

    加密散列在Java标准库中可用,通过 java.security.MessageDigest .

    补充 :还有一个复杂的问题:直接散列密码是个坏主意。原因是攻击者可以尝试所有可能的密码(例如字典单词、人名等)。此问题的标准解决方案是将密码与 随机的 字符串称为 salt 在计算散列值之前:你做一些像 sha.digest((salt+password).getBytes()) . salt使得攻击者预先计算所有可能密码的散列是不明智的。

    通常,salt是在用户选择他/她的密码时随机生成的,它存储在用户数据库的密码散列旁边,但是根据您所展示的方案,没有这样的东西。根据您的设计,使用文件名作为salt是合理的: fileName.concat(encrypt(fileName + password)) .

        4
  •  2
  •   NullUserException Mark Roddy    14 年前

    老实说,我不知道JAVA如何抵御碰撞。 hashCode() 是。如果我猜的话,我会说不是很。我以前测试过它,在仅仅几十万次输入之后发现了一些碰撞。

    因为您在这里处理密码,所以应该使用像sha1这样的加密散列。

        5
  •  2
  •   Shawn D.    14 年前

    散列数据并不像你想象的那么难,最好使用真正的散列算法。如果您有一个包含密码的字节数组,您可以这样做。如果要从字符串中获取字节数组,请确保在调用getbytes()时指定编码(即utf-8);

    下面是一个使用MD5的简单示例。

        try {
            MessageDigest md5 = MessageDigest.getInstance( "MD5" );
    
            byte [] digest = md5.digest( data );
    
            return digest;
        } catch( java.security.NoSuchAlgorithmException ex ) {
            // Insert error handling here.
        }
    
        6
  •  1
  •   Kirk Woll    14 年前

    我担心这个代码是不可移植的。不能保证一个JVM将产生与另一个JVM相同的哈希值。这似乎很危险。

        7
  •  1
  •   BenoitParis    14 年前

    以下是string.hashcode()的实现:

    S[0]*31^(n-1)+S[1]*31^(n-2)+…+S[N-1 ]

    公共可用 here

    这实际上是VM无关的,而且它过去还没有依赖Java版本。实现保持不变。

    碰撞安全没有问题,但是出于明显的原因,将其用于加密目的是一个坏主意。

        8
  •  0
  •   irreputable    14 年前

    问题是哈希值只有32位。太短了。一个有基础的孩子能在一秒钟内打破它。

    MD5的长度是128位,现在被认为是弱的。