From 4a1bc8a259a83ff83c6f9d82a387d96569b2d346 Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Wed, 10 Nov 2021 22:27:57 -0800 Subject: Import crypto utils --- crypto/ecdsa/ecdsa.go | 11 +++++++++ crypto/x509/csr.go | 28 +++++++++++++++++++++++ encoding/pem/read.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ encoding/pem/write.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 crypto/ecdsa/ecdsa.go create mode 100644 crypto/x509/csr.go create mode 100644 encoding/pem/read.go create mode 100644 encoding/pem/write.go diff --git a/crypto/ecdsa/ecdsa.go b/crypto/ecdsa/ecdsa.go new file mode 100644 index 0000000..3793663 --- /dev/null +++ b/crypto/ecdsa/ecdsa.go @@ -0,0 +1,11 @@ +package ecdsa + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" +) + +func GenerateECPrivateKey() (*ecdsa.PrivateKey, error) { + return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) +} diff --git a/crypto/x509/csr.go b/crypto/x509/csr.go new file mode 100644 index 0000000..76ea809 --- /dev/null +++ b/crypto/x509/csr.go @@ -0,0 +1,28 @@ +package x509 + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" +) + +const defaultRSAKeyStrength = 4096 + +func GenerateRSAKeyCSR(domains ...string) ([]byte, *rsa.PrivateKey, error) { + ckey, err := rsa.GenerateKey(rand.Reader, defaultRSAKeyStrength) + if err != nil { + return nil, nil, err + } + + csr, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{ + Subject: pkix.Name{CommonName: domains[0]}, + DNSNames: domains, + ExtraExtensions: []pkix.Extension{}, + }, ckey) + if err != nil { + return nil, nil, err + } + + return csr, ckey, nil +} diff --git a/encoding/pem/read.go b/encoding/pem/read.go new file mode 100644 index 0000000..dbf2f73 --- /dev/null +++ b/encoding/pem/read.go @@ -0,0 +1,61 @@ +package pem + +import ( + "crypto/ecdsa" + "crypto/x509" + "encoding/pem" + "fmt" + "os" +) + +func LoadECPrivateKey(filename string) (*ecdsa.PrivateKey, error) { + pb, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + + block, _ := pem.Decode(pb) + if block == nil { + return nil, fmt.Errorf("failed to decode pem bytes") + } + + key, err := x509.ParseECPrivateKey(block.Bytes) + if err != nil { + return nil, err + } + + return key, nil +} + +func CertificateFromPemData(data []byte) (*x509.Certificate, error) { + block, _ := pem.Decode(data) + if block == nil { + return nil, fmt.Errorf("Unable to decode PEM") + } + + crt, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, err + } + + return crt, nil +} + +func CertificateRequestFromPemDataRaw(data []byte) (*x509.CertificateRequest, []byte, error) { + block, _ := pem.Decode(data) + if block == nil { + return nil, nil, fmt.Errorf("Unable to decode PEM") + } + + csr, err := x509.ParseCertificateRequest(block.Bytes) + if err != nil { + return nil, nil, err + } + + return csr, block.Bytes, nil +} + +func CertificateRequestFromPemData(data []byte) (*x509.CertificateRequest, error) { + csr, _, err := CertificateRequestFromPemDataRaw(data) + return csr, err +} diff --git a/encoding/pem/write.go b/encoding/pem/write.go new file mode 100644 index 0000000..c239f8e --- /dev/null +++ b/encoding/pem/write.go @@ -0,0 +1,62 @@ +package pem + +import ( + "bytes" + "crypto/ecdsa" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "io" + "os" +) + +func pemWrite(filename, header string, data [][]byte) error { + out, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) + if err != nil { + return err + } + defer out.Close() + + for _, d := range data { + err = pem.Encode(out, &pem.Block{ + Type: header, + Bytes: d, + }) + if err != nil { + return err + } + } + + return nil +} + +func WriteRSAPrivateKey(filename string, key *rsa.PrivateKey) error { + return pemWrite(filename, "RSA PRIVATE KEY", [][]byte{x509.MarshalPKCS1PrivateKey(key)}) +} + +func WriteCertificateChain(filename string, der [][]byte) error { + return pemWrite(filename, "CERTIFICATE", der) +} + +func WriteECPrivateKey(filename string, key *ecdsa.PrivateKey) error { + m, err := x509.MarshalECPrivateKey(key) + if err != nil { + return err + } + + return pemWrite(filename, "EC PRIVATE KEY", [][]byte{m}) +} + +func CSRToPEMReader(der []byte) (io.ReadCloser, error) { + out := &bytes.Buffer{} + + err := pem.Encode(out, &pem.Block{ + Type: "CERTIFICATE REQUEST", + Bytes: der, + }) + if err != nil { + return nil, err + } + + return io.NopCloser(out), nil +} -- cgit v1.2.3