Search code examples
node.jsopensslcryptographynode-crypto

`node:crypto` to generate a sha256 password hash?


I am trying to do the equivalent of openssl passwd -6 in nodejs using the crypto library.

My attempt was to use this function:

import * as crypto from "node:crypto";
import { promisify } from "node:util";

const pbkdf2 = promisify(crypto.pbkdf2);

export async function sha256Password(
  password: string,
  salt: string
): Promise<string> {
  const derivedKey = await pbkdf2(password, salt, 10000, 64, "sha256");

  return `$6$${salt}$${derivedKey.toString("base64")}`;
}

However given a password "my-password" and a salt "saltytest" the string that openssl generates is:

openssl -6 --salt saltytest my-password
$6$saltytest$PxLELj3gGh05NbVO3c3o1mt92k5KZsg1V3OtI4dlclCclCqT4jwwN4Oi325S7T5VNI8JlEF3BnwhkxP5xmYHn/

But my sha256Password function yields something different:

await sha256Password("my-password", "saltytest")
$6$saltytest$anHaLrq0Dl+zNBuXT0v5w91vxwDSNtz/DU2hnRtE2CBiCx5uhyzMi+Euo0bENXe1Poriyq96YpkMHS8hx4IGPQ==

What I am not really sure about, is how exactly openssl passwd -6 really works. In particular I wonder which of my assumptions were wrong:

  • The correct function to use is pbkdf2
  • Encoding of output is base64
  • Number of iterations or passes is 10,000
  • The key-length is 64

Solution

  • Thanks for the comment @Topaco. The suggestion of using unixcrypt actually works:

    npm install unixcrypt
    
    import { encrypt } from "unixcrypt";
    
    
    export function sha256Password(password: string, salt: string): string {
      return encrypt(password, `$6$${salt}`);
    }
    
    encrypt("my-password", "$6$saltytest");
    
    $6$saltytest$PxLELj3gGh05NbVO3c3o1mt92k5KZsg1V3OtI4dlclCclCqT4jwwN4Oi325S7T5VNI8JlEF3BnwhkxP5xmYHn/