rio/account.go

127 lines
2.7 KiB
Go
Raw Normal View History

2023-12-31 21:41:51 +00:00
package main
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/json"
"encoding/base64"
"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: &registration,
}
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
}