0
0
Fork 0

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.
This commit is contained in:
Gibheer 2015-01-16 11:23:14 +01:00
parent 43384bab59
commit 68167a5891
3 changed files with 172 additions and 7 deletions

18
main.go
View File

@ -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()
}

73
sign_input.go Normal file
View File

@ -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
}

88
verify_signature.go Normal file
View File

@ -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
}