在Go中暴露公共JWK

xqnpmsa8  于 2023-01-10  发布在  Go
关注(0)|答案(1)|浏览(170)

我试图在Go语言中公开一个JWK的端点,但是我生成模数的方式似乎不正确,我做错了什么?
下面是我生成密钥的方法:

openssl genrsa -out private_key.pem 2048

公共部分:

openssl rsa -in private_key.pem -pubout -out public_key.pub

在我的围棋程序中,我是这样做的:

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())

下面是密钥的公开方式:

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"`
}

下面是curl的输出(我指的是HTTPie):

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"
        }
    ]
}
2ul0zpep

2ul0zpep1#

根据规范,您不能使用标准base64编码:

6.3.1.1.“n”(模数)参数

“n”(modulus)参数包含RSA公钥的模值。它表示为Base64 urlUInt编码的值。
请注意,实现人员发现,某些加密库在返回的模数表示形式前添加了一个额外的零值八位字节,例如,对于2048位密钥返回257个八位字节,而不是256个。使用此类库的实现需要注意从base64 url编码的表示形式中忽略额外的八位字节。

6.3.1.2.“e”(指数)参数

“e”(指数)参数包含RSA公钥的指数值。它表示为Base64 urlUInt编码的值。
例如,当表示值65537时,将被base64 url编码的八位组序列必须由三个八位组[1,0,1]组成;该值的结果表示是“AQAB”。
Go语言有urlEncoding,如果需要的话,可以额外配置使用填充。
阅读上面的规范,您可能希望使用没有任何填充的urlencoding。

base64.RawURLEncoding.EncodeToString(...)

相关问题