The values of "n"
and "e"
in your JSON are just base64-encoded big-endian binary integers, so once you've decoded them you can convert them to type *big.Int
with big.Int.SetBytes
, and then use those to populate an *rsa.PublicKey
.
You mentioned you tried base64 and it didn't work, but you need to make sure you use the right encoding and padding options- the presence of -
and _
characters in the encoded string indicates that you're dealing with the RFC 4648 URL-safe encoding, and the fact that the length of the string is not divisible by 4 indicates that no padding characters are present, so therefore base64.URLEncoding.WithPadding(base64.NoPadding)
is what you need to use.
Comprehensive example of a type you can directly unmarshal into and convert:
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.
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…