package main import ( "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "encoding/base64" "encoding/json" "io/ioutil" "github.com/go-acme/lego/v4/acme" "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/registration" ) type AcmeAccount struct { Email string Registration *registration.Resource Key crypto.PrivateKey } func (a *AcmeAccount) GetEmail() string { return a.Email } func (a *AcmeAccount) GetPrivateKey() crypto.PrivateKey { return a.Key } func (a *AcmeAccount) GetRegistration() *registration.Resource { return a.Registration } func (a *AcmeAccount) FlushToDisk(storage string) { data := map[string]interface{}{ "email": a.Email, "reg": a.Registration, "private_key_encoded": base64.StdEncoding.EncodeToString( certcrypto.PEMEncode(a.Key), ), } raw, _ := json.Marshal(data) ioutil.WriteFile(storage, raw, 0600) } func ClientFromFile(storage, acmeServer string) (*lego.Client, error) { file, err := ioutil.ReadFile(storage) if err != nil { return nil, err } var data map[string]interface{} _ = json.Unmarshal(file, &data) reg, _ := data["reg"].(map[string]interface{}) accountRaw := reg["body"].(map[string]interface{}) contact := accountRaw["contact"].([]interface{}) contacts := make([]string, 0) for _, v := range contact { contacts = append(contacts, v.(string)) } registration := registration.Resource{ URI: reg["uri"].(string), Body: acme.Account{ Status: accountRaw["status"].(string), Contact: contacts, TermsOfServiceAgreed: true, //Orders: accountRaw["orders"].(string), }, } pkEncoded, err := base64.StdEncoding.DecodeString(data["private_key_encoded"].(string)) pk, err := certcrypto.ParsePEMPrivateKey(pkEncoded) account := AcmeAccount{ Email: data["email"].(string), Key: pk.(*ecdsa.PrivateKey), Registration: ®istration, } config := lego.NewConfig(&account) config.CADirURL = acmeServer config.Certificate.KeyType = certcrypto.RSA2048 client, err := lego.NewClient(config) if err != nil { return nil, err } return client, nil } func GenerateNewAccount(email, storage, acmeServer string) (*lego.Client, error) { privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, err } account := AcmeAccount{ Email: email, Key: privateKey, } config := lego.NewConfig(&account) config.CADirURL = acmeServer config.Certificate.KeyType = certcrypto.RSA2048 client, err := lego.NewClient(config) if err != nil { return nil, err } // Register it req, err := client.Registration.Register( registration.RegisterOptions{ TermsOfServiceAgreed: true, }, ) if err != nil { return nil, err } account.Registration = req account.FlushToDisk(storage) return client, nil }