aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGibheer <gibheer@gmail.com>2015-03-30 21:52:39 +0200
committerGibheer <gibheer@gmail.com>2015-03-30 21:52:39 +0200
commit37423989c812e9a7972b6f272128e5f1e64c2827 (patch)
tree5f5120db8e7e9c3b2045c20478fe65298d20abda
parent9ba6a88449e6297ea925e0c59e923c56e742983f (diff)
split certificate stuff into own file
This moves the complicated certificate flag handling into its own file to make it a bit easier to handle.
-rw-r--r--certificate.go239
-rw-r--r--flags.go201
-rw-r--r--main.go25
3 files changed, 240 insertions, 225 deletions
diff --git a/certificate.go b/certificate.go
new file mode 100644
index 0000000..58f42b1
--- /dev/null
+++ b/certificate.go
@@ -0,0 +1,239 @@
+package main
+
+// This file contains all code to create certificates.
+
+import (
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "io/ioutil"
+ "math/big"
+ "strings"
+ "time"
+
+ "github.com/gibheer/pki"
+)
+
+var (
+ // the possible valid key usages to check against the commandline
+ ValidKeyUsages = map[string]x509.KeyUsage{
+ "digitalsignature": x509.KeyUsageDigitalSignature,
+ "contentcommitment": x509.KeyUsageContentCommitment,
+ "keyencipherment": x509.KeyUsageKeyEncipherment,
+ "dataencipherment": x509.KeyUsageDataEncipherment,
+ "keyagreement": x509.KeyUsageKeyAgreement,
+ "certsign": x509.KeyUsageCertSign,
+ "crlsign": x509.KeyUsageCRLSign,
+ "encipheronly": x509.KeyUsageEncipherOnly,
+ "decipheronly": x509.KeyUsageDecipherOnly,
+ }
+ // the valid extended key usages, to check against the commandline
+ ValidExtKeyUsages = map[string]x509.ExtKeyUsage{
+ "any": x509.ExtKeyUsageAny,
+ "serverauth": x509.ExtKeyUsageServerAuth,
+ "clientauth": x509.ExtKeyUsageClientAuth,
+ "codesigning": x509.ExtKeyUsageCodeSigning,
+ "emailprotection": x509.ExtKeyUsageEmailProtection,
+ "ipsecendsystem": x509.ExtKeyUsageIPSECEndSystem,
+ "ipsectunnel": x509.ExtKeyUsageIPSECTunnel,
+ "ipsecuser": x509.ExtKeyUsageIPSECUser,
+ "timestamping": x509.ExtKeyUsageTimeStamping,
+ "ocspsigning": x509.ExtKeyUsageOCSPSigning,
+ "microsoftservergatedcrypto": x509.ExtKeyUsageMicrosoftServerGatedCrypto,
+ "netscapeservergatedcrypto": x509.ExtKeyUsageNetscapeServerGatedCrypto,
+ }
+
+ CmdCreateCert = &Command{
+ Use: "create-cert",
+ Short: "create a certificate from a sign request",
+ Long: "Create a certificate based on a certificate sign request.",
+ Example: "create-cert -private-key=foo.ecdsa -csr-path=foo.csr",
+ Run: create_cert,
+ }
+ // certificate specific creation stuff
+ FlagCertificateGeneration pki.CertificateOptions
+)
+
+type (
+ // holds all certificate related flags, which need parsing afterwards
+ certiticateRequestRawFlags struct {
+ manual struct {
+ serialNumber string // the serial number for the cert
+ commonName string // the common name used in the cert
+ dnsNames string // all alternative names in the certificate (comma separated list)
+ ipAddresses string // all IP addresses in the certificate (comma separated list)
+ emailAddresses string // alternative email addresses
+ }
+ automatic struct {
+ Country string // the country names which should end up in the cert (comma separated list)
+ Organization string // the organization names (comma separated list)
+ OrganizationalUnit string // the organizational units (comma separated list)
+ Locality string // the city or locality (comma separated list)
+ Province string // the province name (comma separated list)
+ StreetAddress string // the street addresses of the organization (comma separated list)
+ PostalCode string // the postal codes of the locality
+ }
+ }
+
+ // the raw flags collected through flags
+ certGenerationRaw struct {
+ serial int64
+ notBefore string
+ notAfter string
+ isCA bool
+ length int
+ caPath string // path to the ca file if isCA is false
+ keyUsage string // comma separated list of key usages
+ extKeyUsage string // comma separated list of extended key usages
+ }
+)
+
+// add flag to load certificate flags
+func InitFlagCert(cmd *Command) {
+ cmd.Flags().Int64Var(&flagContainer.certGeneration.serial, "serial", 0, "serial number of all certificates")
+ cmd.Flags().BoolVar(&flagContainer.certGeneration.isCA, "ca", false, "check if the resulting certificate is a ca")
+ cmd.Flags().IntVar(
+ &flagContainer.certGeneration.
+ length,
+ "length",
+ 0,
+ "the number of certificates allowed in the chain between this cert and the end certificate",
+ )
+ cmd.Flags().StringVar(
+ &flagContainer.certGeneration.notBefore,
+ "not-before",
+ time.Now().Format(time.RFC3339),
+ "time before the certificate is not valid in RFC3339 format (default now)",
+ )
+ cmd.Flags().StringVar(
+ &flagContainer.certGeneration.notAfter,
+ "not-after",
+ time.Now().Add(time.Duration(180*24*time.Hour)).Format(time.RFC3339),
+ "time after which the certificate is not valid in RFC3339 format (default now + 180 days)",
+ )
+ cmd.Flags().StringVar(
+ &flagContainer.certGeneration.keyUsage,
+ "key-usage", "",
+ "comma separated list of key usages",
+ )
+ cmd.Flags().StringVar(
+ &flagContainer.certGeneration.extKeyUsage,
+ "ext-key-usage", "",
+ "comma separated list of extended key usage flags",
+ )
+}
+
+// create a certificate
+func create_cert(cmd *Command, args []string) {
+ err := checkFlags(checkPrivateKey, checkOutput, checkCSR, checkCertFlags)
+ if err != nil {
+ crash_with_help(cmd, ErrorFlagInput, "Flags invalid: %s", err)
+ }
+
+ // TODO implement flags for all certificate options
+ cert, err := FlagCertificateSignRequest.ToCertificate(
+ FlagPrivateKey,
+ FlagCertificateGeneration,
+ nil,
+ )
+ if err != nil {
+ crash_with_help(cmd, ErrorProgram, "Error generating certificate: %s", err)
+ }
+ pem_block, err := cert.MarshalPem()
+ if err != nil {
+ crash_with_help(cmd, ErrorProgram, "Error when marshalling to pem: %s", err)
+ }
+ _, err = pem_block.WriteTo(FlagOutput)
+ if err != nil {
+ crash_with_help(cmd, ErrorProgram, "Could not write to output: %s", err)
+ }
+}
+
+// parse the certificate data
+func checkCertFlags() error {
+ FlagCertificateGeneration.IsCA = flagContainer.certGeneration.isCA
+ FlagCertificateGeneration.CALength = flagContainer.certGeneration.length
+ FlagCertificateGeneration.SerialNumber = big.NewInt(flagContainer.certGeneration.serial)
+
+ var err error
+ if notbefore := flagContainer.certGeneration.notBefore; notbefore != "" {
+ FlagCertificateGeneration.NotBefore, err = parseTimeRFC3339(notbefore)
+ if err != nil {
+ return err
+ }
+ }
+ if notafter := flagContainer.certGeneration.notAfter; notafter != "" {
+ FlagCertificateGeneration.NotAfter, err = parseTimeRFC3339(notafter)
+ if err != nil {
+ return err
+ }
+ }
+ // parse the key usage string
+ if keyUstr := flagContainer.certGeneration.keyUsage; keyUstr != "" {
+ keyUarr := strings.Split(keyUstr, ",")
+ var keyUresult x509.KeyUsage
+ for _, usage := range keyUarr {
+ if value, ok := ValidKeyUsages[strings.ToLower(usage)]; ok {
+ keyUresult = keyUresult | value
+ } else {
+ return fmt.Errorf("unsupported key usage '%s'", usage)
+ }
+ }
+ FlagCertificateGeneration.KeyUsage = keyUresult
+ }
+ // parse the extended key usage flags
+ if eKeyUstr := flagContainer.certGeneration.extKeyUsage; eKeyUstr != "" {
+ eKeyUarr := strings.Split(eKeyUstr, ",")
+ eKeyUResult := make([]x509.ExtKeyUsage, 0)
+ for _, usage := range eKeyUarr {
+ if value, ok := ValidExtKeyUsages[strings.ToLower(usage)]; ok {
+ eKeyUResult = append(eKeyUResult, value)
+ } else {
+ return fmt.Errorf("unsupported extended key usage '%s'", usage)
+ }
+ }
+ FlagCertificateGeneration.KeyExtendedUsage = eKeyUResult
+ }
+ return nil
+}
+
+// add flag to load certificate sign request
+func InitFlagCSR(cmd *Command) {
+ cmd.Flags().StringVar(&flagContainer.signRequestPath, "csr-path", "", "path to the certificate sign request")
+}
+
+// parse the certificate sign request
+func checkCSR() error {
+ rest, err := ioutil.ReadFile(flagContainer.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",
+ flagContainer.signRequestPath,
+ )
+ }
+
+ csr, err := pki.LoadCertificateSignRequest(csr_asn1)
+ if err != nil {
+ return fmt.Errorf("Invalid certificate sign request: %s", err)
+ }
+ FlagCertificateSignRequest = csr
+ return nil
+}
+
+// parse the string as a RFC3339 time
+func parseTimeRFC3339(tr string) (time.Time, error) {
+ return time.Parse(time.RFC3339, tr)
+}
diff --git a/flags.go b/flags.go
index b93c156..cb69398 100644
--- a/flags.go
+++ b/flags.go
@@ -4,74 +4,18 @@ package main
// often used by multiple functions.
import (
- "crypto/elliptic"
- "crypto/x509"
"encoding/base64"
- "encoding/pem"
"fmt"
"io"
- "io/ioutil"
- "math/big"
"net"
"os"
"reflect"
"strings"
- "time"
"github.com/gibheer/pki"
)
-var (
- // the possible valid key usages to check against the commandline
- ValidKeyUsages = map[string]x509.KeyUsage{
- "digitalsignature": x509.KeyUsageDigitalSignature,
- "contentcommitment": x509.KeyUsageContentCommitment,
- "keyencipherment": x509.KeyUsageKeyEncipherment,
- "dataencipherment": x509.KeyUsageDataEncipherment,
- "keyagreement": x509.KeyUsageKeyAgreement,
- "certsign": x509.KeyUsageCertSign,
- "crlsign": x509.KeyUsageCRLSign,
- "encipheronly": x509.KeyUsageEncipherOnly,
- "decipheronly": x509.KeyUsageDecipherOnly,
- }
- // the valid extended key usages, to check against the commandline
- ValidExtKeyUsages = map[string]x509.ExtKeyUsage{
- "any": x509.ExtKeyUsageAny,
- "serverauth": x509.ExtKeyUsageServerAuth,
- "clientauth": x509.ExtKeyUsageClientAuth,
- "codesigning": x509.ExtKeyUsageCodeSigning,
- "emailprotection": x509.ExtKeyUsageEmailProtection,
- "ipsecendsystem": x509.ExtKeyUsageIPSECEndSystem,
- "ipsectunnel": x509.ExtKeyUsageIPSECTunnel,
- "ipsecuser": x509.ExtKeyUsageIPSECUser,
- "timestamping": x509.ExtKeyUsageTimeStamping,
- "ocspsigning": x509.ExtKeyUsageOCSPSigning,
- "microsoftservergatedcrypto": x509.ExtKeyUsageMicrosoftServerGatedCrypto,
- "netscapeservergatedcrypto": x509.ExtKeyUsageNetscapeServerGatedCrypto,
- }
-)
-
type (
- // holds all certificate related flags, which need parsing afterwards
- certiticateRequestRawFlags struct {
- manual struct {
- serialNumber string // the serial number for the cert
- commonName string // the common name used in the cert
- dnsNames string // all alternative names in the certificate (comma separated list)
- ipAddresses string // all IP addresses in the certificate (comma separated list)
- emailAddresses string // alternative email addresses
- }
- automatic struct {
- Country string // the country names which should end up in the cert (comma separated list)
- Organization string // the organization names (comma separated list)
- OrganizationalUnit string // the organizational units (comma separated list)
- Locality string // the city or locality (comma separated list)
- Province string // the province name (comma separated list)
- StreetAddress string // the street addresses of the organization (comma separated list)
- PostalCode string // the postal codes of the locality
- }
- }
-
// a container go gather all incoming flags for further processing
paramContainer struct {
outputPath string // path to output whatever is generated
@@ -87,17 +31,6 @@ type (
certificatePath string // path to a certificate
}
- certGenerationRaw struct {
- serial int64
- notBefore string
- notAfter string
- isCA bool
- length int
- caPath string // path to the ca file if isCA is false
- keyUsage string // comma separated list of key usages
- extKeyUsage string // comma separated list of extended key usages
- }
-
flagCheck func() error
)
@@ -140,14 +73,6 @@ certificate requests and certificates and sign/verify messages.`,
Run: create_sign_request,
}
- CmdCreateCert = &Command{
- Use: "create-cert",
- Short: "create a certificate from a sign request",
- Long: "Create a certificate based on a certificate sign request.",
- Example: "create-cert -private-key=foo.ecdsa -csr-path=foo.csr",
- Run: create_cert,
- }
-
// variable to hold the raw arguments before checking
flagContainer *paramContainer
@@ -165,8 +90,6 @@ certificate requests and certificates and sign/verify messages.`,
FlagCertificateRequestData *pki.CertificateData
// the certificate sign request
FlagCertificateSignRequest *pki.CertificateRequest
- // certificate specific creation stuff
- FlagCertificateGeneration pki.CertificateOptions
)
func InitFlags() {
@@ -234,129 +157,7 @@ func checkPublicKey() error {
return nil
}
-// add flag to load certificate flags
-func InitFlagCert(cmd *Command) {
- cmd.Flags().Int64Var(&flagContainer.certGeneration.serial, "serial", 0, "serial number of all certificates")
- cmd.Flags().BoolVar(&flagContainer.certGeneration.isCA, "ca", false, "check if the resulting certificate is a ca")
- cmd.Flags().IntVar(
- &flagContainer.certGeneration.
- length,
- "length",
- 0,
- "the number of certificates allowed in the chain between this cert and the end certificate",
- )
- cmd.Flags().StringVar(
- &flagContainer.certGeneration.notBefore,
- "not-before",
- time.Now().Format(time.RFC3339),
- "time before the certificate is not valid in RFC3339 format (default now)",
- )
- cmd.Flags().StringVar(
- &flagContainer.certGeneration.notAfter,
- "not-after",
- time.Now().Add(time.Duration(180*24*time.Hour)).Format(time.RFC3339),
- "time after which the certificate is not valid in RFC3339 format (default now + 180 days)",
- )
- cmd.Flags().StringVar(
- &flagContainer.certGeneration.keyUsage,
- "key-usage", "",
- "comma separated list of key usages",
- )
- cmd.Flags().StringVar(
- &flagContainer.certGeneration.extKeyUsage,
- "ext-key-usage", "",
- "comma separated list of extended key usage flags",
- )
-}
-
-// parse the certificate data
-func checkCertFlags() error {
- FlagCertificateGeneration.IsCA = flagContainer.certGeneration.isCA
- FlagCertificateGeneration.CALength = flagContainer.certGeneration.length
- FlagCertificateGeneration.SerialNumber = big.NewInt(flagContainer.certGeneration.serial)
-
- var err error
- if notbefore := flagContainer.certGeneration.notBefore; notbefore != "" {
- FlagCertificateGeneration.NotBefore, err = parseTimeRFC3339(notbefore)
- if err != nil {
- return err
- }
- }
- if notafter := flagContainer.certGeneration.notAfter; notafter != "" {
- FlagCertificateGeneration.NotAfter, err = parseTimeRFC3339(notafter)
- if err != nil {
- return err
- }
- }
- // parse the key usage string
- if keyUstr := flagContainer.certGeneration.keyUsage; keyUstr != "" {
- keyUarr := strings.Split(keyUstr, ",")
- var keyUresult x509.KeyUsage
- for _, usage := range keyUarr {
- if value, ok := ValidKeyUsages[strings.ToLower(usage)]; ok {
- keyUresult = keyUresult | value
- } else {
- return fmt.Errorf("unsupported key usage '%s'", usage)
- }
- }
- FlagCertificateGeneration.KeyUsage = keyUresult
- }
- // parse the extended key usage flags
- if eKeyUstr := flagContainer.certGeneration.extKeyUsage; eKeyUstr != "" {
- eKeyUarr := strings.Split(eKeyUstr, ",")
- eKeyUResult := make([]x509.ExtKeyUsage, 0)
- for _, usage := range eKeyUarr {
- if value, ok := ValidExtKeyUsages[strings.ToLower(usage)]; ok {
- eKeyUResult = append(eKeyUResult, value)
- } else {
- return fmt.Errorf("unsupported extended key usage '%s'", usage)
- }
- }
- FlagCertificateGeneration.KeyExtendedUsage = eKeyUResult
- }
- return nil
-}
-
-func parseTimeRFC3339(tr string) (time.Time, error) {
- return time.Parse(time.RFC3339, tr)
-}
-
-// add flag to load certificate sign request
-func InitFlagCSR(cmd *Command) {
- cmd.Flags().StringVar(&flagContainer.signRequestPath, "csr-path", "", "path to the certificate sign request")
-}
-
-// parse the certificate sign request
-func checkCSR() error {
- rest, err := ioutil.ReadFile(flagContainer.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",
- flagContainer.signRequestPath,
- )
- }
-
- csr, err := pki.LoadCertificateSignRequest(csr_asn1)
- if err != nil {
- return fmt.Errorf("Invalid certificate sign request: %s", err)
- }
- FlagCertificateSignRequest = csr
- return nil
-}
-
+// initialize the output flag
func InitFlagOutput(cmd *Command) {
cmd.Flags().StringVar(&flagContainer.outputPath, "output", "STDOUT", "path to the output or STDOUT")
}
diff --git a/main.go b/main.go
index a4eec3f..9b9ab0a 100644
--- a/main.go
+++ b/main.go
@@ -117,31 +117,6 @@ func create_sign_request(cmd *Command, args []string) {
}
}
-func create_cert(cmd *Command, args []string) {
- err := checkFlags(checkPrivateKey, checkOutput, checkCSR, checkCertFlags)
- if err != nil {
- crash_with_help(cmd, ErrorFlagInput, "Flags invalid: %s", err)
- }
-
- // TODO implement flags for all certificate options
- cert, err := FlagCertificateSignRequest.ToCertificate(
- FlagPrivateKey,
- FlagCertificateGeneration,
- nil,
- )
- if err != nil {
- crash_with_help(cmd, ErrorProgram, "Error generating certificate: %s", err)
- }
- pem_block, err := cert.MarshalPem()
- if err != nil {
- crash_with_help(cmd, ErrorProgram, "Error when marshalling to pem: %s", err)
- }
- _, err = pem_block.WriteTo(FlagOutput)
- if err != nil {
- crash_with_help(cmd, ErrorProgram, "Could not write to output: %s", err)
- }
-}
-
// crash and provide a helpful message
func crash_with_help(cmd *Command, code int, message string, args ...interface{}) {
fmt.Fprintf(os.Stderr, message+"\n", args...)