How to generate password_hash for RabbitMQ Management HTTP API

Dinei picture Dinei · Dec 23, 2016 · Viewed 14.7k times · Source

The beloved RabbitMQ Management Plugin has a HTTP API to manage the RabbitMQ through plain HTTP requests.

We need to create users programatically, and the HTTP API was the chosen way to go. The documentation is scarce, but the API it's pretty simple and intuitive.

Concerned about the security, we don't want to pass the user password in plain text, and the API offers a field to send the password hash instead. Quote from there:

[ GET | PUT | DELETE ] /api/users/name

An individual user. To PUT a user, you will need a body looking something like this:

{"password":"secret","tags":"administrator"}

or:

{"password_hash":"2lmoth8l4H0DViLaK9Fxi6l9ds8=", "tags":"administrator"}

The tags key is mandatory. Either password or password_hash must be set.

So far, so good, the problem is: how to correctly generate the password_hash?

The password hashing algorithm is configured in RabbitMQ's configuration file, and our is configured as the default SHA256.

I'm using C#, and the following code to generate the hash:

var cr = new SHA256Managed();
var simplestPassword = "1";
var bytes = cr.ComputeHash(Encoding.UTF8.GetBytes(simplestPassword));
var sb = new StringBuilder();
foreach (var b in bytes) sb.Append(b.ToString("x2"));
var hash = sb.ToString();

This doesn't work. Testing in some online tools for SHA256 encryption, the code is generating the expected output. However, if we go to the management page and set the user password manually to "1" then it works like a charm.

This answer led me to export the configurations and take a look at the hashes RabbitMQ are generating, and I realized a few things:

  • hash example of "1": "y4xPTRVfzXg68sz9ALqeQzARam3CwnGo53xS752cDV5+Utzh"
  • all the user's hashes have fixed length
  • the hashes change every time (even if the password is the same). I know PB2K also do this to passwords, but don't know the name of this cryptographic property.
  • if I pass the password_hash the RabbitMQ stores it without changes

I'm accepting suggestions in another programming languages as well, not just C#.

Answer

Waldo picture Waldo · Nov 6, 2018

And for the fun the bash version !

#!/bin/bash

function encode_password()
{
    SALT=$(od -A n -t x -N 4 /dev/urandom)
    PASS=$SALT$(echo -n $1 | xxd -ps | tr -d '\n' | tr -d ' ')
    PASS=$(echo -n $PASS | xxd -r -p | sha256sum | head -c 128)
    PASS=$(echo -n $SALT$PASS | xxd -r -p | base64 | tr -d '\n')
    echo $PASS
}

encode_password "some-password"