package acme import ( "crypto/rsa" "encoding/json" "io" "io/ioutil" "net/mail" "strings" "github.com/square/go-jose" ) // KeySize is a default RSA key size const KeySize = 2048 // Account ... type Account struct { Contact Contacts `json:"contact"` PrivKey *rsa.PrivateKey `json:"key"` signer jose.Signer nonce chan string } func newMail(email string) (Mail, error) { m, err := mail.ParseAddress(email) if err != nil { return "", err } mm := Mail(m.Address) return mm, nil } func newPhone(phone string) (Phone, error) { p := strings.TrimSpace(phone) return Phone(p), nil } // NewAccount ... func NewAccount(email, phone string, key *rsa.PrivateKey) (*Account, error) { var c Contacts m, err := newMail(email) if err != nil { return nil, err } c = append(c, m) if ph, _ := newPhone(phone); ph != "" { c = append(c, ph) } return &Account{ Contact: c, PrivKey: key, }, nil } func LoadAccount(fname string) (*Account, error) { body, err := ioutil.ReadFile(fname) if err != nil { return nil, err } a := new(Account) err = json.Unmarshal(body, a) return a, err } func (a Account) SaveAccount(fname string) error { body, err := json.MarshalIndent(a, "", "\t") if err != nil { return err } return ioutil.WriteFile(fname, body, 0600) } // Signer describes a signing interface type Signer interface { Sign([]byte, jose.NonceSource) (io.Reader, error) } func (a *Account) Sign(msg []byte, n jose.NonceSource) (io.Reader, error) { if a.signer == nil { var err error a.signer, err = jose.NewSigner(jose.RS256, a.PrivKey) if err != nil { return nil, err } a.signer.SetNonceSource(n) } obj, err := a.signer.Sign(msg) if err != nil { return nil, err } return strings.NewReader(obj.FullSerialize()), nil }