在Node.js中复制Java密码散列代码(PBKDF2WithHmacSHA1) [英] Replicating Java password hashing code in Node.js (PBKDF2WithHmacSHA1)

查看:273
本文介绍了在Node.js中复制Java密码散列代码(PBKDF2WithHmacSHA1)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:我的问题已更新,请检查此帖子的底部以获取最新的问题。我将其余的内容留给了那些想阅读整篇文章的人:)



我一直在努力将一个小的Java应用程序转换为Node.js ,这在很大程度上一直很好。我不得不查找很多Java函数来弄清楚他们在做什么以及如何在Node中复制它们的行为(因为我几乎没有任何Java经验),但是我现在获得了大部分功能。

不幸的是,有一点我似乎无法工作。它是一种用于生成密码哈希的方法,它使用一组似乎不存在于Node中的高级Java特定函数。我一直在尝试两天来完成这项工作,但我无法得到我想要的结果。



这是原始的Java代码:

  public static String hashPassword(final String password,final String salt)throws NoSuchAlgorithmException,InvalidKeySpecException {
final char [] passwordChars = password。 toCharArray();
final byte [] saltBytes = salt.getBytes();
final PBEKeySpec spec = new PBEKeySpec(passwordChars,saltBytes,1000,192);
final SecretKeyFactory key = SecretKeyFactory.getInstance(PBKDF2WithHmacSHA1);
final byte [] hashedPassword = key.generateSecret(spec).getEncoded();
return String.format(%x,new BigInteger(hashedPassword));
}

注意:salt是一个固定值,它不是随机的。我知道这不是应该如何,但这是如何设置应用程序。所以,由于Java代码总是得到相同的结果,所以应该可以在Node中得到相同的结果。



我试过使用 crypto.pbkdf2 ,使用看似相似的各种密码,但这一切给我的结果都不同于Java代码。所以我想我会问在这里,看看有没有人知道如何做到这一点,或者有任何建议如何解决这个问题。



请注意(正如我所说)我不了解Java的一些东西,所以我的困难让这个工作起作用可能来自这样一个事实,即我很难掌握这个方法中发生的事情,并且使用各种函数搜索出相互矛盾的答案,而且大多只是显示其他人与他们很难。



