How to generate password_hash for RabbitMQ Management HTTP API

rabbitmq rest api
rabbitmq management ssl
rabbitmq http
rabbitmq management plugin windows
sha256
rabbitmq cors
rabbitmq path_prefix
rabbitmq rates_mode

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#.

From: http://rabbitmq.1065348.n5.nabble.com/Password-Hashing-td276.html

However, the algorithm is quite simple if you want to implement it yourself. Here's a worked example:

Generate a random 32 bit salt:

CA D5 08 9B

Concatenate that with the UTF-8 representation of the password (in this case "simon"):

CA D5 08 9B 73 69 6D 6F 6E

Take the MD5 hash:

CB 37 02 72 AC 5D 08 E9 B6 99 4A 17 2B 5F 57 12

Concatenate the salt again:

CA D5 08 9B CB 37 02 72 AC 5D 08 E9 B6 99 4A 17 2B 5F 57 12

And convert to base64 encoding:

ytUIm8s3AnKsXQjptplKFytfVxI=

you should be able to modify your code to follow this process

Credentials and Passwords, When a new user is added using rabbitmqctl, her password is combined with a via the HTTP API, the password hash must be generated using the following  Password Hashing. The REST api documentation says that we can create users with a hashed password instead of one in clear text. An individual user. To PUT a user, you will need a body looking something like this:

For lazy people (like me ;) ), there is the code for computing RabbitMq password with Sha512 for the framework .Net Core.

public static class RabbitMqPasswordHelper
{
    public static string EncodePassword(string password)
    {
        using (RandomNumberGenerator rand = RandomNumberGenerator.Create())
        using (var sha512 = SHA512.Create())
        {
            byte[] salt = new byte[4];

            rand.GetBytes(salt);

            byte[] saltedPassword = MergeByteArray(salt, Encoding.UTF8.GetBytes(password));
            byte[] saltedPasswordHash = sha512.ComputeHash(saltedPassword);

            return Convert.ToBase64String(MergeByteArray(salt, saltedPasswordHash));
        }
    }

    private static byte[] MergeByteArray(byte[] array1, byte[] array2)
    {
        byte[] merge = new byte[array1.Length + array2.Length];
        array1.CopyTo(merge, 0);
        array2.CopyTo(merge, array1.Length);

        return merge;
    }
}

