Generate Password Hash for RabbitMq

In the previous post, we explored how to use docker compose to per-initialize queues in a docker container. The configuration files also provided a way to initialize users. Each of the users where configured with a password, which is given in the configuration file as a hash value comprising of a randomly generated 32 bit salt and the pass key.

In this post, we will explore how to generate the hashed passkey and write some reusable code for the same.

Generate random 32bit salt.

The first step involved generating a random 32 bit salt.

var salt = GetSalt(4); // 4 bytes = 32 bit

// Plain Text Salt :  5A-C9-AA-26

Where GetSalt() is defined as

byte[] GetSalt(int maximumSaltLength)
{
    return RandomNumberGenerator.GetBytes(maximumSaltLength);
}

Prepend Salt with PassKey

The next step involve prepending the generated salt with the UTF8 representation of the passkey.

var plainPassKeyInBytes = Encoding.UTF8.GetBytes(plainPasskey);
var saltedPassKey = Concatenate(salt,plainPassKeyInBytes);

// Plain Text PassKey:  6D-79-70-61-73-73
// Salted Plain Text PassKey:  5A-C9-AA-26-6D-79-70-61-73-73

Where Concatenate() is defined as

byte[] Concatenate(params byte[][] arrays)
{
    byte[] result = newbyte[arrays.Sum(a => a.Length)];
    int offset = 0;
    foreach (byte[] array in arrays)
    {
        System.Buffer.BlockCopy(array, 0, result, offset, array.Length);
        offset += array.Length;
    }
    return result;
}

Generate Hash Value of Salted PassKey

Now we will generate hash value for the salted passkey. By default, RabbitMq uses SHA256 algorithm, but it also supports SHA512.

var saltedPassKeyHash = SHA256.HashData(saltedPassKey);
var result = Convert.ToBase64String(Concatenate(salt, saltedPassKeyHash));

// Hashed Salted PassKey:  30-50-4E-CD-AB-D4-ED-08-3B-D5-D0-F1-C8-8E-19-18-94-BE-20-DD-E6-F7-6C-16-79-B7-87-B2-0D-6B-6B-6C
// Salted Hash Value :  5A-C9-AA-26-30-50-4E-CD-AB-D4-ED-08-3B-D5-D0-F1-C8-8E-19-18-94-BE-20-DD-E6-F7-6C-16-79-B7-87-B2-0D-6B-6B-6C

Hash value generated is again prepended with the plain key salt. This is then converted to a Base64 encoded value, which would be used in the configuration file.

The complete source is as follows

if (args.Any())
{
    var plainPasskey = args[0];
    var plainPassKeyInBytes = Encoding.UTF8.GetBytes(plainPasskey);
    var salt = GetSalt(32);
    var saltedPassKey = Concatenate(salt,plainPassKeyInBytes);
    var saltedPassKeyHash = SHA256.HashData(saltedPassKey);
    var result = Convert.ToBase64String(Concatenate(salt, saltedPassKeyHash));
    Console.WriteLine(result);
}

byte[] GetSalt(int maximumSaltLength)
{
    return RandomNumberGenerator.GetBytes(maximumSaltLength);
}

byte[] Concatenate(params byte[][] arrays)
{
    byte[] result = newbyte[arrays.Sum(a => a.Length)];
    int offset = 0;
    foreach (byte[] array in arrays)
    {
        System.Buffer.BlockCopy(array, 0, result, offset, array.Length);
        offset += array.Length;
    }
    return result;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s