title: Validating SHA512 hashes from PHP in node.js
body: <p>I'm trying to port a legacy password hashing scheme from PHP to Javascript (node.js), but I'm missing something in the process.</p>
  
  <hr>
  
  <h2>Original, working PHP version</h2>
  
  <p>Here is the "original", working code:</p>
  
  <pre class="lang-php prettyprint-override"><code>function create_hash($password) {
      $salt = uniqid();
      $algorithm = '6'; // CRYPT_SHA512
      $rounds = '1234';
  
      // This is the "salt" string we give to crypt().
      $cryptSalt = '$' . $algorithm . '$rounds=' . $rounds . '$' . $salt;
  
      $hashedPassword = crypt($password, $cryptSalt);
  
      return $hashedPassword;
  
  }
  
  function hash_is_valid($password, $hash) {
      return (crypt($password, $hash) == $hash);
  }
  </code></pre>
  
  <p>Working test with above PHP functions:</p>
  
  <pre class="lang-php prettyprint-override"><code>echo $password = 'secret';
  echo '&lt;br /&gt;&lt;br /&gt;';
  
  echo $hash = create_hash($password);
  echo '&lt;br /&gt;&lt;br /&gt;';
  
  echo 'Should be true: ';
  $valid1 = hash_is_valid($password, $hash);
  var_dump($valid1); // outputs "bool(true)"
  echo '&lt;br /&gt;&lt;br /&gt;';
  
  echo 'Should be false: ';
  $valid2 = hash_is_valid('wrong_pass', $hash);
  var_dump($valid2); // outputs "bool(false)"
  echo '&lt;br /&gt;&lt;br /&gt;';
  </code></pre>
  
  <h2>Javascript Version (broken)</h2>
  
  <p>Here's what I've got so far, but it isn't quite there</p>
  
  <pre class="lang-js prettyprint-override"><code>function hash_is_valid(password, hash, cb) {
  
      // Hash Format:
      // $[algorithm]$[number_of_rounds]$[salt]$[hashed_password]
      let hashParts = hash.split('$')
      console.log(hashParts)
      let salt = hashParts[3]
      let numRounds = parseInt(hashParts[2].substr(7)) // from string like rounds=1234
      let originalHashResult = hashParts[4]
  
      let salted = password + '{' + salt + '}'
      let processedHash = crypto.createHash('sha512').update(salted, 'utf-8');
  
      for (let i = 1; i &lt; numRounds ; i++) {
        processedHash = crypto.createHash('sha512').update(processedHash.digest('binary') + salted);
      }
  
      processedHash = processedHash.digest('base64')
  
      // Capture the result
      let hashVerified = (processedHash === originalHashResult)
  
      // Call the callback with the result
      cb(hashVerified)
  
  }
  
  hash_is_valid('secret', '$6$rounds=1234$56ab50921c460$P4bgd3kMX2xyWJTDOYAdow.jsXiS2TARUJW4BXifgm4czraOIDFLqZ5Ii50GLIKwYTjWwN6WrtG82omQes0cK0', (passed) =&gt; {
    console.log((passed) ? 'password is good' : 'password is no good')
  })
  </code></pre>
  
  <p><em>javascript based on answer to SO question <a href="https://stackoverflow.com/questions/26179033/how-to-validate-symfony2-sha512-passwords-using-nodejs">How to validate Symfony2 sha512 passwords using nodejs</a></em></p>
  
  <p>The javascript version is using some test values:</p>
  
  <p>password: <code>secret</code></p>
  
  <p>hash: <code>$6$rounds=1234$56ab50921c460$P4bgd3kMX2xyWJTDOYAdow.jsXiS2TARUJW4BXifgm4czraOIDFLqZ5Ii50GLIKwYTjWwN6WrtG82omQes0cK0</code></p>