package acme import ( "crypto" "crypto/ecdsa" "crypto/rsa" "encoding/base64" "io" "strings" "gopkg.in/square/go-jose.v1" ) // KeySize is a default RSA key size const KeySize = 2048 // Account ... type Account struct { signer jose.Signer thumb string } func NewAccount(privKey crypto.PrivateKey) (*Account, error) { thumb := func(alg string, pubKey crypto.PublicKey) (string, error) { wk := &jose.JsonWebKey{Key: pubKey, Algorithm: alg} t, err := wk.Thumbprint(crypto.SHA256) return base64.RawURLEncoding.EncodeToString(t), err } switch k := privKey.(type) { case *rsa.PrivateKey: s, err := jose.NewSigner(jose.RS256, k) if err != nil { return nil, err } t, err := thumb("RSA", k.Public()) if err != nil { return nil, err } return &Account{signer: s, thumb: t}, nil case *ecdsa.PrivateKey: s, err := jose.NewSigner(jose.ES384, k) if err != nil { return nil, err } t, err := thumb("EC", k.Public()) if err != nil { return nil, err } return &Account{signer: s, thumb: t}, nil default: return nil, errKeyType } } // Signer describes a signing interface type Signer interface { Sign([]byte, jose.NonceSource) (io.Reader, error) KeyAuth(string) string } // Sign implements Signer interface func (a Account) Sign(msg []byte, n jose.NonceSource) (io.Reader, error) { a.signer.SetNonceSource(n) obj, err := a.signer.Sign(msg) if err != nil { return nil, err } return strings.NewReader(obj.FullSerialize()), nil } func (a Account) KeyAuth(token string) string { return token + "." + a.thumb }