SIDEBAR
»
S
I
D
E
B
A
R
«
Generating passwords for Mosquitto MQTT broker using PHP
Jan 13th, 2017 by miki

NOTE 2024-08-31: see also recent discussion I was involved in on a Mosquitto github issue about a similar need of generating credentials for use on systems where installed software is very constrained. As this pops up continually I’ll put on my tinkering TODO (which means no  promises or guarantees at all(!)) to look into and potentially contribute a suite of utilities to do this using different tools, currently I guess PHP, OpenSSL and maybe Python would be a good start. Feel free to also ping me if this would be something you are interested in.

NOTE 2021-07-11: prompted by an email from a reader the approach described below was refined into a script which can be used as a (sort of) drop-in replacement for mosquitto_passwd, find it on sourcehut in my hometools repository as mosquitto_passwd.php (first edition also on paste.sr.ht). Even though it generates a pre-2.0 plain hash using SHA512 this is still parsable by 2.0 and later. However, 2.0 adds support for PBKDF2 aka. RFC2898 on top of SHA512 with 20.000 iterations which is also the default generated by 2.0+ mosquitto_passwd, but the broker is still able to parse previous SHA512 hashes (notice the algorithm identifier after <username>:$, 6 for SHA512, 7 for PBKDF2-SHA512, similar to common /etc/shadow convention and extensions to implementations of POSIX crypt()).

Here is a delayed write-up of my involvement in a question posted to the liberally licensed MQTT broker (server) Mosquitto’s developer list list about how to generate authentication tokens programmatically. It kicked the curious cat in me which propelled a journey into the backyards of the C code for the mosquitto_passwd tool which normally is used for this purpose. This resulted in the proof of concept PHP implementation outlined in my answer on the list which is reproduced below.

MQTT (once Message Queue Telemetry Transport) is a lightweight publish/subscribe protocol intended for communication between low power, low bandwidth embedded devices. These days it is commonly hyped as a holy grail in the religion of IoT. The protocol was originally developed by IBM but is now a standard overseen by the OASIS standardization organization which also has the OpenDocument standard (ODF, think Open/Libre-Office) under its wings. According to Wikipedia MQTT is used behind the scenes of Facebook Messenger, OpenStack and Amazon’s IoT services.

For further practical use of the concept outlined you would need to produce a random 16 byte base64 encoded salt to feed into the hasher, that could be done using something like; $salt_base64=base64_encode(openssl_random_pseudo_bytes(12));

If your need a shrink wrapped solution to this you could try to ping me.

Hi Srinivas.

On 2016-07-26 12:49, Srinivas Pokala wrote:
> Username successfully created using linux command with: 
> "mosquitto_passwd /etc/mosquitto/passwd guest".
> I need to create same with php or javascript how?

Looking at the source of mosquitto_passwd
(https://github.com/eclipse/mosquitto/blob/master/src/mosquitto_passwd.c)
basically all it does to generate the resulting line you see in the
password file is:

1) draw a random 12 byte binary salt
2) hash the combination of password and salt using sha512
3) write username, base64 encoded salt, base64 encoded hash in one line

A PHP implementation would use something like this ($salt is fixed for
demonstration purposes, it ought to be random in production);

---
$username="Bitten";
$password="Insect";
$salt_base64="spicychilinstuff";
$salt=base64_decode($salt_base64);
$hash=hash("sha512",$password.$salt, true);
$hash_base64=base64_encode($hash);
echo($username.":$6$".$salt_base64."$".$hash_base64."\n");
---

Comparing against mosquitto_passwd using a one-liner (uses the base64
salt from output to be able to correlate the two);

---
$ mosquitto_passwd -b ~/mosq_passwd_test Bitten Insect
$ cat ~/mosq_passwd_test
Bitten:$6$mfJ0Eq3rIDLKG33r$gkiIlz80JA6Pq9OtGhasIsx7L2vf0APdZH77+thmNW2Zp5vE1d/dAi5TjbfO9mZpKHLh38Oem1ic072rSO328g==

$ php -r '$username="Bitten"; $password="Insect";
$salt_base64="mfJ0Eq3rIDLKG33r"; $salt=base64_decode($salt_base64);
$hash=hash("sha512",$password.$salt, true);
$hash_base64=base64_encode($hash);
echo($username.":$6$".$salt_base64."$".$hash_base64."\n");'
Bitten:$6$mfJ0Eq3rIDLKG33r$gkiIlz80JA6Pq9OtGhasIsx7L2vf0APdZH77+thmNW2Zp5vE1d/dAi5TjbfO9mZpKHLh38Oem1ic072rSO328g==
---

As can be seen, the PHP generated password line are identical to the
mosquitto_passwd generated.

I have also successfully tested authentication against the mosquitto
broker with PHP generated users. One caveat is that the above can
generate a salt of arbitrary length, but the broker must see a 12 byte
binary salt (16 byte base64) or authentication will fail.

Note however, that this hasn't been tested on more than a few
username/password pairs, there might be other issues lurking.

Regards,
-- 
Mikkel
One-liner: Decompress file and diff against another file
Dec 8th, 2016 by miki

Below is a handy shell one-liner for comparing the decompressed contents of a compressed file against a plain file. The purpose here is to test whether the compressed file is actually derived from compressing the plain file. This particular example is from a real life situation where log rotation by cron.daily on a Ubuntu server had begun failing. The situation is thought to be the result of an interrupted logrotate execution leaving a compressed (but non-rotated) intermediate file in the file system that prevented further log rotation on subsequent executions.

The command constructs a pipe between two process, specified using the | symbol (vertical line), to send the decompressed contents from gunzip stdout to stdin of the compare tool. The example uses diff as compare tool which is suitable for textual contents. You could use f.x. cmp instead if the contents is binary. Both diff and cmp interprets the file name “-” as meaning that input should be read from stdin.

$ gunzip --stdout /var/log/syslog.1.gz | diff --report-identical-files - /var/log/syslog.1
Files - and /var/log/syslog.1 are identical

The above uses long options for clarity, in a real life situation you would probably be using short options instead. That means -c instead of –stdout and s instead of –report-identical-files.

$ gunzip -c /var/log/syslog.1.gz | diff -s - /var/log/syslog.1
Files - and /var/log/syslog.1 are identical

 

»  Substance:WordPress   »  Style:Ahren Ahimsa
© 2023 Mikkel Kirkgaard Nielsen, contents CC BY-SA 4.0