aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-03-06 02:26:20 +0100
committerDimitri Sokolyuk <demon@dim13.org>2016-03-06 02:26:20 +0100
commitcf49d970245fdd871a85c9393a54bdefcbdfc39a (patch)
treec793c47b5837c21e1d8c13e7604651f471de6cb7
parent15d5478b1ebbeab7e34ead678d4d963ed736be9a (diff)
Move file handling out of the lib
-rw-r--r--account.go37
-rw-r--r--cmd/acme/fs.go64
-rw-r--r--cmd/acme/main.go27
-rw-r--r--crypto.go62
-rw-r--r--desire.go33
-rw-r--r--solve_tls.go2
-rw-r--r--solve_webroot.go10
7 files changed, 107 insertions, 128 deletions
diff --git a/account.go b/account.go
index a5a3886..7ac6089 100644
--- a/account.go
+++ b/account.go
@@ -3,8 +3,6 @@ package acme
import (
"crypto"
"crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
"crypto/rsa"
"encoding/base64"
"io"
@@ -22,31 +20,7 @@ type Account struct {
signer jose.Signer
}
-func LoadAccount(fname string) (*Account, error) {
- key, err := LoadKeyFile(fname)
- if err != nil {
- return nil, err
- }
- return newAccount(key)
-}
-
-func NewAccount(size int) (*Account, error) {
- key, err := rsa.GenerateKey(rand.Reader, size)
- if err != nil {
- return nil, err
- }
- return newAccount(key)
-}
-
-func NewAccountEC() (*Account, error) {
- key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
- if err != nil {
- return nil, err
- }
- return newAccount(key)
-}
-
-func newAccount(key crypto.PrivateKey) (*Account, error) {
+func NewAccount(key crypto.PrivateKey) (*Account, error) {
switch k := key.(type) {
case *rsa.PrivateKey:
signer, err := jose.NewSigner(jose.RS256, k)
@@ -89,12 +63,3 @@ func (a *Account) KeyAuth(token string) (string, error) {
}
return token + "." + base64.RawURLEncoding.EncodeToString(thumb), nil
}
-
-func (a *Account) Save(fname string) error {
- fd, err := CreateFile(fname, 0600)
- if err != nil {
- return err
- }
- defer fd.Close()
- return SaveKey(fd, a.key)
-}
diff --git a/cmd/acme/fs.go b/cmd/acme/fs.go
new file mode 100644
index 0000000..4f8c479
--- /dev/null
+++ b/cmd/acme/fs.go
@@ -0,0 +1,64 @@
+package main
+
+import (
+ "crypto"
+ "crypto/tls"
+ "io"
+ "os"
+ "syscall"
+
+ "dim13.org/acme"
+)
+
+func NewFile(fname string, mode os.FileMode) (io.WriteCloser, error) {
+ err := os.Rename(fname, fname+".bak")
+ if nerr, ok := err.(*os.LinkError); ok && nerr.Err != syscall.ENOENT {
+ return nil, err
+ }
+ flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC
+ return os.OpenFile(fname, flags, mode)
+}
+
+func (d domain) Save(cert tls.Certificate) error {
+ // save key
+ fd, err := NewFile(d.KeyFile, 0600)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ err = acme.SaveKey(fd, cert.PrivateKey)
+ if err != nil {
+ return err
+ }
+
+ // save certs
+ fd, err = NewFile(d.CrtFile, 0644)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ for _, crt := range cert.Certificate {
+ if err := acme.SaveCert(fd, crt); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (a account) Save(key crypto.PrivateKey) error {
+ fd, err := NewFile(a.KeyFile, 0600)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ return acme.SaveKey(fd, key)
+}
+
+func (a account) Load() (crypto.PrivateKey, error) {
+ fd, err := os.Open(a.KeyFile)
+ if err != nil {
+ return nil, err
+ }
+ defer fd.Close()
+ return acme.LoadKey(fd)
+}
diff --git a/cmd/acme/main.go b/cmd/acme/main.go
index 721d204..50855d9 100644
--- a/cmd/acme/main.go
+++ b/cmd/acme/main.go
@@ -41,10 +41,22 @@ func main() {
for _, v := range v.Account {
log.Println("Load", v.KeyFile)
- acc, err := getAccount(v.KeyFile, v.KeySize)
+ key, err := v.Load()
+ if err != nil {
+ key, err = acme.NewKey(v.KeySize)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+ if err := v.Save(key); err != nil {
+ log.Fatal(err)
+ }
+
+ acc, err := acme.NewAccount(key)
if err != nil {
log.Fatal(err)
}
+
con := acme.Contacts{}
con.AddMail(v.Mail)
con.AddPhone(v.Phone)
@@ -84,21 +96,10 @@ func main() {
}
log.Println("Save", v.CrtFile, v.KeyFile)
- if err := des.SaveKeyPair(v.CrtFile, v.KeyFile); err != nil {
+ if err := v.Save(des.Cert()); err != nil {
log.Fatal(err)
}
}
}
}
}
-
-func getAccount(keyFile string, keySize int) (*acme.Account, error) {
- acc, err := acme.LoadAccount(keyFile)
- if err != nil {
- acc, err = acme.NewAccount(keySize)
- if err != nil {
- return nil, err
- }
- }
- return acc, acc.Save(keyFile)
-}
diff --git a/crypto.go b/crypto.go
index 5ed81c0..eb859c2 100644
--- a/crypto.go
+++ b/crypto.go
@@ -3,14 +3,14 @@ package acme
import (
"crypto"
"crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"io"
"io/ioutil"
- "os"
- "syscall"
)
const (
@@ -21,13 +21,20 @@ const (
var errKeyType = errors.New("unknown key type")
-func LoadKeyFile(fname string) (crypto.PrivateKey, error) {
- fd, err := os.Open(fname)
- if err != nil {
- return nil, err
+func SaveKey(w io.Writer, key crypto.PrivateKey) error {
+ var block *pem.Block
+ switch k := key.(type) {
+ case *rsa.PrivateKey:
+ der := x509.MarshalPKCS1PrivateKey(k)
+ block = &pem.Block{Type: pemRSA, Bytes: der}
+ case *ecdsa.PrivateKey:
+ der, err := x509.MarshalECPrivateKey(k)
+ if err != nil {
+ return err
+ }
+ block = &pem.Block{Type: pemEC, Bytes: der}
}
- defer fd.Close()
- return LoadKey(fd)
+ return pem.Encode(w, block)
}
func LoadKey(r io.Reader) (crypto.PrivateKey, error) {
@@ -46,23 +53,7 @@ func LoadKey(r io.Reader) (crypto.PrivateKey, error) {
}
}
-func SaveKey(w io.Writer, key crypto.PrivateKey) error {
- var block *pem.Block
- switch k := key.(type) {
- case *rsa.PrivateKey:
- der := x509.MarshalPKCS1PrivateKey(k)
- block = &pem.Block{Type: pemRSA, Bytes: der}
- case *ecdsa.PrivateKey:
- der, err := x509.MarshalECPrivateKey(k)
- if err != nil {
- return err
- }
- block = &pem.Block{Type: pemEC, Bytes: der}
- }
- return pem.Encode(w, block)
-}
-
-func saveCert(w io.Writer, cert []byte) error {
+func SaveCert(w io.Writer, cert []byte) error {
block := &pem.Block{
Type: pemCRT,
Bytes: cert,
@@ -70,15 +61,6 @@ func saveCert(w io.Writer, cert []byte) error {
return pem.Encode(w, block)
}
-func LoadCertFile(fname string) ([]*x509.Certificate, error) {
- fd, err := os.Open(fname)
- if err != nil {
- return nil, err
- }
- defer fd.Close()
- return LoadCerts(fd)
-}
-
func LoadCerts(r io.Reader) ([]*x509.Certificate, error) {
der, err := ioutil.ReadAll(r)
if err != nil {
@@ -88,11 +70,11 @@ func LoadCerts(r io.Reader) ([]*x509.Certificate, error) {
return x509.ParseCertificates(block.Bytes)
}
-func CreateFile(fname string, mode os.FileMode) (io.WriteCloser, error) {
- err := os.Rename(fname, fname+".bak")
- if nerr, ok := err.(*os.LinkError); ok && nerr.Err != syscall.ENOENT {
- return nil, nerr
+func NewKey(size int) (crypto.PrivateKey, error) {
+ switch size {
+ case 0:
+ return ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
+ default:
+ return rsa.GenerateKey(rand.Reader, size)
}
- flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC
- return os.OpenFile(fname, flags, mode)
}
diff --git a/desire.go b/desire.go
index 4e7392a..148523f 100644
--- a/desire.go
+++ b/desire.go
@@ -2,7 +2,6 @@ package acme
import (
"crypto/rand"
- "crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
@@ -16,7 +15,7 @@ type Desire struct {
}
func NewDesire(altnames []string, size int) (*Desire, error) {
- key, err := rsa.GenerateKey(rand.Reader, size)
+ key, err := NewKey(size)
if err != nil {
return nil, err
}
@@ -54,32 +53,6 @@ func (d *Desire) LoadKeyPair(certFile, keyFile string) (err error) {
return
}
-func (d *Desire) SaveKeyPair(certFile, keyFile string) error {
- if err := d.saveKey(keyFile); err != nil {
- return err
- }
- return d.saveCert(certFile)
-}
-
-func (d *Desire) saveKey(fname string) error {
- fd, err := CreateFile(fname, 0600)
- if err != nil {
- return err
- }
- defer fd.Close()
- return SaveKey(fd, d.cert.PrivateKey)
-}
-
-func (d *Desire) saveCert(fname string) error {
- fd, err := CreateFile(fname, 0644)
- if err != nil {
- return err
- }
- defer fd.Close()
- for _, crt := range d.cert.Certificate {
- if err := saveCert(fd, crt); err != nil {
- return err
- }
- }
- return nil
+func (d *Desire) Cert() tls.Certificate {
+ return d.cert
}
diff --git a/solve_tls.go b/solve_tls.go
index 4e376c1..36bbf11 100644
--- a/solve_tls.go
+++ b/solve_tls.go
@@ -55,7 +55,7 @@ func newCert(domain string) (tls.Certificate, error) {
fail := func(err error) (tls.Certificate, error) {
return tls.Certificate{}, err
}
- key, err := rsa.GenerateKey(rand.Reader, 2048)
+ key, err := rsa.GenerateKey(rand.Reader, 2048) // NewKey(2048)
if err != nil {
return fail(err)
}
diff --git a/solve_webroot.go b/solve_webroot.go
index 096ca4a..12720f3 100644
--- a/solve_webroot.go
+++ b/solve_webroot.go
@@ -1,7 +1,7 @@
package acme
import (
- "io"
+ "io/ioutil"
"log"
"os"
"path"
@@ -23,13 +23,7 @@ func (s *webrootSolver) Solve(ch Challenge) error {
if err != nil {
return err
}
- fd, err := CreateFile(s.file, 0644)
- if err != nil {
- return err
- }
- defer fd.Close()
- _, err = io.WriteString(fd, ch.KeyAuthorization)
- return err
+ return ioutil.WriteFile(s.file, []byte(ch.KeyAuthorization), 0644)
}
func (s *webrootSolver) Solved() error {