Yearly Archives

2 Articles

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

0   4615 轉為簡體

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   6868 轉為簡體

我們在一個項目中創(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