Category Archives

147 Articles

Ubuntu 22.04 / OpenSSH 8.9 使用 gpg-agent 登錄報錯 agent refused operation 的解決方法

0   5898 轉為簡體

Ubuntu 22.04 升級了 OpenSSH 到8.9,這個版本默認開啟 [email protected] 作為密鑰交換(KEX)方法。這個演算法使用 512 bit 的 hash。

如果客戶端和服務端都升級到了8.9或以上,則成功協商使用這一KEX演算法,這時如果使用 gpg-agent 的 SSH 功能簽名則會報 agent refused operation。

列印 gpg-agent 的日誌可看到報錯為 Provided object is too large。

解決方法是在客戶端(~/.ssh/config)或服務端(/etc/ssh/sshd_config)中禁用這個演算法

同理 diffie-hellman-group16-sha512 和 diffie-hellman-group18-sha512 也應該被禁用,但它們優先順序本來就很低。

如果仍然有問題,把Kex Host Key Algorithm也改一下,如改成

Go中JSON解碼非UTF-8二進位值的問題

0   8585 轉為簡體

我們在一個項目中創(luan)新(xie)地用JSON來編碼msgpack編碼後的結果(即encoded = json_encode(msgpack_encode(txt))),結果發現Golang側無法解碼。

首先我們可以確定msgpack沒有問題,因為輸入給msgpack解碼數據就與輸入值不一致。

我們使用lua-cjson來編碼一個JSON,因為結果不是printable的,所以在外面加一層base64.encode

結果是eyJhIjoihjEyMyJ9。

在Python里解碼它:

結果是{‘a’: ‘\x86123’}。沒有問題,和輸入一致。

在Go里解碼它:

結果是[239 191 189 49 50 51],可以看到\x86被解碼成了\239 \191 \189即\xefbfbd,表示無效的UTF8字元。

這是因為Go默認採用UTF-8解碼,如果field被標記為string,則json.Unmarshal會使用utf8.DecodeRune來嘗試解碼輸入https://github.com/golang/go/blob/master/src/encoding/json/decode.go#L1304。但在我們的場景中,\x86是一個單位元組的非UTF-8字元,所以utf8.DecodeRune返回了utf8.RuneError並把它放到了結果里。

那麼到底是哪裡出了問題呢?

首先,JSON的RFC指出,其中的字元串必須以UTF-8編碼(https://datatracker.ietf.org/doc/html/rfc8259#section-8.1),但是同時也提到,除了幾個特殊的字元外,其中的字元可以被escape也可以不escape(https://datatracker.ietf.org/doc/html/rfc8259#section-7)。所以lua-cjson的這種編碼方式似乎也是合法的?

解決辦法是寫一個自己的Unmarshal方法。首先把結構體中的field標記為自定義類型:

然後我們魔改unquote方法,在原來的基礎上加上對解碼結果是否為utf8.RuneError的判斷

還需要注意的是,Go的json包默認對[]byte類型的field進行base64編解碼:

結果是> [123 34 120 34 58 34 107 119 61 61 34 125] {“x”:”kw==”};同理Unmarshal時也會需要輸入為base64編碼結果。

因此在上面這個解決方法中,我們用rawBytes這個新類型來alias到[]byte,而並不直接使用[]byte類型再在之後自己解碼。

發了一個issue:https://github.com/golang/go/issues/51094。

另外的JSON庫沒有這個問題,測試了https://github.com/json-iterator/go 和 https://github.com/bytedance/sonic

開源了鹹魚撿的京付的三色墨水屏驅動

0   7811 轉為簡體

35塊一個,長這樣

經過一番Google找到了對應的原廠屏,是Gooddisplay的GDEH042Z96,屏幕晶元是SSD1619A,這個晶元初始化序列比幻塔的新手教程還長。

整理了一下官方常式之後,發了一個PR:https://github.com/ZinggJM/GxEPD2/pull/47;有一些點需要注意:

  1. 三色屏(實際上是雙色)是兩種液晶分開刷新的,先刷黑色,再刷紅色。其中SSD1619A的紅色輸入值需要取反,否則屏幕整塊都是紅的。
  2. 這塊屏只支持全刷,全刷一次要20秒,要把GxEPD2的默認等待BUSY pin的時間調長。

效果如下圖所示,用的是我魔改的中文版天氣:https://github.com/fffonion/ESP32-e-Paper-Weather-Display