diff options
author | Gibheer <gibheer@gmail.com> | 2015-02-15 01:34:25 +0100 |
---|---|---|
committer | Gibheer <gibheer@gmail.com> | 2015-02-15 01:34:25 +0100 |
commit | 16eb14db9f9b228ef88bcf1beb09cf823256dac1 (patch) | |
tree | 414ed9ba9f3e5679a7b0ae7b120e752d3f8ee2f6 /private_key.go | |
parent | 2f9126dc6a2eab32316ec90e21688d31159f9e80 (diff) |
redesign cli
This is a major rebuilding of the CLI. The library part is split out
into pkilib and the cli handles only the communication with the user,
I/O and the library.
The API will still look the same, but the code should be much better to
grasp. Instead of repeating everything, more will be grouped together
and reused.
Diffstat (limited to 'private_key.go')
-rw-r--r-- | private_key.go | 160 |
1 files changed, 24 insertions, 136 deletions
diff --git a/private_key.go b/private_key.go index 785b305..07ec3f8 100644 --- a/private_key.go +++ b/private_key.go @@ -1,145 +1,33 @@ package main -// generate an ecdsa or rsa private key - import ( - "crypto" - "crypto/elliptic" - "crypto/ecdsa" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "flag" - "fmt" - "io" - "io/ioutil" - "os" + "errors" + "github.com/gibheer/pkilib" ) -type ( - CreateFlags struct { - CryptType string // rsa or ecdsa - CryptLength int // the bit length - Output string // a path or stream to output the private key to - - output_stream io.WriteCloser // the actual stream to the output - } +const ( + TypeLabelRSA = "RSA PRIVATE KEY" + TypeLabelECDSA = "EC PRIVATE KEY" ) -// create a new private key -func create_private_key() { - flags := parse_create_flags() - - var err error - flags.output_stream, err = open_output_stream(flags.Output) - if err != nil { - crash_with_help(2, fmt.Sprintf("Error when creating file %s: %s", flags.Output, err)) - } - defer flags.output_stream.Close() - - switch flags.CryptType { - case "rsa": create_private_key_rsa(flags) - case "ecdsa": create_private_key_ecdsa(flags) - default: crash_with_help(2, fmt.Sprintf("%s not supported!", flags.CryptType)) - } -} - -// generate a rsa private key -func create_private_key_rsa(flags CreateFlags) { - if flags.CryptLength < 2048 { - crash_with_help(2, "Length is smaller than 2048!") - } - - priv, err := rsa.GenerateKey( rand.Reader, flags.CryptLength) - if err != nil { - fmt.Fprintln(os.Stderr, "Error: ", err) - os.Exit(3) - } - marshal := x509.MarshalPKCS1PrivateKey(priv) - block := &pem.Block{Type: TypeLabelRSA, Bytes: marshal} - pem.Encode(flags.output_stream, block) -} - -// generate a ecdsa private key -func create_private_key_ecdsa(flags CreateFlags) { - var curve elliptic.Curve - switch flags.CryptLength { - case 224: curve = elliptic.P224() - case 256: curve = elliptic.P256() - case 384: curve = elliptic.P384() - case 521: curve = elliptic.P521() - default: crash_with_help(2, "Unsupported crypt length!") - } - - priv, err := ecdsa.GenerateKey(curve, rand.Reader) - if err != nil { - fmt.Fprintln(os.Stderr, "Error: ", err) - os.Exit(3) - } - marshal, err := x509.MarshalECPrivateKey(priv) - if err != nil { - crash_with_help(2, fmt.Sprintf("Problems marshalling the private key: %s", err)) - } - block := &pem.Block{Type: TypeLabelECDSA, Bytes: marshal} - pem.Encode(flags.output_stream, block) -} - -// parse the flags to create a private key -func parse_create_flags() CreateFlags { - flags := CreateFlags{} - fs := flag.NewFlagSet("create-private", flag.ExitOnError) - fs.StringVar(&flags.CryptType, "type", "ecdsa", "which type to use to encrypt key (rsa, ecdsa)") - fs.IntVar(&flags.CryptLength, "length", 521, fmt.Sprintf( - "%i - %i for rsa; %v for ecdsa", RsaLowerLength, RsaUpperLength, EcdsaLength,)) - fs.StringVar(&flags.Output, "output", "STDOUT", "filename to store the private key") - fs.Parse(os.Args[2:]) - - return flags -} - -// load the private key stored at `path` -func load_private_key(path string) crypto.Signer { - if path == "" { - crash_with_help(2, "No path to private key supplied!") - } - - file, err := os.Open(path) - if err != nil { - crash_with_help(3, fmt.Sprintf("Error when opening private key: %s", err)) - } - defer file.Close() - - data, err := ioutil.ReadAll(file) - if err != nil { - crash_with_help(3, fmt.Sprintf("Error when reading private key: %s", err)) - } - - block, _ := pem.Decode(data) - if block.Type == TypeLabelRSA { - return load_private_key_rsa(block) - } else if block.Type == TypeLabelECDSA { - return load_private_key_ecdsa(block) - } else { - crash_with_help(2, "No valid private key file! Only RSA and ECDSA keys are allowed!") - return nil - } -} - -// parse rsa private key -func load_private_key_rsa(block *pem.Block) crypto.Signer { - key, err := x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - crash_with_help(3, fmt.Sprintf("Error parsing private key: %s", err)) - } - return key -} +var ( + ErrNoPKFound = errors.New("no private key found") +) -// parse ecdsa private key -func load_private_key_ecdsa(block *pem.Block) crypto.Signer { - key, err := x509.ParseECPrivateKey(block.Bytes) - if err != nil { - crash_with_help(3, fmt.Sprintf("Error parsing private key: %s", err)) - } - return key +// Read the private key from the path and try to figure out which type of key it +// might be. +func ReadPrivateKeyFile(path string) (pkilib.PrivateKey, error) { + raw_pk, err := readSectionFromFile(path, TypeLabelECDSA) + if err == nil { + pk, err := pkilib.LoadPrivateKeyEcdsa(raw_pk) + if err != nil { return nil, err } + return pk, nil + } + raw_pk, err = readSectionFromFile(path, TypeLabelRSA) + if err == nil { + pk, err := pkilib.LoadPrivateKeyRsa(raw_pk) + if err != nil { return nil, err } + return pk, nil + } + return nil, ErrNoPKFound } |