104 lines
3.0 KiB
Go
104 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
// "crypto/ecdsa"
|
|
// "crypto/rsa"
|
|
)
|
|
|
|
type (
|
|
SignInputFlags struct {
|
|
Message string // the message to sign
|
|
MessageStream string // the message stream to sign
|
|
PrivateKeyPath string // path to the private key
|
|
Output string // a path or stream to output the private key to
|
|
Format string // the format of the output
|
|
|
|
private_key crypto.Signer
|
|
output_stream io.Writer // the output stream for the CSR
|
|
input_stream io.Reader // the input stream to read the message from
|
|
}
|
|
)
|
|
|
|
func sign_input() {
|
|
flags := parse_sign_input_flags()
|
|
if flags.Message != "" && flags.MessageStream != "" {
|
|
crash_with_help(2, "Only message or message file can be signed!")
|
|
}
|
|
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 flags.MessageStream != "" {
|
|
input_stream, err := open_input_stream(flags.MessageStream)
|
|
if err != nil {
|
|
crash_with_help(2, fmt.Sprintf("Error when opening stream %s: %s", flags.MessageStream, err))
|
|
}
|
|
flags.input_stream = input_stream
|
|
defer input_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 (STDOUT, STDERR, file)")
|
|
fs.StringVar(&flags.Message, "message", "", "the message to sign")
|
|
fs.StringVar(&flags.MessageStream, "message-stream", "STDIN", "the path to the stream to sign (file, STDIN)")
|
|
fs.StringVar(&flags.Format, "format", "base64", "the output format (binary, base64)")
|
|
fs.Parse(os.Args[2:])
|
|
|
|
return flags
|
|
}
|
|
|
|
func create_signature(flags SignInputFlags) error {
|
|
var message []byte
|
|
var err error
|
|
|
|
if flags.MessageStream != "" {
|
|
message, err = ioutil.ReadAll(flags.input_stream)
|
|
if err != nil { return err }
|
|
} else {
|
|
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!") }
|
|
|
|
// 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 }
|
|
if flags.Format == "base64" {
|
|
flags.output_stream.Write([]byte(base64.StdEncoding.EncodeToString(signature)))
|
|
} else {
|
|
flags.output_stream.Write(signature)
|
|
}
|
|
flags.output_stream.Write([]byte("\n"))
|
|
return nil
|
|
}
|