diff --git a/flags.go b/flags.go index 9af8371..c825b57 100644 --- a/flags.go +++ b/flags.go @@ -5,6 +5,7 @@ package main import ( "crypto/elliptic" + "encoding/base64" "flag" "fmt" "io" @@ -48,13 +49,17 @@ type ( publicKeyPath string // path to the public key signRequestPath string // path to the certificate sign request certificateFlags *certFlagsContainer // container for certificate related flags + signature string // a base64 encoded signature } // a container for the refined flags flagSet struct { PrivateKey pki.PrivateKey + PublicKey pki.PublicKey Output io.WriteCloser Input io.ReadCloser + // an asn1 encoded signature of a signage process + Signature []byte // private key specific stuff PrivateKeyGenerationFlags privateKeyGenerationFlags @@ -140,6 +145,22 @@ func (f *Flags) parsePrivateKey() error { return nil } +// add the public key flag +func (f *Flags) AddPublicKey() { + f.check_list = append(f.check_list, f.parsePublicKey) + f.flagset.StringVar(&f.flag_container.publicKeyPath, "public-key", "", "path to the public key") +} + +// parse public key flag +func (f *Flags) parsePublicKey() error { + if f.flag_container.publicKeyPath == "" { return fmt.Errorf("No public key given!") } + + pu, err := ReadPublicKeyFile(f.flag_container.publicKeyPath) + if err != nil { return fmt.Errorf("Error reading public key: %s", err) } + f.Flags.PublicKey = pu + return nil +} + // add the output parameter to the checklist func (f *Flags) AddOutput() { f.check_list = append(f.check_list, f.parseOutput) @@ -214,3 +235,17 @@ func (f *Flags) parsePrivateKeyGenerationFlags() error { } return nil } + +// add the signature flag to load a signature from a signing process +func (f *Flags) AddSignature() { + f.check_list = append(f.check_list, f.parseSignature) + f.flagset.StringVar(&f.flag_container.signature, "signature", "", "the base64 encoded signature to use for verification") +} + +// parse the signature flag +func (f *Flags) parseSignature() error { + var err error + f.Flags.Signature, err = base64.StdEncoding.DecodeString(f.flag_container.signature) + if err != nil { return err } + return nil +} diff --git a/main.go b/main.go index 3898417..c509fd7 100644 --- a/main.go +++ b/main.go @@ -24,7 +24,7 @@ func main() { case "create-private": create_private_key() case "create-public": create_public_key() case "sign-input": sign_input() -// case "verify-signature": verify_signature() + case "verify-signature": verify_input() // case "create-cert-sign": create_sign_request() // case "sign-request": sign_request() case "help": print_modules() @@ -73,8 +73,8 @@ func create_public_key() { func sign_input() { fs := NewFlags("sign-input") fs.AddPrivateKey() - fs.AddOutput() fs.AddInput() + fs.AddOutput() err := fs.Parse(program_args()) if err != nil { os.Exit(2) } @@ -92,6 +92,29 @@ func sign_input() { } } +// verify a message using a signature and a public key +func verify_input() { + fs := NewFlags("sign-input") + fs.AddPublicKey() + fs.AddInput() + fs.AddOutput() + fs.AddSignature() + err := fs.Parse(program_args()) + if err != nil { os.Exit(2) } + + signature := fs.Flags.Signature + message, err := ioutil.ReadAll(fs.Flags.Input) + if err != nil { crash_with_help(2, "Error reading input: %s", err) } + valid, err := fs.Flags.PublicKey.Verify(message, signature, crypto.SHA256) + if err != nil { crash_with_help(2, "Could not verify message with signature: %s", err) } + if valid { + fmt.Println("valid") + os.Exit(0) + } + fmt.Println("invalid") + os.Exit(1) +} + // print the module help func print_modules() { fmt.Printf(`Usage: %s command args @@ -110,7 +133,7 @@ where 'command' is one of: // crash and provide a helpful message func crash_with_help(code int, message string, args ...interface{}) { - fmt.Fprintln(os.Stderr, message) + fmt.Fprintf(os.Stderr, message + "\n", args...) print_modules() os.Exit(code) } diff --git a/private_key.go b/private_key.go index 3e6aee3..0591e18 100644 --- a/private_key.go +++ b/private_key.go @@ -5,25 +5,22 @@ import ( "github.com/gibheer/pki" ) -const ( - TypeLabelRSA = "RSA PRIVATE KEY" - TypeLabelECDSA = "EC PRIVATE KEY" -) - var ( ErrNoPKFound = errors.New("no private key found") + ErrNoPUFound = errors.New("no public key found") + ErrUnknownFormat = errors.New("key is an unknown format") ) // Read the private key from the path and try to figure out which type of key it // might be. func ReadPrivateKeyFile(path string) (pki.PrivateKey, error) { - raw_pk, err := readSectionFromFile(path, TypeLabelECDSA) + raw_pk, err := readSectionFromFile(path, pki.PemLabelEcdsa) if err == nil { pk, err := pki.LoadPrivateKeyEcdsa(raw_pk) if err != nil { return nil, err } return pk, nil } - raw_pk, err = readSectionFromFile(path, TypeLabelRSA) + raw_pk, err = readSectionFromFile(path, pki.PemLabelRsa) if err == nil { pk, err := pki.LoadPrivateKeyRsa(raw_pk) if err != nil { return nil, err } @@ -31,3 +28,16 @@ func ReadPrivateKeyFile(path string) (pki.PrivateKey, error) { } return nil, ErrNoPKFound } + +// read the public key and try to figure out what kind of key it might be +func ReadPublicKeyFile(path string) (pki.PublicKey, error) { + raw_pu, err := readSectionFromFile(path, pki.PemLabelPublic) + if err != nil { return nil, ErrNoPUFound } + + var public pki.PublicKey + public, err = pki.LoadPublicKeyEcdsa(raw_pu) + if err == nil { return public, nil } + public, err = pki.LoadPublicKeyRsa(raw_pu) + if err == nil { return public, nil } + return nil, ErrUnknownFormat +}