Skip to content

Instantly share code, notes, and snippets.

@christianclinton
Last active January 5, 2024 04:08
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save christianclinton/faa1aef119a0919aeb2e to your computer and use it in GitHub Desktop.
Save christianclinton/faa1aef119a0919aeb2e to your computer and use it in GitHub Desktop.
RabbitMQ Password Hash - Python
#!/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
@claytondaley
Copy link

FYI. Per the documentation:

As of version 3.6.0, RabbitMQ can be configured to use several password hashing functions:

  • SHA-256
  • SHA-512
  • MD5 (only for backwards compatibility)

The default is now SHA-265 (rabbit_password_hashing_sha256). To actually use this option, it's necessary to edit line 37.

@claytondaley
Copy link

Here's a py3 (and sha256) variant:

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

def decode_rabbit_password_hash(password_hash):
    password_hash = binascii.a2b_base64(password_hash)
    decoded_hash = bytes.fromhex(password_hash).decode('utf-8')
    return decoded_hash[0:8], decoded_hash[8:]

@notmeta
Copy link

notmeta commented May 21, 2019

@claytondaley

Your python3 decode function doesn't work, but this one does:

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

I have only tested this on 3.7.3, which might be why yours doesn't work for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment