go-mockid/xkeypairs/jwk.go

71 lines
1.7 KiB
Go

package xkeypairs
import (
"crypto/ecdsa"
"crypto/rsa"
"encoding/base64"
"errors"
"fmt"
"math/big"
"git.rootprojects.org/root/keypairs"
)
type JWK interface {
marshalJWK() ([]byte, error)
}
type ECJWK struct {
KeyID string `json:"kid,omitempty"`
Curve string `json:"crv"`
X string `json:"x"`
Y string `json:"y"`
Use []string `json:"use,omitempty"`
Seed string `json:"_seed,omitempty"`
}
func (k *ECJWK) marshalJWK() ([]byte, error) {
return []byte(fmt.Sprintf(`{"crv":%q,"kty":"EC","x":%q,"y":%q}`, k.Curve, k.X, k.Y)), nil
}
type RSAJWK struct {
KeyID string `json:"kid,omitempty"`
Exp string `json:"e"`
N string `json"n"`
Use []string `json:"use,omitempty"`
Seed string `json:"_seed,omitempty"`
}
func (k *RSAJWK) marshalJWK() ([]byte, error) {
return []byte(fmt.Sprintf(`{"e":%q,"kty":"RSA","n":%q}`, k.Exp, k.N)), nil
}
func ToPublicJWK(pubkey keypairs.PublicKey) JWK {
switch k := pubkey.Key().(type) {
case *ecdsa.PublicKey:
return ECToPublicJWK(k)
case *rsa.PublicKey:
return RSAToPublicJWK(k)
default:
panic(errors.New("impossible key type"))
return nil
}
}
// ECToPublicJWK will output the most minimal version of an EC JWK (no key id, no "use" flag, nada)
func ECToPublicJWK(k *ecdsa.PublicKey) *ECJWK {
return &ECJWK{
Curve: k.Curve.Params().Name,
X: base64.RawURLEncoding.EncodeToString(k.X.Bytes()),
Y: base64.RawURLEncoding.EncodeToString(k.Y.Bytes()),
}
}
// RSAToPublicJWK will output the most minimal version of an RSA JWK (no key id, no "use" flag, nada)
func RSAToPublicJWK(p *rsa.PublicKey) *RSAJWK {
return &RSAJWK{
Exp: base64.RawURLEncoding.EncodeToString(big.NewInt(int64(p.E)).Bytes()),
N: base64.RawURLEncoding.EncodeToString(p.N.Bytes()),
}
}