aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go163
1 files changed, 163 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..1b1c0d9
--- /dev/null
+++ b/main.go
@@ -0,0 +1,163 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "crypto/elliptic"
+ "crypto/ecdsa"
+ "crypto/x509"
+// "crypto/x509/pkix"
+ "crypto/rand"
+ "encoding/pem"
+// "code.google.com/p/go.crypto/ssh/terminal"
+// "math/big"
+// "time"
+)
+
+const (
+ RsaLowerLength = 2048
+ RsaUpperLength = 4096
+)
+
+var (
+ EcdsaLength = []int{224, 256, 384, 521}
+)
+
+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
+ }
+)
+
+func main() {
+ if len(os.Args) == 1 {
+ crash_with_help(1, "No module selected!")
+ }
+ switch os.Args[1] {
+ case "create-private": create_private_key()
+ case "create-cert-sign": create_sign_request()
+ case "help": print_modules()
+ case "info": info_on_file()
+ case "sign": sign_request()
+ }
+}
+
+// create a new private key
+func create_private_key() {
+ flags := parse_create_flags()
+
+ if flags.Output == "STDOUT" {
+ flags.output_stream = os.Stdout
+ } else {
+ var err error
+ flags.output_stream, err = os.OpenFile(flags.Output, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0600)
+ 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) {
+
+}
+
+// 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.Println("Error: ", err)
+ os.Exit(3)
+ }
+ result, err := x509.MarshalECPrivateKey(priv)
+ if err != nil {
+ crash_with_help(2, fmt.Sprintf("Problems marshalling the private key: %s", err))
+ }
+ block := &pem.Block{Type: "ECDSA PRIVATE KEY", Bytes: result}
+ 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
+}
+
+// create a sign request with a private key
+func create_sign_request() {}
+// get information on file (private key, sign request, certificate, ...)
+func info_on_file() {}
+// sign a certificate request to create a new certificate
+func sign_request() {}
+
+// print the module help
+func print_modules() {
+ fmt.Printf(`Usage: %s command args
+where 'command' is one of:
+ create-private create a new private key
+ create-cert-sign create a new certificate sign request
+ help show this help
+ info get info on a file
+ sign sign a certificate request
+`, filepath.Base(os.Args[0]))
+ fmt.Println()
+}
+
+func crash_with_help(code int, message string) {
+ fmt.Fprintln(os.Stderr, message)
+ print_modules()
+ os.Exit(code)
+}
+
+// fmt.Println("Lets create a cert!")
+// template := &x509.Certificate{
+// SerialNumber: big.NewInt(1),
+// Subject: pkix.Name{
+// Organization: []string{"Acme Co"},
+// },
+// NotBefore: time.Now(),
+// NotAfter: time.Now().Add(365 * 24 * time.Hour),
+// KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+// ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+// BasicConstraintsValid: true,
+// }
+// priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+// fmt.Println(priv.PublicKey, err)
+// raw_string, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)
+// cert, err := x509.ParseCertificate(raw_string)
+// fmt.Println(cert, err)
+//
+// // read a password or so
+// password, err := terminal.ReadPassword(0)
+// fmt.Println(string(password), err)
+//}