package acme import ( "crypto" "crypto/ecdsa" "crypto/rsa" "crypto/x509" "encoding/pem" "errors" "io" "io/ioutil" "os" "path" ) const ( pemRSA = `RSA PRIVATE KEY` pemEC = `EC PRIVATE KEY` pemCRT = `CERTIFICATE` ) 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 } defer fd.Close() return LoadKey(fd) } func LoadKey(r io.Reader) (crypto.PrivateKey, error) { der, err := ioutil.ReadAll(r) if err != nil { return nil, err } block, _ := pem.Decode(der) switch block.Type { case pemRSA: return x509.ParsePKCS1PrivateKey(block.Bytes) case pemEC: return x509.ParseECPrivateKey(block.Bytes) default: return nil, errKeyType } } 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, crt *x509.Certificate) error { block := &pem.Block{ Type: pemCRT, Bytes: crt.Raw, } 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 { return nil, err } block, _ := pem.Decode(der) return x509.ParseCertificates(block.Bytes) } func readCert(r io.Reader) (*x509.Certificate, error) { der, err := ioutil.ReadAll(r) if err != nil { return nil, err } return x509.ParseCertificate(der) } func CreatePrivFile(fname string) (io.WriteCloser, error) { return createFile(fname, 0700) } func CreatePubFile(fname string) (io.WriteCloser, error) { return createFile(fname, 0755) } func createFile(fname string, mode os.FileMode) (io.WriteCloser, error) { if err := os.MkdirAll(path.Dir(fname), mode); err != nil { return nil, err } flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC return os.OpenFile(fname, flags, mode&0644) }