在Go中暴露JWK端点时模数生成有误,求排查问题原因
在Go中暴露JWK端点时模数生成错误的问题排查
我尝试在Go中暴露JWK端点,但生成模数的方式似乎不正确,请问我哪里出错了?
密钥生成步骤
openssl genrsa -out private_key.pem 2048
公钥生成命令:
openssl rsa -in private_key.pem -pubout -out public_key.pub
Go程序实现
公钥读取与编码部分
var verifyKey *rsa.PublicKey verifyBytes, err := ioutil.ReadFile("public_key.pub") verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes) modulus := base64.StdEncoding.EncodeToString((*verifyKey.N).Bytes()) exponent := base64.StdEncoding.EncodeToString(big.NewInt(int64(verifyKey.E)).Bytes())
JWK端点处理代码
func (s *ExtAuthzServer) ServeHTTP(response http.ResponseWriter, request *http.Request) { if request.URL.Path == "/.well-known/jwks.json" { log.Printf("[HTTP] jwks requested") n := base64.StdEncoding.EncodeToString((*verifyKey.N).Bytes()) e := base64.StdEncoding.EncodeToString(big.NewInt(int64(verifyKey.E)).Bytes()) keys := PublicKeysData{ Keys: []KeyData{KeyData{"RSA", "go-ext-authz", "sig", n, e}}, } response.WriteHeader(http.StatusOK) b, _ := json.Marshal(keys) _, _ = response.Write([]byte(b)) return } }
结构体定义
type PublicKeysData struct { Keys []KeyData `json:"keys"` } type KeyData struct { Kty string `json:"kty"` Kid string `json:"kid"` Use string `json:"use"` N string `json:"n"` E string `json:"e"` }
请求端点后的输出
HTTP/1.1 200 OK Content-Length: 419 Content-Type: text/plain; charset=utf-8 Date: Fri, 06 Jan 2023 16:35:48 GMT { "keys": [ { "e": "AQAB", "kid": "go-ext-authz", "kty": "RSA", "n": "pulIwmeoYdXIOS+vPMURqJsB2IhL3G+OIgMm8I7FqwgeM1Rf12kxycb8VbAVgaN+cMsVfFzxg+oiUqHW4af6dO503bNgZ88DemO/gT9J9Ob4EcmNNohVX28ts6qRmhOtTN0o4xV3cHXiJYL+JTf3U/GhyEK8bJcIgj1X8kNhl7X3gtza2Ft5S8t61ZepdQJdDIdzq7wpw2DTRJ76rvstOvzvLNjfhPhX48aFaw0tSJKw2LmoawHvUviP6tjro7gFUmLX6xolniv/1U/Uas8ZbNFPZBbUs1mjMccNErtUi02VZuHWqGtHL8v+n7rgso9NMd/ljU+BV/dB2KWnO6dD2Q==", "use": "sig" } ] }
问题排查与修正
问题出在Base64编码格式不符合JWK规范:JWK要求使用Base64URL无填充编码,而你当前使用的是标准Base64编码。
具体修正点
- 将所有
base64.StdEncoding替换为base64.RawURLEncoding,该编码会自动替换标准Base64中的+、/为-、_,并省略末尾的填充=,完全符合JWK的格式要求。 - 对模数
N和指数E的编码都需要做此替换。
修正后的代码示例
// 公钥读取部分的修正 modulus := base64.RawURLEncoding.EncodeToString((*verifyKey.N).Bytes()) exponent := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(verifyKey.E)).Bytes()) // 端点处理部分的修正 n := base64.RawURLEncoding.EncodeToString((*verifyKey.N).Bytes()) e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(verifyKey.E)).Bytes())
补充说明
标准Base64的特殊字符在URL中需要转义,而JWK规范明确要求使用Base64URL无填充格式,避免转义问题,确保客户端能正确解析JWKS内容。
内容的提问来源于stack exchange,提问作者Marc06210
相关产品推荐
相关产品推荐