所以实际上有三个问题,我问:


  1. 是否可以在Node.js中进行复制,或者Java是否使用Node中不存在的功能?

  2. 是否有人拥有更多的Java经验解释此代码中的各种行,每个人都做了什么?最好以某种体面的Node.js体验(和一些PHP)但从未与Java一起工作的人理解:
  3. 如果有人知道,哪个Node功能是我的看着这个工作?我可以使用内置的加密模块吗?还是我需要额外的模块?



  4. 最后,在你说节点特定的哈希算法(这将是更容易的选择),我不能这样做,因为这将用于已经包含这些哈希密码并且也被其他现有Java应用程序使用的现有数据库。更改其他应用程序或数据库目前不是一个选项。



    更新:我得到的回答非常有用,现在我在Node.js代码中得到了这个:

      hashPassword = function(password,salt){
    crypto.pbkdf2 (密码,新缓冲区(salt),1000,24,'sha1',函数(err,key){

    }
    }

    这就是我再次卡住的地方,我无法从密钥中得到所需的字符串值,我搜索了一下,发现<$ Java代码中的c $ c> String.format 行将BigInteger转换为十六进制整数,但似乎无法获得正确的值。




    • 我尝试了简单的 key.toString('hex'),但是没有成功。
    • 我找到了这个 node-biginteger 模块,并尝试 BigInteger.fromBuffer(1,key).toString(24)和一些但它仍然给我一个与Java应用程序截然不同的结果。



    有关如何获取正确字符串值的帮助从缓冲区将非常赞赏。



    Update2 :我终于得到了我的应用程序工作,因为事实证明它是一个外部模块输出不好的哈希值。

    解决方案

    这些参数生成相同的缓冲区:



    crypto.pbkdf2('test','salt',1000,24,'sha1',function(err,key){});



    剩下的就是以同样的方式格式化一个字符串。这可能有点问题,因为 BigInteger 是签名的,所以你也应该考虑签名。



    您可以使用 bn.js 执行以下操作:

     函数格式(键){
    if(key [0]>>> 7 === 0){
    return key.toString('hex');
    }

    return' - '+ new BN(key.toString('hex'),16).notn(1​​92).add(new BN(1))。toString(16 );
    }



    bn.js不会将前导符号解释为符号,所以您有首先检查它,然后根据表示法转换为字符串。


    Edit: my question has been updated, check the bottom of this post for the latest issue. I left the rest up for people who want to read the whole story :)

    I've been working on translating a small Java application into Node.js, which for the most part has been going very well. I've had to look up a lot of Java functions to figure out what they do and how to replicate their behaviour in Node (since I have pretty much no experience whatsoever with Java), but I got most of the functionality working by now.

    Unfortunately there is one bit that I just can't seem to get working. It is a method used to generate a password hash, using a set of high level Java-specific functions that don't seem to exist in Node. I've been trying for two days to get this working but I just can't get the results I want.

    This is the original Java code:

    public static String hashPassword(final String password, final String salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
        final char[] passwordChars = password.toCharArray();
        final byte[] saltBytes = salt.getBytes();
        final PBEKeySpec spec = new PBEKeySpec(passwordChars, saltBytes, 1000, 192);
        final SecretKeyFactory key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        final byte[] hashedPassword = key.generateSecret(spec).getEncoded();
        return String.format("%x", new BigInteger(hashedPassword));
    }
    

    Note: the salt is a fixed value, it is not random. I know this is not how it should be, but this is how the application is set up. So, since the Java code always gets the same result, it should be possible to get the same result in Node as well.

    I've tried using crypto.pbkdf2, using various ciphers that seemed similar, but it all gave me a different outcome than the Java code. So I figured I'd ask here, to see if anyone knows how to do this, or has any suggestions on how to approach this.

    Note that (as I said) I don't know a thing about Java, so my difficulties getting this to work probably come from the fact that I have a hard time grasping just what is happening within this method, and googling the various functions used gives conflicting answers and mostly just shows other people having a hard time with them as well.

    So there are actually three questions I'm asking:

    1. Is this possible to replicate in Node.js or does Java use functionality that just doesn't exist within Node?
    2. Could someone who has more Java experience explain the various lines in this code, and what each one does? Preferably in a way that someone with a decent level of Node.js experience (and some PHP) but who never worked with Java would understand :)
    3. If anyone knows, which Node functions am I looking at to get this working? Can I do it with the built-in crypto module or will I need additional modules?

    Lastly, before you say "just implement a Node-specific hashing algorithm" (which would be the easier option), I can't do that since this is to be used on existing databases that already contain these hashed passwords and that are used by other existing Java applications as well. Changing the other applications or the database is currently not an option.

    UPDATE: I've gotten an answer that was very helpful, and now I got this in my Node.js code:

    hashPassword = function(password, salt){
        crypto.pbkdf2(password, new Buffer(salt), 1000, 24, 'sha1', function(err, key){
    
        }
    }
    

    That's where I'm stuck again. I can't get the string value I need from the key. I googled a bit and found out that the String.format line in the Java code turns the BigInteger into a hexadecimal integer, but I can't seem to get the correct value.

    Any help on how to get the correct string value from the buffer would be very much appreciated.

    Update2: I finally got my application working, as it turns out it was an external module that outputted bad hashes. Implementing the crypto module properly fixed it.

    解决方案

    These parameters generate the same buffer:

    crypto.pbkdf2('test', 'salt', 1000, 24, 'sha1', function(err, key) {});

    What is left is to format a string the same way. It can be a bit problematic, since BigInteger is signed, so you should take sign into account as well.

    You can do this as following using bn.js:

    function format(key) {
      if (key[0] >>> 7 === 0) {
        return key.toString('hex');
      }
    
      return '-' + new BN(key.toString('hex'), 16).notn(192).add(new BN(1)).toString(16);
    }
    

    bn.js doesn't interpret leading bit as a sign, so you have to check it first, and then convert to string according to two's complement representation.

    这篇关于在Node.js中复制Java密码散列代码(PBKDF2WithHmacSHA1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