126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package acme
|
|
|
|
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
|
|
}
|