aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGibheer <gibheer@gmail.com>2015-01-16 11:23:14 +0100
committerGibheer <gibheer@gmail.com>2015-01-16 11:23:14 +0100
commit68167a5891e3680331a44ab20fdb198e0447cf88 (patch)
treee1d07dd2b4dbcb935b2a00c5f3c10c752781434e
parent43384bab59112965e171d217f9b60e00c20659a0 (diff)
add signing and verifying of messages
With this it is possible to sign a message with a private key and verify it with a public key. The only problem is, that it is currently not compatible with openssl yet.
-rw-r--r--main.go18
-rw-r--r--sign_input.go73
-rw-r--r--verify_signature.go88
3 files changed, 172 insertions, 7 deletions
diff --git a/main.go b/main.go
index dac1ee4..73ea1b2 100644
--- a/main.go
+++ b/main.go
@@ -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
+}