diff options
-rw-r--r-- | main.go | 18 | ||||
-rw-r--r-- | sign_input.go | 73 | ||||
-rw-r--r-- | verify_signature.go | 88 |
3 files changed, 172 insertions, 7 deletions
@@ -28,10 +28,11 @@ func main() { case "create-private": create_private_key() case "create-cert-sign": create_sign_request() case "create-public": create_public_key() - case "help": print_modules() - case "info": info_on_file() - case "sign-request": sign_request() - case "sign-input": sign_input() + case "help": print_modules() + case "info": info_on_file() + case "sign-request": sign_request() + case "sign-input": sign_input() + case "verify-signature": verify_signature() default: crash_with_help(1, "Command not supported!") } } @@ -43,9 +44,10 @@ func sign_request() {} // open stream for given path func open_output_stream(path string) (io.WriteCloser, error) { - if path == "STDOUT" { - return os.Stdout, nil - } else { + switch path { + case "STDOUT": return os.Stdout, nil + case "STDERR": return os.Stderr, nil + default: var err error output_stream, err := os.OpenFile(path, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0600) if err != nil { @@ -65,6 +67,8 @@ where 'command' is one of: help show this help info get info on a file sign sign a certificate request + sign-input sign a message with a private key + verify-signature verify a signature `, filepath.Base(os.Args[0])) fmt.Println() } diff --git a/sign_input.go b/sign_input.go new file mode 100644 index 0000000..4cd9035 --- /dev/null +++ b/sign_input.go @@ -0,0 +1,73 @@ +package main + +import ( + "crypto" + "crypto/rand" + "crypto/sha256" + "errors" + "flag" + "fmt" + "io" + "os" +// "crypto/ecdsa" +// "crypto/rsa" +) + +type ( + SignInputFlags struct { + Message string // the message to sign + PrivateKeyPath string // path to the private key + Output string // a path or stream to output the private key to + + private_key crypto.Signer + output_stream io.Writer // the output stream for the CSR + } +) + +func sign_input() { + flags := parse_sign_input_flags() + flags.private_key = load_private_key(flags.PrivateKeyPath) + + 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)) + } + flags.output_stream = output_stream + defer output_stream.Close() + + if err := create_signature(flags); err != nil { + fmt.Fprintln(os.Stderr, "Error when creating signature", err) + os.Exit(3) + } +} + +func parse_sign_input_flags() SignInputFlags { + flags := SignInputFlags{} + fs := flag.NewFlagSet("sign-input", flag.ExitOnError) + fs.StringVar(&flags.PrivateKeyPath, "private-key", "", "path to the private key file") + fs.StringVar(&flags.Output, "output", "STDOUT", "path where the generated signature should be stored") + fs.StringVar(&flags.Message, "message", "", "the message to sign") + fs.Parse(os.Args[2:]) + + return flags +} + +func create_signature(flags SignInputFlags) error { + message := []byte(flags.Message) + // compute sha256 of the message + hash := sha256.New() + length, _ := hash.Write(message) + if length != len(message) { return errors.New("Error when creating hash over message!") } + fmt.Println(hash.Sum(nil)) + + // create signature of the hash using the private key + signature, err := flags.private_key.Sign( + rand.Reader, + hash.Sum([]byte("")), + nil, + ) + if err != nil { return err } + fmt.Println(signature) + flags.output_stream.Write(signature) + return nil +} diff --git a/verify_signature.go b/verify_signature.go new file mode 100644 index 0000000..76020bb --- /dev/null +++ b/verify_signature.go @@ -0,0 +1,88 @@ +package main + +import ( + "crypto/ecdsa" + "crypto/sha256" + "crypto/x509" + "encoding/asn1" + "encoding/pem" + "errors" + "flag" + "fmt" + "io/ioutil" + "math/big" + "os" +) + +type ( + VerifySignatureFlags struct { + Message string // the message to sign + PublicKeyPath string // path to the private key + Signature string // a path or stream to output the private key to + } + // struct to load the signature into (which is basically two bigint in byte form) + Signature struct { + R, S *big.Int + } +) + +func verify_signature() { + flags := parse_verify_signature_flags() + public_key, err := load_public_key_ecdsa(flags.PublicKeyPath) + if err != nil { + crash_with_help(2, fmt.Sprintf("Error when loading public key: %s", err)) + } + signature, err := load_signature(flags.Signature) + if err != nil { + crash_with_help(2, fmt.Sprintf("Error when loading the signature: %s", err)) + } + hash := sha256.New() + hash.Write([]byte(flags.Message)) + + success := ecdsa.Verify(public_key, hash.Sum(nil), signature.R, signature.S) + fmt.Println(success) +} + +// parse the parameters +func parse_verify_signature_flags() VerifySignatureFlags { + flags := VerifySignatureFlags{} + fs := flag.NewFlagSet("verify-signature", flag.ExitOnError) + fs.StringVar(&flags.PublicKeyPath, "public-key", "", "path to the public key file") + fs.StringVar(&flags.Signature, "signature", "", "path where the signature file can be found") + fs.StringVar(&flags.Message, "message", "", "the message to be validated") + fs.Parse(os.Args[2:]) + + return flags +} + +// load the private key from pem file +func load_public_key_ecdsa(path string) (*ecdsa.PublicKey, error) { + public_key_file, err := os.Open(path) + if err != nil { return nil, err } + public_key_pem, err := ioutil.ReadAll(public_key_file) + if err != nil { return nil, err } + public_key_file.Close() + + block, _ := pem.Decode(public_key_pem) + if block.Type != TypeLabelPubKey { + return nil, errors.New(fmt.Sprintf("No public key found in %s", path)) + } + + public_key, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { return nil, err } + return public_key.(*ecdsa.PublicKey), nil +} + +// parse the signature from asn1 file +func load_signature(path string) (*Signature, error) { + signature_file, err := os.Open(path) + if err != nil { return nil, err } + signature_raw, err := ioutil.ReadAll(signature_file) + if err != nil { return nil, err } + signature_file.Close() + + var signature Signature + _, err = asn1.Unmarshal(signature_raw, &signature) + if err != nil { return nil, err } + return &signature, nil +} |