我试图在GO中公开jwks端点,但我生成模数的方式似乎不正确. 有没有人已经做过了,可以告诉我我做错了什么?

以下是我如何生成我的密钥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
    }    
}

具有以下 struct 定义

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

推荐答案

根据spec,您不能使用标准的Base64编码:

6.3.1.1. "n" (Modulus) Parameter

"n"(模数)参数包含RSA的模数值 公钥.它表示为Base64urlUInt编码值.

请注意,实施者已经发现一些加密库 在它们的模数表示法前面加上一个额外的零值八位字节 例如,返回2048位密钥的257个八位字节,而不是 而不是256.使用这类库的实现将需要 注意从base 64url编码的代码中省略额外的八位字节 代表权.

6.3.1.2. "e" (Exponent) Parameter

"e"(指数)参数包含RSA的指数值 公钥.它表示为Base64urlUInt编码值.

例如,当表示值65537时,八位组序列 要进行Base64url编码,必须由三个八位字节[1,0,1]组成; 该值的结果表示为"AQAB".

Go有urlEncoding个,如果需要,可以额外配置为使用填充.

阅读上面的规范,您可能希望使用不带任何填充的url编码.

 base64.RawURLEncoding.EncodeToString(...)

Go相关问答推荐

Go-Colly:将数据切片为POST请求

带有条件的for循环中缺少RETURN语句

如何从 nil 指针创建值

如何使用 html/template 在 golang 中运行一个范围内的范围

使用Goldmark在golang中添加ChildNode会导致堆栈溢出

一个Go module可以和之前的非module模块发布在同一个路径下吗?

当我的 go build 成功时,如何修复我的 docker build 失败? Dockerfile 包括 go mod 下载

Golang - POST 失败(NoSurf CSRF)

GoLang: gocui 边框 colored颜色

在 .go 文件中运行一个函数和在 Go 模板中调用它有什么区别?

致命错误 - 所有 Goroutines 都睡着了!僵局

如何使用 Go 代理状态为 OK 的预检请求?

如何过滤来自 fsnotify 的重复系统消息

如何在没有内存分配的情况下压缩和发布文件

当有多个同名包时如何在vscode中显示golang包完整路径?

如何 Select 前 N 个元素 Gin-Gorm

如何从 Go 1.18 中的单个方法返回两种不同的具体类型?

如何正确判断 io.Reader 是否为零?

如何在 Go 中使用 Pact 返回错误请求(400、500)?

go routine 和接收错误或成功的通道