TL;DR: use mosquitto_passwd.php with php-cli for stand-alone command line password generation,choice of sha512-pbkdf2 (>=v2.0) and sha512 (<v2.0) algorithm(requires PHP>=5.5.0 & Hash extension enabled (always enabled since 7.4))
TL;DR: use mosquitto_passwd.php with php-cli for stand-alone command line password generation,choice of sha512-pbkdf2 (>=v2.0) and sha512 (<v2.0) algorithm
Back in the days I were operating some critical systems in a commercial context which employed the Mosquitto broker for internal component communication, these days it is called “Eclipse Mosquitto (TM)” and part of Cedalo’s “Pro Mosquitto MQTT Broker (not TM and not fully FOSS)” aka. “Pro Edition for Mosquitto” (see comparison), which made me follow the development quite closely for some years and even contribute a little here and there.
This made me witness several frustrations from Mosquitto users who wanted to prepare credentials for user authentication on machines which did not have the broker itself nor its tools installed locally (see original trigger question on mosquitto-dev from 2016, and through the years also this, that, there, and some solutions).
The trigger motivated me to investigate and describe the required steps and some PHP code that could perform the needed hash calculation and format the required authentication line for the file supplied to the broker’s password_file config option. This was back in 2016 where only a SHA512 based hash was supported.
I later made a write-up on this blog (part I), which resulted in some readers contacting me for help and clarification. This made me put together a proper script in 2021 which would behave similarly to mosquitto_passwd; mosquitto_passwd.php.
In recent years, another user chipped in on GitHub annoyed by the need to install the broker to generate passwords for use in containers which has now triggered me again, in 2026!, to look into the PBKDF2 method available and default in v2.0 and later (2020-12-03) releases of Mosquitto. This ended up with addition of the -H & -I options for choosing hash method & PBKDF2 iterations to the script for compatibility with mosquitto_passwd (although -I for mosquitto_passwd is completely undocumented, created a PR rectifying that).
So feel free to use mosquitto_passwd.php, it is freely available and distributed under the GNU GPL 3.0 license.
EDIT 2021-08-31: add section about possible unexpected change of behaviour when using the simple (global) setup (fx. git)
There is this nifty OS project, GNU, which has this nifty piece of software for syntax highlighting, source-highlight (aka. src-highlite), together with which is distributed this nifty shell script, src-hilite-lesspipe.sh, meant for piping arbitrary text through the highlighter selecting and applying a sensible highlight language definition, before being paged in some nifty pager which is able to interpret ANSI escape codes (ISO/IEC 6429 or ECMA-48, previously ANSI X3.64/FIPS PUB 86) like fx. the nifty and ubiquitous less.
Sadly, even after having installed less and source-highlight on modern Ubuntu and Debian systems they are not inter-operating by default. You’d have to feel the itch of syntax highlighting, discover source-highlight and dig its documentation to find out about said script.
Below is a quick two-line shell HOW-TO which sets up environment variables for the current user to enable auto-detection of language and subsequent syntax highlighting pr. default in less using GNU source-highlight (here done on Ubuntu 20.04 LTS, should behave similarly on Debian and derived distributions);
$ sudo apt install source-highlight $ echo -e "\nexport LESSOPEN=\"| /usr/share/source-highlight/src-hilite-lesspipe.sh %s\"\nexport LESS=' -R '" >> ~/.bash_aliases
This setup will make fx. some C source code display as below in less.
environment set up for less to enable ANSI color codes and pass any text through source-highlighter for potential ANSI escape code addition
less showing highlighted C code, auto-detected and highlighted by GNU source-highlighter
One caveat of this global setup being active for any invocation of less, is that most programs will behave accordingly and some maybe different from expectations.
Notably, using the git command line client with the above setup will make git refrain from setting a default LESS=FRX environment (see core.pager of man git config) when invoking less. This turns off the less features “quit-if-one-screen” (F) and “no-init” (X) (see OPTIONS of man less) which usually makes less invisible in git contexts unless paging is actually needed. This could cause confusion for some, making git seemingly take over the terminal on even 1 line outputs (see this bug report on GNU src-hilite and my comment detailing the above).
One solution to this would of course be to add “FX” to the environment, another is making a little more elaborate, more conservative and less transparent setup, as below.
If you’d still like to have a “plain less” not messing with and amending you text unless you ask it to, you could make an alias to use specifically when you want syntax highlighting. Put these somewhere interpreted by you shell (for bash fx. ~/.bash_aliases);
# syntax highlight in less alias lesssh="LESSOPEN='|/usr/share/source-highlight/src-hilite-lesspipe.sh %s' LESS=' -R ' less" function lessurl() { wget -O- -q $1 |source-highlight -f esc -s html |less -R; }
Line two is a bonus shell function pulling some HTML from a webserver using wget, adding syntax highlighting and showing it in less.
For the brave, take a tour of the “info source-highlight” (or “man source-highlight”) manuals (also here) to become familiar with the tool. You can use it anywhere you’d like some colour on arbitrary text and where color are supported in various ways and encodings, for example HTML and latex;
source-highlight adding color encoding to C code using HTML and latex encoding
If you are a programmer wanting to add highlighting features to you own application, the command line utilities are building on a highlighting library which you can utilise (API documentation here).
EDIT 2021-07-11: the script described below has been added to the author’s hometools repository on sourcehut.org
Needed some space on the disk.
Had some music, some of it were wav files.
Threw together this script to transmogify it into ogg using ffmpeg.
Statistics say that 24 wav files occupying 1,7 GiB was made into 24 ogg files occupying 105 MiB, a reduction to ~6% (du -h calculates 2^10 numbers but uses SI 10^3 prefixes..).
miki@filly:~/Music$ find . -iname "*.wav" -print0 | sed s/.wav/.ogg/g |du --files0-from=- -h -c|tail -1 105M total miki@filly:~/Music$ find . -iname "*.wav" -print0 | sed s/.wav/.wav/g |du --files0-from=- -h -c|tail -1 1,7G total miki@filly:~/Music$ find . -iname "*.wav" -print0 | sed s/.wav/.ogg/g |du --files0-from=- -h |wc -l 24 miki@filly:~/Music$
Install prerequisite ffmpeg and ffprobe utilities on apt distributions by doing “apt install ffmpeg”.
BEWARE: script deletes any wav files in current directory and below without warning if conversion to ogg is fine according to ffmpeg return code and stdout/err.
Manual confirmation of all deletions can be enabled by uncommenting line 8 (CONFIRM=..).
It could (very) easily be amended for conversion between any container or compression format supported by ffmpeg by replacing “wav” and “ogg” in glob pattern and OGG variable definition (for completeness also in echo output…).
miki@filly:~/wavtest$ cat ~/hometools/wav2ogg.sh #! /bin/bash # # Make .ogg out of all .wav in cwd and below, remove .wav! # # When converting remove only if conversion is ok. # ffprobe any present .ogg and check if playtime is same as wav, remove only if all is good. #CONFIRM=-i # confirm deletion? REQS="ffmpeg ffprobe" which $REQS >/dev/null if [ ! $? -eq 0 ]; then echo We need $REQS to do stuff! exit 1 fi shopt -s globstar nullglob nocaseglob # enable 2-star magic for f in **/*.wav; do OGG=$(dirname "$f")/$(basename "$f" wav)ogg echo -n "$f: " if [ ! -f "$OGG" ]; then echo -en "\e[33mno ogg\e[0m" CONVERT=1 else echo -en "\e[32malready there\e[0m" if [ ! "$(ffprobe "$f" 2>&1|grep Duration|cut -d, -f1)" = "$(ffprobe "$OGG" 2>&1|grep Duration|cut -d, -f1)" ]; then echo -en " - \e[31mogg corrupt\e[0m" CONVERT=1 rm $CONFIRM "$OGG" else OGGOK=1 fi fi if [ $CONVERT ]; then echo -en " - \e[33mconverting\e[0m" OUT=$(ffmpeg -loglevel error -i "$f" "$OGG" 2>&1) if [ ! $? -eq 0 ]; then echo -e " \e[31mfatal error!\e[0m\nffmpeg output was:\n\n$OUT\n" rm $CONFIRM "$OGG" elif [ ! -z "$OUT" ]; then echo -e " \e[31mnon-fatal error!\e[0m\nffmpeg output was:\n\n$OUT\n" else OGGOK=1 fi fi if [ $OGGOK ]; then echo -e " - all good removing wav" rm $CONFIRM "$f" fi done miki@filly:~/wavtest$
miki@filly:~/wavtest$ ls -lR .: total 59964 drwxrwxr-x 3 miki miki 4096 Jun 6 22:33 one -rw-rw-r-- 1 miki miki 61390864 Jun 6 22:32 Sordid Affair (Man Without Country Version).wav ./one: total 30720 drwxrwxr-x 3 miki miki 4096 Jun 6 22:34 two -rw-rw-r-- 1 miki miki 31451304 Jun 6 22:30 Vision Man MASTER.wav ./one/two: total 55352 -rw-rw-r-- 1 miki miki 56675660 Jun 6 22:34 Bye Barat - Going For Broke (UNKWON´s Autumn Remix) LIM_02.wav drwxrwxr-x 2 miki miki 4096 Jun 6 22:34 three ./one/two/three: total 375112 -rw-rw-r-- 1 miki miki 384108056 Jun 6 22:30 Rigoremix - Pornographe - Final2.wav miki@filly:~/wavtest$ du -hs . 509M . miki@filly:~/wavtest$
In real life, also in technicolor!
miki@filly:~/wavtest$ ~/hometools/wav2ogg.sh one/two/Bye Barat - Going For Broke (UNKWON´s Autumn Remix) LIM_02.wav: no ogg - converting - all good removing wav one/two/three/Rigoremix - Pornographe - Final2.wav: no ogg - converting - all good removing wav one/Vision Man MASTER.wav: no ogg - converting - all good removing wav Sordid Affair (Man Without Country Version).wav: no ogg - converting - all good removing wav miki@filly:~/wavtest$
miki@filly:~/wavtest$ ls -lR .: total 4952 drwxrwxr-x 3 miki miki 4096 Jun 6 22:35 one -rw-rw-r-- 1 miki miki 5066460 Jun 6 22:35 Sordid Affair (Man Without Country Version).ogg ./one: total 2528 drwxrwxr-x 3 miki miki 4096 Jun 6 22:34 two -rw-rw-r-- 1 miki miki 2580752 Jun 6 22:35 Vision Man MASTER.ogg ./one/two: total 4680 -rw-rw-r-- 1 miki miki 4785594 Jun 6 22:34 Bye Barat - Going For Broke (UNKWON´s Autumn Remix) LIM_02.ogg drwxrwxr-x 2 miki miki 4096 Jun 6 22:35 three ./one/two/three: total 19456 -rw-rw-r-- 1 miki miki 19922936 Jun 6 22:35 Rigoremix - Pornographe - Final2.ogg miki@filly:~/wavtest$ du -hs . 31M . miki@filly:~/wavtest$
ffmpeg does some nice metadata conversions out of the box;
miki@filly:~/Music$ ffprobe ~/"wavbak/Delayscape A Short While Rigolin Edit Audaccity.wav" 2>&1| grep Input -A 1000 Input #0, wav, from '/home/miki/wavbak/Delayscape A Short While Rigolin Edit Audaccity.wav': Metadata: title : Delayscape - A Short While (Rigolin Edit) artist : rigolin comment : Love Melody date : 2018 Duration: 00:06:33.97, bitrate: 3072 kb/s Stream #0:0: Audio: pcm_f32le ([3][0][0][0] / 0x0003), 48000 Hz, 2 channels, flt, 3072 kb/s miki@filly:~/Music$ ffprobe "./Delayscape - Heinz Beauvaix/Soundcloud/Delayscape A Short While Rigolin Edit Audaccity.ogg" 2>&1| grep Input -A 1000 Input #0, ogg, from './Delayscape - Heinz Beauvaix/Soundcloud/Delayscape A Short While Rigolin Edit Audaccity.ogg': Duration: 00:06:33.97, start: 0.000000, bitrate: 99 kb/s Stream #0:0: Audio: vorbis, 48000 Hz, stereo, fltp, 112 kb/s Metadata: ENCODER : Lavc56.60.100 libvorbis TITLE : Delayscape - A Short While (Rigolin Edit) ARTIST : rigolin comment : Love Melody DATE : 2018 miki@filly:~/Music$
TL;DR: use mosquitto_passwd.php with php-cli for stand-alone command line password generation(requires PHP>=5.5.0 & Hash extension enabled (always enabled since 7.4))
TL;DR: use mosquitto_passwd.php with php-cli for stand-alone command line password generation
Update 2026-02-13: the mosquitto_passwd.php script has been updated to support generation of post-2.0 Mosquitto hashes (ie. SHA5152-PBKDF2). It defaults to this, so if you are stuck with pre-2.0 use the “-H sha512” option to produce a compatible SHA512 hash (equivalent with mosquitto_passwd). This was triggered by some activity on the earlier discussion, which also produced a PR to fix some issues in mosquitto_passwd.
Update 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.
Update 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