package acme import ( "crypto" "crypto/ecdsa" "crypto/rsa" "encoding/base64" "io" "strings" "github.com/square/go-jose" ) // KeySize is a default RSA key size const KeySize = 2048 // Account ... type Account struct { key crypto.PrivateKey signer jose.Signer } func NewAccount(key crypto.PrivateKey) (*Account, error) { switch k := key.(type) { case *rsa.PrivateKey: signer, err := jose.NewSigner(jose.RS256, k) return &Account{key: k, signer: signer}, err case *ecdsa.PrivateKey: signer, err := jose.NewSigner(jose.ES384, k) return &Account{key: k, signer: signer}, err default: return nil, errKeyType } } // Signer describes a signing interface type Signer interface { Sign([]byte, jose.NonceSource) (io.Reader, error) KeyAuth(string) (string, error) } // 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, error) { var wk *jose.JsonWebKey switch k := a.key.(type) { case *rsa.PrivateKey: wk = &jose.JsonWebKey{Key: k.Public(), Algorithm: "RSA"} case *ecdsa.PrivateKey: wk = &jose.JsonWebKey{Key: k.Public(), Algorithm: "EC"} } thumb, err := wk.Thumbprint(crypto.SHA256) if err != nil { return "", err } return token + "." + base64.RawURLEncoding.EncodeToString(thumb), nil }