<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>mosquitto &#8211; acm&#039;s blog</title>
	<atom:link href="https://blog.acm.idv.tw/tag/mosquitto/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.acm.idv.tw</link>
	<description>技術與生活隨筆</description>
	<lastBuildDate>Mon, 12 Sep 2022 01:33:25 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8</generator>

<image>
	<url>https://blog.acm.idv.tw/wp-content/uploads/2022/06/cropped-logo_kaffa9-3-32x32.png</url>
	<title>mosquitto &#8211; acm&#039;s blog</title>
	<link>https://blog.acm.idv.tw</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>編譯mosquitto-auth-plug</title>
		<link>https://blog.acm.idv.tw/2022/09/12/%e7%b7%a8%e8%ad%afmosquitto-auth-plug/</link>
					<comments>https://blog.acm.idv.tw/2022/09/12/%e7%b7%a8%e8%ad%afmosquitto-auth-plug/#respond</comments>
		
		<dc:creator><![CDATA[kaffa9]]></dc:creator>
		<pubDate>Mon, 12 Sep 2022 01:33:25 +0000</pubDate>
				<category><![CDATA[程式設計]]></category>
		<category><![CDATA[mosquitto]]></category>
		<category><![CDATA[mqtt]]></category>
		<guid isPermaLink="false">https://kaffa9.com/?p=617</guid>

					<description><![CDATA[這段日子和mosquitto-auth-plug朝夕相處，可以說是對其又愛又恨，在此簡單整理一些編譯mosquitto-auth-plug時需要做的前置作業，也...<p class="read-more"><a class="btn btn-default" href="https://blog.acm.idv.tw/2022/09/12/%e7%b7%a8%e8%ad%afmosquitto-auth-plug/"> Read More<span class="screen-reader-text">  Read More</span></a></p>]]></description>
										<content:encoded><![CDATA[
<p>這段日子和mosquitto-auth-plug朝夕相處，可以說是對其又愛又恨，在此簡單整理一些編譯mosquitto-auth-plug時需要做的前置作業，也方便自己日後查閱。</p>



<span id="more-617"></span>



<h2 class="wp-block-heading">修改config.mk.in</h2>



<ul class="wp-block-list"><li>設定BACKEND_xxx，將想要使用的backend模組（如：mysql），設定為yes。</li><li>設定MOSQUITTO_SRC，指定mosquitto原始碼的位置。</li><li>設定OPENSSLDIR，若無特別需求，可以維持/usr不變。</li></ul>



<h2 class="wp-block-heading">修改auth_plug.c</h2>



<p>由於mosquitto-auth-plug在2018年即不再維護，但mosquitto在某一版以後，修改了mosquitto plugin API定義，這會使得編譯過程發生錯誤，因此需要修改auth-plug.c關於plugin API的部份。</p>



<p>相關API如下：</p>



<ul class="wp-block-list"><li>mosquitto_auth_unpwd_check</li><li>mosquitto_auth_acl_check</li><li>mosquitto_auth_psk_key_get</li></ul>



<p>要將以上3個API參數裡的mosquitto struct前面的const修飾子去除。</p>



<p>為了維持與舊版的相容性，這邊可以使用#if前置處理指令判斷MOSQ_AUTH_PLUGIN_VERSION是否>=4即可，例如：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="c" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#if MOSQ_AUTH_PLUGIN_VERSION >=4
int mosquitto_auth_unpwd_check(void *userdata, struct mosquitto *client, const char *username, const char *password)
#elif MOSQ_AUTH_PLUGIN_VERSION >=3
int mosquitto_auth_unpwd_check(void *userdata, const struct mosquitto *client, const char *username, const char *password)
#else
int mosquitto_auth_unpwd_check(void *userdata, const char *username, const char *password)
#endif</pre>



<h2 class="wp-block-heading">修正訂閱ACL判斷（以be-mysql.c為例）</h2>



<p>在mosquitto的security_default.c裡，預設的ACL判斷邏輯在遇到access == MOSQ_ACL_SUBSCRIBE時，會直接放行通過，然而在mosquitto-auth-plug裡卻不是，這會導致client訂閱某些包含wildcard字元(&#8216;#&#8217;)時，無法成功訂閱，自然也無法正常收到訊息。</p>



<p>可以在be_mysql_aclcheck函式裡新增以下邏輯：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="c" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 比照 mosquitto security_default.c 寫法，若 access == MOSQ_ACL_SUBSCRIBE，直接放行通過
if (acc == MOSQ_ACL_SUBSCRIBE)
    return (BACKEND_ALLOW);</pre>



<p>記得前面補上header file宣告：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="c" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#include &lt;mosquitto_plugin.h></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.acm.idv.tw/2022/09/12/%e7%b7%a8%e8%ad%afmosquitto-auth-plug/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>mosquitto-go-auth編譯與使用</title>
		<link>https://blog.acm.idv.tw/2022/08/14/mosquitto-go-auth%e7%b7%a8%e8%ad%af%e8%88%87%e4%bd%bf%e7%94%a8/</link>
					<comments>https://blog.acm.idv.tw/2022/08/14/mosquitto-go-auth%e7%b7%a8%e8%ad%af%e8%88%87%e4%bd%bf%e7%94%a8/#respond</comments>
		
		<dc:creator><![CDATA[kaffa9]]></dc:creator>
		<pubDate>Sun, 14 Aug 2022 03:11:35 +0000</pubDate>
				<category><![CDATA[技術]]></category>
		<category><![CDATA[未分類]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[mosquitto]]></category>
		<category><![CDATA[mqtt]]></category>
		<guid isPermaLink="false">https://kaffa9.com/?p=606</guid>

					<description><![CDATA[mosquitto是一個受歡迎的輕量MQTT broker，雖然本身具備了pwfile、aclfile等使用者驗證機制，但使用者數增加、或是使用情境較複雜一點的...<p class="read-more"><a class="btn btn-default" href="https://blog.acm.idv.tw/2022/08/14/mosquitto-go-auth%e7%b7%a8%e8%ad%af%e8%88%87%e4%bd%bf%e7%94%a8/"> Read More<span class="screen-reader-text">  Read More</span></a></p>]]></description>
										<content:encoded><![CDATA[
<p>mosquitto是一個受歡迎的輕量MQTT broker，雖然本身具備了pwfile、aclfile等使用者驗證機制，但使用者數增加、或是使用情境較複雜一點的時候，用起來就沒有那麼彈性了，而且修改完pwfile、aclfile還需要重啟服務，如果服務不適合中斷，那可就尷尬了。</p>



<p>為了做更有彈性的使用者驗證管理，有些人會考慮自行修改mosquitto原始碼（畢竟mosquitto是開源軟體），或者是另外撰寫mosquitto plug-in來處理驗證這一塊（是的！mosquitto有plug-in interface），例如jpmens的mosquitto-auth-plugin，就是一個廣受觀迎的mosquitto驗證plug-in，在Github上的fork數甚至達到487！不過這有一部份原因應該是原作者在2018年底就不再繼續維護此專案，大家有issue或是新需求就fork出來各自努力。<img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f625.png" alt="😥" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>不過別難過得太早，早在2017年開始，iegomez便開始了一個新的mosquitto驗證plug-in專案，稱為mosquitto-go-auth，也就是本文要介紹的軟體。</p>



<span id="more-606"></span>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">簡介</h2>



<p>根據mosquitto-go-auth專案的README.md所述，這個專案主要是受到jpmens的mosquitto-auth-plug專案啟發，採用Go語言開發，並利用cgo曝露出符合mosquitto plug-in規範的連結介面，供mosquitto與此plug-in動態連結。</p>



<p>mosquitto-go-auth主要具備以下幾個優點（個人看法）：</p>



<ul class="wp-block-list"><li>使用Go開發，擴充、改寫、編譯皆比原本以C撰寫來得方便</li><li>原mosquitto-auth-plug支援的backend皆有支援（如：Redis、MySQL、JWT、HTTP、……等），甚至更完善</li><li>與最新版的Mosquitto 2.0相容</li><li>持續維護中！</li></ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">編譯</h2>



<p>要編譯mosquitto-go-auth專案，需準備以下項目：</p>



<ul class="wp-block-list"><li>Go工具包（建議直接用最新版，本文撰寫之時為1.19）</li><li>mosquitto原始碼</li><li>mosquitto-go-auth原始碼</li></ul>



<p>工作目錄如下：</p>



<ul class="wp-block-list"><li>Go: /home/kaffa9/ws/go1.19</li><li>mosquitto: /home/kaffa9/ws/mosquitto</li><li>mosquitto-go-auth: /home/kaffa9/ws/mosquitto-go-auth</li><li>測試目錄: /home/kaffa9/ws/mosquitto-test</li></ul>



<p>在mosquitto-go-auth工作目錄下，先以編輯器開啟Makefile：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">CFLAGS := -I/usr/local/include -fPIC
LDFLAGS := -shared

UNAME_S := $(shell uname -s)

ifeq ($(UNAME_S),Darwin)
	LDFLAGS += -undefined dynamic_lookup
endif

all:
	@echo "Bulding for $(UNAME_S)"
	env CGO_CFLAGS="$(CFLAGS)" go build -buildmode=c-archive go-auth.go
	env CGO_LDFLAGS="$(LDFLAGS)" go build -buildmode=c-shared -o go-auth.so
	go build pw-gen/pw.go

test:
	cd plugin &amp;&amp; make
	go test ./backends ./cache ./hashing -v -count=1
	rm plugin/*.so

test-backends:
	cd plugin &amp;&amp; make
	go test ./backends -v -failfast -count=1
	rm plugin/*.so

test-cache:
	go test ./cache -v -failfast -count=1

test-hashing:
	go test ./hashing -v -failfast -count=1

service:
	@echo "Generating gRPC code from .proto files"
	@go generate grpc/grpc.go

clean:
	rm -f go-auth.h
	rm -f go-auth.so
	rm -f pw</pre>



<p>進行以下修改：</p>



<ul class="wp-block-list"><li>在第1行加上mosquitto標頭檔的路徑：-I../mosquitto/src -I../mosquitto/lib</li><li>在第12行加上CGO_LDFLAGS=&#8221;$(LDFLAGS)&#8221;</li><li>在第13行加上CGO_CFLAGS=&#8221;$(CFLAGS)&#8221;</li></ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">CFLAGS := -I/usr/local/include -I../mosquitto/src -I../mosquitto/lib -fPIC
LDFLAGS := -shared

UNAME_S := $(shell uname -s)

ifeq ($(UNAME_S),Darwin)
	LDFLAGS += -undefined dynamic_lookup
endif

all:
	@echo "Bulding for $(UNAME_S)"
	env CGO_CFLAGS="$(CFLAGS)" CGO_LDFLAGS="$(LDFLAGS)" go build -buildmode=c-archive go-auth.go
	env CGO_CFLAGS="$(CFLAGS)" CGO_LDFLAGS="$(LDFLAGS)" go build -buildmode=c-shared -o go-auth.so
	go build pw-gen/pw.go

test:
	cd plugin &amp;&amp; make
	go test ./backends ./cache ./hashing -v -count=1
	rm plugin/*.so

test-backends:
	cd plugin &amp;&amp; make
	go test ./backends -v -failfast -count=1
	rm plugin/*.so

test-cache:
	go test ./cache -v -failfast -count=1

test-hashing:
	go test ./hashing -v -failfast -count=1

service:
	@echo "Generating gRPC code from .proto files"
	@go generate grpc/grpc.go

clean:
	rm -f go-auth.h
	rm -f go-auth.so
	rm -f pw</pre>



<p>如此一下，Go編譯時才找得到相依的mosquitto標頭檔。</p>



<p>設定一下Go工具路徑：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">export PATH=/home/kaffa9/ws/go1.19/bin:$PATH</pre>



<p>就可以開始編譯囉！</p>



<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">make</pre>



<p>編譯完成後，可得以下檔案：</p>



<ul class="wp-block-list"><li>go-auth.so : plug-in</li><li>pw : 密碼工具</li></ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">設定與運行（以Redis為例）</h2>



<p>首先將mosquitto執行檔以及go-auth.so複製到測試目錄（/home/kaffa9/ws/mosquitto-test）中。</p>



<p>要讓plug-in順利運行，必須在mosquitto.conf中進行設定，以下為參考設定值：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">listener 1883

auth_plugin /home/kaffa9/ws/mosquitto-test/go-auth.so
auth_opt_backends redis
auth_opt_hasher pbkdf2                 # password hashing type
auth_opt_hasher_salt_size 16           # salt bytes length
auth_opt_hasher_iterations 100000      # number of iterations
auth_opt_hasher_keylen 64              # key length
auth_opt_hasher_algorithm sha512       # hashing algorithm, either sha512 (default) or sha256
auth_opt_hasher_salt_encoding base64   # salt encoding, either base64 (default) or utf-8
auth_opt_redis_host localhost
auth_opt_redis_port 6379
auth_opt_redis_db 1
auth_opt_redis_password myPa55w0rd
auth_opt_redis_disable_superuser true</pre>



<p>我們將mosquitto運行在port 1883，指定驗證plug-in路徑，並額外進行以下設定：</p>



<ul class="wp-block-list"><li>auth_opt_backends : 指定使用redis</li><li>auth_opt_hasher : 指定密碼採用pbkdf2格式</li><li>auth_opt_hasher_salt_size : 指定salt長度為16</li><li>auth_opt_hasher_iterations : 指定PBKDF2迭代次數為100000</li><li>auth_opt_hasher_keylen : 指定金鑰長度為64</li><li>auth_opt_hasher_algorithm : 指定HMAC雜湊演算法為sha512</li><li>auth_opt_hasher_salt_encoding : 指定salt儲存格式為base64</li><li>auth_opt_redis_host : Redis連線位址</li><li>auth_opt_redis_port : Redis連線port</li><li>auth_opt_redis_db : Redis資料庫編號</li><li>auth_opt_redis_password : Redis密碼</li><li>auth_opt_redis_disable_superuser : 是否停用superuser功能</li></ul>



<p>接下來可以使用pw工具為使用者，依照mosquitto.conf裡設定的條件（salt_size、iterations、keylen、……）產生密碼，這裡我們產生foo123和bar123，共2組密碼，待會兒給foo和bar這2個帳號使用：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$ ./pw -a sha512 -e base64 -h pbkdf2 -i 100000 -l 64 -s 16 -p foo123
PBKDF2$sha512$100000$9Ey+5BSIyYJCTnNFJm7NPA==$S7BZ8loLtIergIybLQbOf45iJsubksB10VHAnBkZ93/FyfS9nXuYH34Rv2mIhC8sVg24jzjs+fwg9IayGNSr7g==
$ ./pw -a sha512 -e base64 -h pbkdf2 -i 100000 -l 64 -s 16 -p bar123
PBKDF2$sha512$100000$Yd+W79o4NRrvl+c5uiYceA==$Op/YJbn0xs7nd9tFZ9Eumstj/HBn4A+nJydYEsScucko1rdDXJOIy83lV2CbiZNXfTWPFgtG2gv1ju0M/TI0TQ==</pre>



<p>然後將帳號密碼的對應關係寫入Redis中（以下在redis-cli中操作）：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">選擇使用資料庫1
127.0.0.1:6379> SELECT 1

新增foo
127.0.0.1:6379[1]> SET foo PBKDF2$sha512$100000$9Ey+5BSIyYJCTnNFJm7NPA==$S7BZ8loLtIergIybLQbOf45iJsubksB10VHAnBkZ93/FyfS9nXuYH34Rv2mIhC8sVg24jzjs+fwg9IayGNSr7g==
OK

新增bar
127.0.01:6379[1]> SET bar PBKDF2$sha512$100000$Yd+W79o4NRrvl+c5uiYceA==$Op/YJbn0xs7nd9tFZ9Eumstj/HBn4A+nJydYEsScucko1rdDXJOIy83lV2CbiZNXfTWPFgtG2gv1ju0M/TI0TQ==
OK</pre>



<p>接著設定ACL：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">設定ACL (subscribe)
127.0.0.1:6379[1]> SADD foo:sacls "mailbox/foo/#"
OK

設定ACL (read)
127.0.0.1:6379[1]> SADD foo:racls "mailbox/foo/#"
OK

設定ACL (write)
127.0.0.1:6379[1]> SADD foo:wacls "mailbox/foo/#"
OK

設定ACL (readwrite)
127.0.0.1:6379[1]> SADD foo:rwacls "mailbox/foo/#"
OK

//bar的部份如法泡製</pre>



<p>接著讓mosquitto正式上場：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">./mosquitto -c ./mosquitto.conf
1660441737: mosquitto version 2.0.14 starting
1660441737: Config loaded from ./mosquitto.conf.
1660441737: Loading plugin: /home/kaffa9/ws/mosquitto-test/go-auth.so
1660441737:  ├── Username/password checking enabled.
1660441737:  ├── TLS-PSK checking enabled.
1660441737:  └── Extended authentication not enabled.
INFO[2022-08-14T01:48:57Z] Backend registered: Redis
INFO[2022-08-14T01:48:57Z] registered acl checker: redis
INFO[2022-08-14T01:48:57Z] registered user checker: redis
INFO[2022-08-14T01:48:57Z] registered superuser checker: redis
INFO[2022-08-14T01:48:57Z] No cache set.
1660441737: Opening ipv4 listen socket on port 1883.
1660441737: Opening ipv6 listen socket on port 1883.
1660441737: mosquitto version 2.0.14 running</pre>



<p>之後就可以使用MQTT client來測試看看啦！</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">給「原mosquitto-auth-plug使用者」注意事項</h2>



<p>原mosquitto-auth-plug密碼格式只支援PBKDF2，但使用時不需特別指定salt和key長度，mosquitto-auth-plug驗證時會檢查interation數以及salt、key長度，自動往回推算（如下列C程式碼，第11行tokenize取出PDFBK2密碼hash的各部位，第19行計算key長度、第39行計算salt長度）。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="c" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">int pbkdf2_check(char *password, char *hash)
{
	char *sha, *salt, *h_pw;
	int iterations, saltlen, blen;
	char *b64, *keybuf;
	unsigned char *out;
	int match = FALSE;
	const EVP_MD *evpmd;
	int keylen, rc;

	if (detoken(hash, &amp;sha, &amp;iterations, &amp;salt, &amp;h_pw) != 0)
		return match;

	/* Determine key length by decoding base64 */
	if ((keybuf = malloc(strlen(h_pw) + 1)) == NULL) {
		fprintf(stderr, "Out of memory\n");
		return FALSE;
	}
	keylen = base64_decode(h_pw, keybuf);
	if (keylen &lt; 1) {
		free(keybuf);
		return (FALSE);
	}
	free(keybuf);

	if ((out = malloc(keylen)) == NULL) {
		fprintf(stderr, "Cannot allocate out; out of memory\n");
		return (FALSE);
	}

#ifdef RAW_SALT
	char *rawSalt;

	if ((rawSalt = malloc(strlen(salt) + 1)) == NULL) {
		fprintf(stderr, "Out of memory\n");
		return FALSE;
	}

	saltlen = base64_decode(salt, rawSalt);
	if (saltlen &lt; 1) {
		return (FALSE);
	}

	free(salt);
	salt = rawSalt;
	rawSalt = NULL;
#else
	saltlen = strlen((char *)salt);
#endif

#ifdef PWDEBUG
	fprintf(stderr, "sha        =[%s]\n", sha);
	fprintf(stderr, "iterations =%d\n", iterations);
	fprintf(stderr, "salt       =[%s]\n", salt);
	fprintf(stderr, "salt len   =[%d]\n", saltlen);
	fprintf(stderr, "h_pw       =[%s]\n", h_pw);
	fprintf(stderr, "kenlen     =[%d]\n", keylen);
#endif


	evpmd = EVP_sha256();
	if (strcmp(sha, "sha1") == 0) {
		evpmd = EVP_sha1();
	} else if (strcmp(sha, "sha512") == 0) {
		evpmd = EVP_sha512();
	}

	rc = PKCS5_PBKDF2_HMAC(password, strlen(password),
		(unsigned char *)salt, saltlen,
		iterations,
		evpmd, keylen, out);
	if (rc != 1) {
		goto out;
	}

	blen = base64_encode(out, keylen, &amp;b64);
	if (blen > 0) {
		int i, diff = 0, hlen = strlen(h_pw);
#ifdef PWDEBUG
		fprintf(stderr, "HMAC b64   =[%s]\n", b64);
#endif

		/* "manual" strcmp() to ensure constant time */
		for (i = 0; (i &lt; blen) &amp;&amp; (i &lt; hlen); i++) {
			diff |= h_pw[i] ^ b64[i];
		}

		match = diff == 0;
		if (hlen != blen)
			match = 0;

		free(b64);
	}

  out:
	free(sha);
	free(salt);
	free(h_pw);
	free(out);

	return match;
}</pre>



<p>然而<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">在mosquitto-go-auth中，會發現雖然要求在mosquitto.conf中指定hmac演算法、iteration、salt len、keylen</mark>，但經過trace原始碼發現，目前仍是仿照mosquitto-auth-plug，由取得的hash做tokenize，分別得到HMAC演算法、iteration、salt len、keylen等值後，再將客戶端的明文密碼進行PBKDF2計算。至於日後會不會改變？（也許不會吧）這是要特別注意的地方。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">參考資源</h2>



<ol class="wp-block-list"><li>Eclipsea Mosquitto &#8211; <a rel="noreferrer noopener" href="https://github.com/eclipse/mosquitto" target="_blank">https://github.com/eclipse/mosquitto</a></li><li>mosquitto-auth-plugin &#8211; <a rel="noreferrer noopener" href="https://github.com/jpmens/mosquitto-auth-plug" target="_blank">https://github.com/jpmens/mosquitto-auth-plug</a></li><li>mosquitto-go-auth &#8211; <a href="https://github.com/iegomez/mosquitto-go-auth" target="_blank" rel="noreferrer noopener">https://github.com/iegomez/mosquitto-go-auth</a></li></ol>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.acm.idv.tw/2022/08/14/mosquitto-go-auth%e7%b7%a8%e8%ad%af%e8%88%87%e4%bd%bf%e7%94%a8/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
