1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
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
}
|