Comparing BCrypt hash between PHP and NodeJS

后端 未结 3 1689
梦毁少年i
梦毁少年i 2020-12-04 15:04

For an app I\'m working on, nodejs needs to verify hashes created by PHP and vice-versa.

The problem is, the hashes generated in PHP (via Laravel\'s Hash

相关标签:
3条回答
  • 2020-12-04 15:21

    I have tried to compute what was said before to get codes that work. As you can see I don't need to replace anything.

    On the PHP 7.2.4 side:

    <?php
    $password = "test123";
        $hash = password_hash($password, PASSWORD_BCRYPT);
        echo $hash; // I get $2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6
    

    On the nodeJS side:

    Install bcryptjs package: npm i bcryptjs

    var bcrypt = require('bcryptjs');
    let hash1="$2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6";
    console.log(bcrypt.compareSync("test123", hash1)); // display true
    
    0 讨论(0)
  • 2020-12-04 15:26

    The implementation of bcrypt in different language might be differ.

    For example, in Node.js version bcrypt.js, the salt length applied are 29 characters

        bcrypt.getSalt = function(hash) {
            if (typeof hash !== 'string')
                throw Error("Illegal arguments: "+(typeof hash));
            if (hash.length !== 60)
                throw Error("Illegal hash length: "+hash.length+" != 60");
            return hash.substring(0, 29);
        };
    

    But, in Go version golang.org/x/crypto/bcrypt, the salt size are 22 of bytes:

    const (
        majorVersion       = '2'
        minorVersion       = 'a'
        maxSaltSize        = 16
        maxCryptedHashSize = 23
        encodedSaltSize    = 22
        encodedHashSize    = 31
        minHashSize        = 59
    )
    

    So, it might happen that hashed string in Node.js gets error when compared in Go, other languages likewise.

    0 讨论(0)
  • 2020-12-04 15:41

    This fails because the types of bcrypt hashes being generated from php and node are different. Laravel generates the $2y$ while node generates the $2a$. But the good news is the only difference between 2a and 2y are their prefixes.

    So what you can do is make one of the prefix similar to the other. Like:

    $phpGeneratedHash  = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
    $nodeGeneratedHash = '$2a$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
    

    To something like:

    $phpGeneratedHash  = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
    $nodeGeneratedHash = '$2y$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
    

    Notice that I replaced the $2a$ of the node hash to $2y$. You can simply do this with:

    PHP

    $finalNodeGeneratedHash = str_replace("$2a$", "$2y$", $nodeGeneratedHash);
    

    Node

    finalNodeGeneratedHash = nodeGeneratedHash.replace('$2a$', '$2y$');
    

    Then compare phpGeneratedHash to finalNodeGeneratedHash.

    Note: It is recommended that if you're comparing in PHP, change the prefix of the NodeJS generated hash to $2y$ and if you're comparing in NodeJS; change the prefix of the PHP generated hash to $2a$.

    0 讨论(0)
提交回复
热议问题