From 31bf8bc739b5066eaaf25294a202170ffede4bc2 Mon Sep 17 00:00:00 2001 From: Gibheer Date: Mon, 16 Mar 2015 17:15:29 +0100 Subject: [PATCH] certificate generation is in The hole certificate sign request and certificate creation process was pulled into pki, which made pkictl a bit smaller in code. There are still some things missing, but the initial support for certificates is done! --- certificate_data.go | 28 ------------------------ flags.go | 52 ++++++++++++++++++++++++++++++++++++++------- main.go | 38 +++++++++++++++++++++++++-------- 3 files changed, 73 insertions(+), 45 deletions(-) delete mode 100644 certificate_data.go diff --git a/certificate_data.go b/certificate_data.go deleted file mode 100644 index 76f3323..0000000 --- a/certificate_data.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "crypto/x509" - "crypto/x509/pkix" - "net" -) - -type ( - certificateData struct { - Subject pkix.Name - - DnsNames []string - EmailAddresses []string - IpAddresses []net.IP - } -) - -func (c *certificateData) GenerateCSR() *x509.CertificateRequest { - csr := &x509.CertificateRequest{} - - csr.Subject = c.Subject - csr.DNSNames = c.DnsNames - csr.IPAddresses = c.IpAddresses - csr.EmailAddresses = c.EmailAddresses - - return csr -} diff --git a/flags.go b/flags.go index 7aee688..d70120b 100644 --- a/flags.go +++ b/flags.go @@ -5,11 +5,12 @@ package main import ( "crypto/elliptic" - "crypto/x509/pkix" "encoding/base64" + "encoding/pem" "flag" "fmt" "io" + "io/ioutil" "net" "os" "reflect" @@ -76,7 +77,9 @@ type ( // private key specific stuff PrivateKeyGenerationFlags privateKeyGenerationFlags // a certificate filled with the parameters - CertificateData certificateData + CertificateData *pki.CertificateData + // the certificate sign request + CertificateSignRequest *pki.CertificateRequest } privateKeyGenerationFlags struct { @@ -175,6 +178,39 @@ func (f *Flags) parsePublicKey() error { return nil } +// add flag to load certificate sign request +func (f *Flags) AddCSR() { + f.check_list = append(f.check_list, f.parseCSR) + f.flagset.StringVar(&f.flag_container.signRequestPath, "csr-path", "", "path to the certificate sign request") +} + +// parse the certificate sign request +func (f *Flags) parseCSR() error { + rest, err := ioutil.ReadFile(f.flag_container.signRequestPath) + if err != nil { return fmt.Errorf("Error reading certificate sign request: %s", err) } + + var csr_asn1 []byte + var block *pem.Block + for len(rest) > 0 { + block, rest = pem.Decode(rest) + if block.Type == "CERTIFICATE REQUEST" { + csr_asn1 = block.Bytes + break + } + } + if len(csr_asn1) == 0 { + return fmt.Errorf( + "No certificate sign request found in %s", + f.flag_container.signRequestPath, + ) + } + + csr, err := pki.LoadCertificateSignRequest(csr_asn1) + if err != nil { return fmt.Errorf("Invalid certificate sign request: %s", err) } + f.Flags.CertificateSignRequest = csr + return nil +} + // add the output parameter to the checklist func (f *Flags) AddOutput() { f.check_list = append(f.check_list, f.parseOutput) @@ -307,7 +343,7 @@ func (f *Flags) AddCertificateFields() { // parse the certificate fields into a raw certificate func (f *Flags) parseCertificateFields() error { - f.Flags.CertificateData = certificateData{Subject: pkix.Name{}} + f.Flags.CertificateData = pki.NewCertificateData() // convert the automatic flags container_type := reflect.ValueOf(&f.flag_container.certificateFlags.automatic).Elem() cert_data_type := reflect.ValueOf(&f.Flags.CertificateData.Subject).Elem() @@ -321,12 +357,12 @@ func (f *Flags) parseCertificateFields() error { } // convert the manual flags - data := &f.Flags.CertificateData + data := f.Flags.CertificateData raw_data := f.flag_container.certificateFlags.manual data.Subject.SerialNumber = raw_data.serialNumber data.Subject.CommonName = raw_data.commonName if raw_data.dnsNames != "" { - data.DnsNames = strings.Split(raw_data.dnsNames, ",") + data.DNSNames = strings.Split(raw_data.dnsNames, ",") } if raw_data.emailAddresses != "" { data.EmailAddresses = strings.Split(raw_data.emailAddresses, ",") @@ -334,10 +370,10 @@ func (f *Flags) parseCertificateFields() error { if raw_data.ipAddresses == "" { return nil } raw_ips := strings.Split(raw_data.ipAddresses, ",") - data.IpAddresses = make([]net.IP, len(raw_ips)) + data.IPAddresses = make([]net.IP, len(raw_ips)) for i, ip := range raw_ips { - data.IpAddresses[i] = net.ParseIP(ip) - if data.IpAddresses[i] == nil { + data.IPAddresses[i] = net.ParseIP(ip) + if data.IPAddresses[i] == nil { return fmt.Errorf("'%s' is not a valid IP", ip) } } diff --git a/main.go b/main.go index b33ced9..7e3d0b6 100644 --- a/main.go +++ b/main.go @@ -2,13 +2,11 @@ package main import ( "crypto" - "crypto/rand" - "crypto/x509" "encoding/base64" - "encoding/pem" "fmt" "io" "io/ioutil" + "math/big" "os" "path/filepath" @@ -29,7 +27,7 @@ func main() { case "sign-input": sign_input() case "verify-signature": verify_input() case "create-cert-sign": create_sign_request() -// case "sign-request": sign_request() + case "create-cert": create_cert() case "help": print_modules() // case "info": info_on_file() default: crash_with_help(1, "Command not supported!") @@ -126,14 +124,36 @@ func create_sign_request() { fs.AddCertificateFields() fs.Parse(program_args()) - csrt := fs.Flags.CertificateData.GenerateCSR() - csr, err := x509.CreateCertificateRequest(rand.Reader, csrt, fs.Flags.PrivateKey.PrivateKey()) + csr, err := fs.Flags.CertificateData.ToCertificateRequest(fs.Flags.PrivateKey) if err != nil { crash_with_help(2, "Could not create certificate sign request: %s", err) } - pem_block := &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csr} - err = pem.Encode(fs.Flags.Output, pem_block) + pem_block, err := csr.MarshalPem() + if err != nil { crash_with_help(2, "Could not covnert to pem: %s", err) } + _, err = pem_block.WriteTo(fs.Flags.Output) if err != nil { crash_with_help(2, "Encoding didn't work: %s", err) } } +func create_cert() { + fs := NewFlags("create-cert") + fs.AddPrivateKey() + fs.AddCSR() + fs.AddOutput() + fs.Parse(program_args()) + + // TODO implement flags for all certificate options + cert_opts := pki.CertificateOptions{} + cert_opts.SerialNumber = big.NewInt(1) + cert, err := fs.Flags.CertificateSignRequest.ToCertificate( + fs.Flags.PrivateKey, + cert_opts, + nil, + ) + if err != nil { crash_with_help(2, "Error generating certificate: %s", err) } + pem_block, err := cert.MarshalPem() + if err != nil { crash_with_help(2, "Error converting to pem: %s", err) } + _, err = pem_block.WriteTo(fs.Flags.Output) + if err != nil { crash_with_help(2, "Output didn't work: %s", err) } +} + // print the module help func print_modules() { fmt.Printf(`Usage: %s command args @@ -143,7 +163,7 @@ where 'command' is one of: sign-input sign a message with a private key verify-signature verify a signature create-cert-sign create a new certificate sign request - sign-request sign a certificate request + create-cert sign a certificate request help show this help info get info on a file `, filepath.Base(os.Args[0]))