From 7ca19d9f729b96229ddec049b23adfc28a582aa8 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 15 Dec 2015 14:58:19 +0100 Subject: Create keys --- cmd/acmed/config.go | 27 ++++++++++++++--- cmd/acmed/main.go | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) (limited to 'cmd') diff --git a/cmd/acmed/config.go b/cmd/acmed/config.go index 2e19849..4130aab 100644 --- a/cmd/acmed/config.go +++ b/cmd/acmed/config.go @@ -1,6 +1,10 @@ package main -import "github.com/BurntSushi/toml" +import ( + "crypto/rsa" + + "github.com/BurntSushi/toml" +) type Config struct { Defaults defaults @@ -16,6 +20,7 @@ type defaults struct { Provider string Account string Basedir string + KeySize int } type provider struct { @@ -23,9 +28,11 @@ type provider struct { } type account struct { - Mail string - Phone string - Key string + Mail string + Phone string + Key string + KeySize int + key *rsa.PrivateKey `toml:"-"` } type hook struct { @@ -37,9 +44,11 @@ type desire struct { Account string Altnames []string Key string + KeySize int Cert string Webroot string Hooks []string + key *rsa.PrivateKey `toml:"-"` } func LoadConfig(fname string) (*Config, error) { @@ -47,3 +56,13 @@ func LoadConfig(fname string) (*Config, error) { _, err := toml.DecodeFile(fname, c) return c, err } + +type Keychain interface { + Path() string + Size() int +} + +func (d desire) Path() string { return d.Key } +func (d desire) Size() int { return d.KeySize } +func (a account) Path() string { return a.Key } +func (a account) Size() int { return a.KeySize } diff --git a/cmd/acmed/main.go b/cmd/acmed/main.go index 06ab7d0..01691e5 100644 --- a/cmd/acmed/main.go +++ b/cmd/acmed/main.go @@ -1 +1,84 @@ package main + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "flag" + "io" + "io/ioutil" + "log" + "os" + "path" +) + +var confName = flag.String("conf", "acme.toml", "configuration file") + +func newKey(w io.Writer, size int) (*rsa.PrivateKey, error) { + key, err := rsa.GenerateKey(rand.Reader, size) + if err != nil { + return nil, err + } + block := &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(key), + } + return key, pem.Encode(w, block) +} + +func chkKey(baseDir string, k Keychain) (*rsa.PrivateKey, error) { + key := path.Join(baseDir, k.Path()) + flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC + if _, err := os.Stat(key); os.IsNotExist(err) { + log.Println("allocating", key, k.Size()) + if err := os.MkdirAll(path.Dir(key), 0700); err != nil { + return nil, err + } + fd, err := os.OpenFile(key, flags, 0600) + if err != nil { + return nil, err + } + defer fd.Close() + return newKey(fd, k.Size()) + } else { + der, err := ioutil.ReadFile(key) + if err != nil { + return nil, err + } + block, _ := pem.Decode(der) + return x509.ParsePKCS1PrivateKey(block.Bytes) + } +} + +func main() { + flag.Parse() + conf, err := LoadConfig(*confName) + if err != nil { + log.Fatal(err) + } + + for k, acc := range conf.Account { + if acc.KeySize == 0 { + acc.KeySize = conf.Defaults.KeySize + } + acc.key, err = chkKey(conf.Defaults.Basedir, acc) + if err != nil { + log.Fatal(err) + } + conf.Account[k] = acc + } + + for k, des := range conf.Desire { + if des.KeySize == 0 { + des.KeySize = conf.Defaults.KeySize + } + des.key, err = chkKey(conf.Defaults.Basedir, des) + if err != nil { + log.Fatal(err) + } + conf.Desire[k] = des + } + + log.Println(conf) +} -- cgit v1.2.3