如何将* rsa.PublicKey转换为可识别的密钥字符串

时间:2018-11-25 00:30:04

标签: go

我有这个功能:

func GetSigningKey() *rsa.PublicKey {
    set, _ := jwk.ParseString(GetWellKnown())
    publicKey, _ := set.Keys[0].Materialize()
    return publicKey.(*rsa.PublicKey)
}

.Materialize()返回interface{},所以我使用此函数将其强制转换为(我认为是)期望的类型。

然后我可以将该令牌用于:

publicKey := GetSigningKey()

token, _ := jwt.Parse(tokenString, func(*jwt.Token) (interface{}, error) {
    return publicKey, nil
})

fmt.Println(token.Valid)

几个问题:

GetSigningKey函数的目的是从众所周知的文件中获取签名密钥,并将结果密钥转换为正确的类型。

1)这需要一个位于GetWellKnown()中的http请求。在该函数中,我执行http请求,并将响应缓存在一个变量中,以便后续请求将从该变量中提取。这是一个好习惯吗? (跟进,我应该对GetSigningKey()中解析的公钥执行相同的操作)

2)我是否认为这是将interface{}转换为正确类型的最佳方法,对吗?

3)如果尝试使用fmt.Println(GetSigningKey()),我会得到一长串无法识别的数字

&{2568409364095596940117712027335...  %!s(int=65537)}635 <nil>

我在这里看到什么?

1 个答案:

答案 0 :(得分:0)

在您的代码中没有错误检查。尤其是如果JWKS为空或包含非RSA密钥的东西,则您的程序将崩溃,而这往往不是Go中鼓励的行为。我将对整个事情进行一些检查;例如,

func GetSigningKey() *rsa.PublicKey, error {
        ...
        if rsaKey, ok := publicKey.(*rsa.PublicKey); ok {
                return rsaKey, nil
        }
        return nil, errors.New("not an RSA key")
}

请记住,other signing methods存在,原则上您可以获取ECDSA密钥或(理论上)用于对称签名的原始密钥,因此在此处进行检查很有价值。

您应该尝试的另一种高级方法是获取原始JSON Web令牌并对其进行解码; https://jwt.io/有一个我使用的调试器。如果标头包含名为"kid"的声明,它是一个密钥ID,那么您应该能够将该密钥ID作为输入传递给JWKS库。这应该比盲目使用JWKS中的第一个密钥更强大。

联机JWKS文档可以更改,但是通常很少更改(以几个月为单位)。 (如果它们确实发生了变化,那么JWKS可能会同时包含旧密钥和新密钥。)在过程中对其进行高速缓存是非常合理的。如果您看到"kid",则表示您无法尝试重新获取文档。

您的fmt.Printf输出看起来可能是原始的RSA公钥。公钥本身由两个数字组成,一个是两个大质数的乘积,第二个通常恰好是65537。Wikipedia description of RSA中对此有更多讨论。