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()), | ||
|  | 	} | ||
|  | } |