71 lines
1.7 KiB
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()),
|
|
}
|
|
}
|