作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 Go 中验证来自 Apple 的 JWT,我需要他们的公钥作为 Go 的 rsa.PublicKey
这样做。我从以下指定的端点检索了他们的 key :
https://developer.apple.com/documentation/sign_in_with_apple/fetch_apple_s_public_key_for_verifying_token_signature
并得到以下信息:
{
"keys": [
{
"kty": "RSA",
"kid": "86D88Kf",
"use": "sig",
"alg": "RS256",
"n": "iGaLqP6y-SJCCBq5Hv6pGDbG_SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3avoVNM8jXevG1Iu1SY11qInqUvjJur--hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOwCPygjLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQtiLk-ILjv1bORSRl8AK677-1T8isGfHKXGZ_ZGtStDe7Lu0Ihp8zoUt59kx2o9uWpROkzF56ypresiIl4WprClRCjz8x6cPZXU2qNWhu71TQvUFwvIvbkE1oYaJMb0jcOTmBRZA2QuYw-zHLwQ",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "eXaunmL",
"use": "sig",
"alg": "RS256",
"n": "4dGQ7bQK8LgILOdLsYzfZjkEAoQeVC_aqyc8GC6RX7dq_KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdDNq1n52TpxQwI2EqxSk7I9fKPKhRt4F8-2yETlYvye-2s6NeWJim0KBtOVrk0gWvEDgd6WOqJl_yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X-Tip84wqwyRpUlq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll-p_Dg8vAXxJLIJ4SNLcqgFeZe4OfHLgdzMvxXZJnPp_VgmkcpUdRotazKZumj6dBPcXI_XID4Z4Z3OM1KrZPJNdUhxw",
"e": "AQAB"
}
]
}
我试过
x509.ParsePKCS1PublicKey(...)
通过解析单个键和使用
asn1.Marshall(...)
返回的整个 JSON 来实现函数功能。我在尝试解析
der
时遇到错误.
"n"
和
"e"
字符串对,并且定义为
here所以我尝试直接创建公钥。但是,
N
和
E
在
rsa.PublicKey
是
*big.Int
和
int
分别。
"n"
的编码和
"e"
,所以我无法准确地将值转换为
rsa.PublicKey
.我试过base64,但是没有用。
rsa.PublicKey
请?
最佳答案
"n"
的值和 "e"
在你的 JSON 中只是 base64 编码的大端二进制整数,所以一旦你解码它们,你可以将它们转换为类型 *big.Int
与 big.Int.SetBytes
,然后使用这些来填充 *rsa.PublicKey
.
您提到您尝试过 base64,但它不起作用,但您需要确保使用正确的编码和填充选项 - -
的存在和 _
编码字符串中的字符表明您正在处理 RFC 4648 URL 安全编码,并且字符串的长度不能被 4 整除的事实表明不存在填充字符,因此 base64.URLEncoding.WithPadding(base64.NoPadding)
是你需要使用的。
您可以直接解码和转换的类型的综合示例:
package main
import (
"crypto/rsa"
"encoding/base64"
"encoding/json"
"log"
"math/big"
)
const keyJSON = `{
"kty": "RSA",
"kid": "86D88Kf",
"use": "sig",
"alg": "RS256",
"n": "4dGQ7bQK8LgILOdLsYzfZjkEAoQeVC_aqyc8GC6RX7dq_KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdDNq1n52TpxQwI2EqxSk7I9fKPKhRt4F8-2yETlYvye-2s6NeWJim0KBtOVrk0gWvEDgd6WOqJl_yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X-Tip84wqwyRpUlq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll-p_Dg8vAXxJLIJ4SNLcqgFeZe4OfHLgdzMvxXZJnPp_VgmkcpUdRotazKZumj6dBPcXI_XID4Z4Z3OM1KrZPJNdUhxw",
"e": "AQAB"
}`
// decodeBase64BigInt decodes a base64-encoded larger integer from Apple's key format.
func decodeBase64BigInt(s string) *big.Int {
buffer, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(s)
if err != nil {
log.Fatalf("failed to decode base64: %v", err)
}
return big.NewInt(0).SetBytes(buffer)
}
// appleKey is a type of public key.
type appleKey struct {
KTY string
KID string
Use string
Alg string
N *big.Int
E int
}
// UnmarshalJSON parses a JSON-encoded value and stores the result in the object.
func (k *appleKey) UnmarshalJSON(b []byte) error {
var tmp struct {
KTY string `json:"kty"`
KID string `json:"kid"`
Use string `json:"use"`
Alg string `json:"alg"`
N string `json:"n"`
E string `json:"e"`
}
if err := json.Unmarshal(b, &tmp); err != nil {
return err
}
*k = appleKey{
KTY: tmp.KTY,
KID: tmp.KID,
Use: tmp.Use,
Alg: tmp.Alg,
N: decodeBase64BigInt(tmp.N),
E: int(decodeBase64BigInt(tmp.E).Int64()),
}
return nil
}
// RSA returns a corresponding *rsa.PublicKey
func (k appleKey) RSA() *rsa.PublicKey {
return &rsa.PublicKey{
N: k.N,
E: k.E,
}
}
func main() {
// Decode the Apple key.
var ak appleKey
if err := json.Unmarshal([]byte(keyJSON), &ak); err != nil {
log.Fatalf("failed to unmarshal JSON: %v", err)
}
// Convert it to a normal *rsa.PublicKey.
rk := ak.RSA()
if rk.Size() != 256 {
log.Fatalf("unexpected key size: %d", rk.Size())
}
// Do what you like with the RSA key now.
}
关于go - Marshal AppleID 的公钥到 rsa.PublicKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66067321/
我是一名优秀的程序员,十分优秀!