From f7a6acda0e7d04c3fd98e72c6089ba4cfad74ddf Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Thu, 31 Dec 2015 01:24:02 +0100 Subject: Encapsulate desire --- account.go | 15 ++++++++++++ client.go | 11 +++++++-- cmd/acme/main.go | 4 ++- crypto.go | 14 +++++++---- desire.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 desire.go diff --git a/account.go b/account.go index 6749bbf..b1312c0 100644 --- a/account.go +++ b/account.go @@ -6,6 +6,8 @@ import ( "encoding/base64" "io" "net/mail" + "os" + "path" "strings" "github.com/square/go-jose" @@ -87,3 +89,16 @@ func KeyAuthorization(s Thumber, token string) (string, error) { } return token + "." + thumb, nil } + +func (a *Account) Save(fname string) error { + if err := os.MkdirAll(path.Dir(fname), 0700); err != nil { + return err + } + flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC + fd, err := os.OpenFile(fname, flags, 0600) + if err != nil { + return err + } + defer fd.Close() + return SaveKey(fd, a.privKey) +} diff --git a/client.go b/client.go index c14d188..eae9f30 100644 --- a/client.go +++ b/client.go @@ -2,6 +2,7 @@ package acme import ( "crypto/rsa" + "crypto/x509" "encoding/json" "errors" "io/ioutil" @@ -297,7 +298,7 @@ func (c *Client) queryStatus(url string, n int, done chan bool) error { return nil } -func (c *Client) Cert(s Signer, altnames []string, key *rsa.PrivateKey) ([]byte, error) { +func (c *Client) Cert(s Signer, altnames []string, key *rsa.PrivateKey) (*x509.Certificate, error) { csr, err := NewCSR(altnames, key) if err != nil { return nil, err @@ -311,5 +312,11 @@ func (c *Client) Cert(s Signer, altnames []string, key *rsa.PrivateKey) ([]byte, return nil, err } defer resp.Body.Close() - return ioutil.ReadAll(resp.Body) + ns := parseHeader(resp) + log.Println(ansi.Color("NEXT", "green"), ns) + der, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return x509.ParseCertificate(der) } diff --git a/cmd/acme/main.go b/cmd/acme/main.go index 762de5f..dc397b2 100644 --- a/cmd/acme/main.go +++ b/cmd/acme/main.go @@ -2,6 +2,7 @@ package main import ( "crypto/rsa" + "crypto/x509" "flag" "io" "log" @@ -40,7 +41,7 @@ func chkKey(k PrivKey) (*rsa.PrivateKey, error) { } } -func saveCert(k Cert, crt []byte) error { +func saveCert(k Cert, crt *x509.Certificate) error { cert := k.CertPath() fd, err := mkdirCreate(cert, 0755, 0644) if err != nil { @@ -98,6 +99,7 @@ func main() { if err != nil { log.Fatal("cert", err) } + log.Println(crt.NotBefore, crt.NotAfter) err = saveCert(des, crt) if err != nil { diff --git a/crypto.go b/crypto.go index f70cc2f..7ceefcc 100644 --- a/crypto.go +++ b/crypto.go @@ -25,11 +25,15 @@ func NewKey(w io.Writer, size int) (*rsa.PrivateKey, error) { if err != nil { return nil, err } + return key, SaveKey(w, key) +} + +func SaveKey(w io.Writer, key *rsa.PrivateKey) error { block := &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key), } - return key, pem.Encode(w, block) + return pem.Encode(w, block) } func NewCSR(altnames []string, key *rsa.PrivateKey) (string, error) { @@ -48,19 +52,19 @@ func NewCSR(altnames []string, key *rsa.PrivateKey) (string, error) { return base64.RawURLEncoding.EncodeToString(der), nil } -func SaveCert(w io.Writer, der []byte) error { +func SaveCert(w io.Writer, crt *x509.Certificate) error { block := &pem.Block{ Type: "CERTIFICATE", - Bytes: der, + Bytes: crt.Raw, } return pem.Encode(w, block) } -func LoadCert(r io.Reader) ([]*x509.Certificate, error) { +func LoadCert(r io.Reader) (*x509.Certificate, error) { der, err := ioutil.ReadAll(r) if err != nil { return nil, err } block, _ := pem.Decode(der) - return x509.ParseCertificates(block.Bytes) + return x509.ParseCertificate(block.Bytes) } diff --git a/desire.go b/desire.go new file mode 100644 index 0000000..5a2aaf8 --- /dev/null +++ b/desire.go @@ -0,0 +1,74 @@ +package acme + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "os" + "path" +) + +type Desire struct { + altnames []string + key *rsa.PrivateKey + cert []*x509.Certificate + signer Signer +} + +func NewDesire(altnames []string, size int) (*Desire, error) { + key, err := rsa.GenerateKey(rand.Reader, size) + if err != nil { + return nil, err + } + return &Desire{ + key: key, + altnames: altnames, + }, nil +} + +func (d *Desire) SaveKey(fname string) error { + if err := os.MkdirAll(path.Dir(fname), 0700); err != nil { + return err + } + flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC + fd, err := os.OpenFile(fname, flags, 0600) + if err != nil { + return err + } + defer fd.Close() + return SaveKey(fd, d.key) +} + +func (d *Desire) SaveCert(fname string) error { + if err := os.MkdirAll(path.Dir(fname), 0755); err != nil { + return err + } + flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC + fd, err := os.OpenFile(fname, flags, 0644) + if err != nil { + return err + } + defer fd.Close() + for _, cert := range d.cert { + if err := SaveCert(fd, cert); err != nil { + return err + } + } + return nil +} + +func (d *Desire) NewCSR() (string, error) { + tmpl := x509.CertificateRequest{ + Subject: pkix.Name{CommonName: d.altnames[0]}, + } + if len(d.altnames) > 1 { + tmpl.DNSNames = d.altnames + } + der, err := x509.CreateCertificateRequest(rand.Reader, &tmpl, d.key) + if err != nil { + return "", err + } + return base64.RawURLEncoding.EncodeToString(der), nil +} -- cgit v1.2.3