rabbitmq management password hash mismatch, So my question is if I wanted to send a HTTP API request to create a new user and I want to use the password_hash parameter(as opposed to  In order to update a user's password hash via the HTTP API, the password hash must be generated using the following algorithm: Generate a random 32 bit salt: 908D C60A; Concatenate that with the UTF-8 representation of the password (in this case test12): 908D C60A 7465 7374 3132

Here is a small python script I stumbled across some time ago (attribution is in the script) that is great for quick hash generation. It doesn't do any error checking, so is quite simple:

#!/usr/bin/env python3

# rabbitMQ password hashing algo as laid out in:
# http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2011-May/012765.html

from __future__ import print_function
import base64
import os
import hashlib
import struct
import sys

# This is the password we wish to encode
password = sys.argv[1]

# 1.Generate a random 32 bit salt:
# This will generate 32 bits of random data:
salt = os.urandom(4)

# 2.Concatenate that with the UTF-8 representation of the plaintext password
tmp0 = salt + password.encode('utf-8')

# 3. Take the SHA256 hash and get the bytes back
tmp1 = hashlib.sha256(tmp0).digest()

# 4. Concatenate the salt again:
salted_hash = salt + tmp1

# 5. convert to base64 encoding:
pass_hash = base64.b64encode(salted_hash)

print(pass_hash.decode("utf-8"))

RabbitMQ 3.5.1 - Definitions.json, http://www.rabbitmq.com/management.html#load-definitions %% I think that it is a problem with the password hash. HTTP API requires the values to be RabbitMQ Password Hash - Python. GitHub Gist: instantly share code, notes, and snippets.

Just in case, full code from Waldo should be next

//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Text;

namespace Rextester
{
    public static class RabbitMqPasswordHelper
{
    public static string EncodePassword(string password)
    {
        using (RandomNumberGenerator rand = RandomNumberGenerator.Create())
        using (var sha256 = SHA256.Create())
        {
            byte[] salt = new byte[4];

            rand.GetBytes(salt);

            byte[] saltedPassword = MergeByteArray(salt, Encoding.UTF8.GetBytes(password));
            byte[] saltedPasswordHash = sha256.ComputeHash(saltedPassword);

            return Convert.ToBase64String(MergeByteArray(salt, saltedPasswordHash));
        }
    }

    private static byte[] MergeByteArray(byte[] array1, byte[] array2)
    {
        byte[] merge = new byte[array1.Length + array2.Length];
        array1.CopyTo(merge, 0);
        array2.CopyTo(merge, array1.Length);

        return merge;
    }
}

    public class Program
    {
        public static void Main(string[] args)
        {
            //Your code goes here
            Console.WriteLine(Rextester.RabbitMqPasswordHelper.EncodePassword("MyPassword"));
        }
    }
}

You can run it online on http://rextester.com/. Output of program will contain your hash.


Python version by christianclinton (https://gist.github.com/christianclinton/faa1aef119a0919aeb2e)

#!/bin/env/python
import hashlib
import binascii

# Utility methods for generating and comparing RabbitMQ user password hashes.
#
# Rabbit Password Hash Algorithm:
# 
# Generate a random 32 bit salt: 
# CA D5 08 9B 

# Concatenate that with the UTF-8 representation of the password (in this 
# case "simon"): 
# CA D5 08 9B 73 69 6D 6F 6E 

# Take the MD5 hash: 
# CB 37 02 72 AC 5D 08 E9 B6 99 4A 17 2B 5F 57 12 

# Concatenate the salt again: 
# CA D5 08 9B CB 37 02 72 AC 5D 08 E9 B6 99 4A 17 2B 5F 57 12 

# And convert to base64 encoding: 
# ytUIm8s3AnKsXQjptplKFytfVxI= 
# 
# Sources:
# http://rabbitmq.1065348.n5.nabble.com/Password-Hashing-td276.html
# http://hg.rabbitmq.com/rabbitmq-server/file/df7aa5d114ae/src/rabbit_auth_backend_internal.erl#l204 

# Test Case:
#   print encode_rabbit_password_hash('CAD5089B', "simon")
#   print decode_rabbit_password_hash('ytUIm8s3AnKsXQjptplKFytfVxI=')
#   print check_rabbit_password('simon','ytUIm8s3AnKsXQjptplKFytfVxI=')

def encode_rabbit_password_hash(salt, password):
    salt_and_password = salt + password.encode('utf-8').encode('hex')
    salt_and_password = bytearray.fromhex(salt_and_password)
    salted_md5 = hashlib.md5(salt_and_password).hexdigest()
    password_hash = bytearray.fromhex(salt + salted_md5)
    password_hash = binascii.b2a_base64(password_hash).strip()
    return password_hash

def decode_rabbit_password_hash(password_hash):
    password_hash = binascii.a2b_base64(password_hash)
    decoded_hash = password_hash.encode('hex')
    return (decoded_hash[0:8], decoded_hash[8:])

def check_rabbit_password(test_password, password_hash):
    salt, hash_md5sum = decode_rabbit_password_hash(password_hash)
    test_password_hash = encode_rabbit_password_hash(salt, test_password)
    return test_password_hash == password_hash

Have fun!

Examples, Windows C:\> curl -i -u guest:guest http://localhost:15672/api/vhosts # Unix $ curl monitoring and management . password_hash must be generated using the  To create simple access logs of requests to the HTTP API, set the value of the http_log_dir variable in the rabbitmq_management application to the name of a directory in which logs can be created and restart RabbitMQ.

Here's one in PowerShell - using SHA512 rather than MD5 has mentioned in @derick-bailey opener - but you can repro the intermediate steps by changing $hash and $salt

param (
    $password
)

$rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$hash = [System.Security.Cryptography.SHA512]::Create()

[byte[]]$salt = New-Object byte[] 4
$rand.GetBytes($salt)

#Uncomment the next 2 to replicate derick baileys sample
#[byte[]]$salt = 0xCA, 0xD5, 0x08, 0x9B
#$hash = [System.Security.Cryptography.Md5]::Create()

#Write-Host "Salt"
#[System.BitConverter]::ToString($salt)

[byte[]]$utf8PasswordBytes = [Text.Encoding]::UTF8.GetBytes($password)
#Write-Host "UTF8 Bytes"
#[System.BitConverter]::ToString($utf8PasswordBytes)

[byte[]]$concatenated = $salt + $utf8PasswordBytes
#Write-Host "Concatenated"
#[System.BitConverter]::ToString($concatenated)

[byte[]]$saltedHash = $hash.ComputeHash($concatenated)
#Write-Host "SHA512:"
#[System.BitConverter]::ToString($saltedHash)

[byte[]]$concatenatedAgain = $salt + $saltedHash
#Write-Host "Concatenated Again"
#[System.BitConverter]::ToString($concatenatedAgain)

$base64 = [System.Convert]::ToBase64String($concatenatedAgain)
Write-Host "BASE64"
$base64

Password Hashing, Most of the GET queries return many fields per object. Windows C:\> curl -i -u guest:guest http://localhost:15672/api/vhosts # Unix $ curl -i -u Setting password_hash to "" will ensure the user cannot use a password to log in. tags is a  Reported here: https://groups.google.com/d/msg/rabbitmq-users/GtnQR0BSn88/uBIko3saAgAJ The docs should be updated to note that password-less users can be created.

How export or import RabbitMQ configuration, Hi, The REST api documentation says that we can create users with a would use a password hash from a user they'd already done a GET on,  RabbitMQ Management HTTP API Introduction. Apart from this help page, all URIs will serve only resources of type application/json, and will require HTTP basic authentication (using the standard RabbitMQ user database).

How to generate password_hash for RabbitMQ Management HTTP API. The beloved RabbitMQ Management Plugin has a HTTP API to manage the RabbitMQ  Specifying admin user via env is good, but by using definitions.json and rabbitmq.config I can configure everything (install additional users and set their permissions, define queues and exchanges, etc.) in a more flexible and transparent way than calling plain console commands. There is no mention of this way to configure RabbitMQ in Docker

Use RabbitMQ Management API to export or import configuration. curl --silent --user admin:password --header "Content-type: application/json" http://127.0.0.1:​15672/api/definitions | jq . Create partial configuration. Mar 2020 · How to generate password hash for CouchDB administrator 13 Mar 2020  Teams. Q&A for Work. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.

Comments
  • I believe they hash not a password but encrypted password. They may use some RSA algorithm to get ecnrypted password and then calculate hash for it.
  • To be able to generate hashes you need to find the key that is used for encrypting passwords.
  • I tried to understand what they do in the source code ( github.com/rabbitmq/rabbitmq-management/blob/master/src/… ), but I know nothing of Erlang and functional languages
  • Thanks Derick, it worked like a charm. Advice for future readers: it's not always MD5, it depends on what is configured on rabbitmq.config (default is SHA256 since v3.6.0)
  • It also works for sha256. You've to just replace SHA512 to SHA256.
  • Any way to do it in the template language.?