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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
package main
import (
"crypto"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"math/big"
"os"
"path/filepath"
"github.com/gibheer/pki"
)
var (
EmptyByteArray = make([]byte, 0)
)
func main() {
if len(os.Args) == 1 {
crash_with_help(1, "No module selected!")
}
switch os.Args[1] {
case "create-private": create_private_key()
case "create-public": create_public_key()
case "sign-input": sign_input()
case "verify-signature": verify_input()
case "create-cert-sign": create_sign_request()
case "create-cert": create_cert()
case "help": print_modules()
// case "info": info_on_file()
default: crash_with_help(1, "Command not supported!")
}
}
// create a private key
func create_private_key() {
fs := NewFlags("create-private")
fs.AddOutput()
fs.AddPrivateKeyGenerationFlags()
err := fs.Parse(program_args())
if err != nil { os.Exit(2) }
var pk pki.Pemmer
switch fs.Flags.PrivateKeyGenerationFlags.Type {
case "ecdsa": pk, err = pki.NewPrivateKeyEcdsa(fs.Flags.PrivateKeyGenerationFlags.Curve)
case "rsa": pk, err = pki.NewPrivateKeyRsa(fs.Flags.PrivateKeyGenerationFlags.Size)
}
if err != nil { os.Exit(2) }
marsh_pem, err := pk.MarshalPem()
if err != nil { os.Exit(2) }
_, err = marsh_pem.WriteTo(fs.Flags.Output)
if err != nil { os.Exit(2) }
}
// create a public key derived from a private key
func create_public_key() {
fs := NewFlags("create-public")
fs.AddPrivateKey()
fs.AddOutput()
err := fs.Parse(program_args())
if err != nil { os.Exit(2) }
var pub_key pki.Pemmer
pub_key = fs.Flags.PrivateKey.Public()
marsh_pem, err := pub_key.MarshalPem()
if err != nil { os.Exit(2) }
_, err = marsh_pem.WriteTo(fs.Flags.Output)
if err != nil { os.Exit(2) }
}
// sign a message using he private key
func sign_input() {
fs := NewFlags("sign-input")
fs.AddPrivateKey()
fs.AddInput()
fs.AddOutput()
err := fs.Parse(program_args())
if err != nil { os.Exit(2) }
message, err := ioutil.ReadAll(fs.Flags.Input)
if err != nil { crash_with_help(2, "Error reading input: %s", err) }
signature, err := fs.Flags.PrivateKey.Sign(message, crypto.SHA256)
if err != nil { crash_with_help(2, "Could not compute signature: %s", err) }
_, err = io.WriteString(fs.Flags.Output, base64.StdEncoding.EncodeToString(signature))
if err != nil { crash_with_help(2, "Could not write to output: %s", err) }
// if we print to stderr, send a final line break to make the output nice
if fs.Flags.Output == os.Stdout {
// we can ignore the result, as either Stdout did work or not
_, _ = io.WriteString(fs.Flags.Output, "\n")
}
}
// verify a message using a signature and a public key
func verify_input() {
fs := NewFlags("sign-input")
fs.AddPublicKey()
fs.AddInput()
fs.AddOutput()
fs.AddSignature()
err := fs.Parse(program_args())
if err != nil { os.Exit(2) }
signature := fs.Flags.Signature
message, err := ioutil.ReadAll(fs.Flags.Input)
if err != nil { crash_with_help(2, "Error reading input: %s", err) }
valid, err := fs.Flags.PublicKey.Verify(message, signature, crypto.SHA256)
if err != nil { crash_with_help(2, "Could not verify message with signature: %s", err) }
if valid {
fmt.Println("valid")
os.Exit(0)
}
fmt.Println("invalid")
os.Exit(1)
}
// create a certificate sign request
func create_sign_request() {
fs := NewFlags("create-cert-sign")
fs.AddPrivateKey()
fs.AddOutput()
fs.AddCertificateFields()
fs.Parse(program_args())
csr, err := fs.Flags.CertificateData.ToCertificateRequest(fs.Flags.PrivateKey)
if err != nil { crash_with_help(2, "Could not create certificate sign request: %s", err) }
pem_block, err := csr.MarshalPem()
if err != nil { crash_with_help(2, "Could not covnert to pem: %s", err) }
_, err = pem_block.WriteTo(fs.Flags.Output)
if err != nil { crash_with_help(2, "Encoding didn't work: %s", err) }
}
func create_cert() {
fs := NewFlags("create-cert")
fs.AddPrivateKey()
fs.AddCSR()
fs.AddOutput()
fs.Parse(program_args())
// TODO implement flags for all certificate options
cert_opts := pki.CertificateOptions{}
cert_opts.SerialNumber = big.NewInt(1)
cert, err := fs.Flags.CertificateSignRequest.ToCertificate(
fs.Flags.PrivateKey,
cert_opts,
nil,
)
if err != nil { crash_with_help(2, "Error generating certificate: %s", err) }
pem_block, err := cert.MarshalPem()
if err != nil { crash_with_help(2, "Error converting to pem: %s", err) }
_, err = pem_block.WriteTo(fs.Flags.Output)
if err != nil { crash_with_help(2, "Output didn't work: %s", err) }
}
// print the module help
func print_modules() {
fmt.Printf(`Usage: %s command args
where 'command' is one of:
create-private create a new private key
create-public create a public key from a private one
sign-input sign a message with a private key
verify-signature verify a signature
create-cert-sign create a new certificate sign request
create-cert sign a certificate request
help show this help
info get info on a file
`, filepath.Base(os.Args[0]))
fmt.Println()
}
// crash and provide a helpful message
func crash_with_help(code int, message string, args ...interface{}) {
fmt.Fprintf(os.Stderr, message + "\n", args...)
print_modules()
os.Exit(code)
}
// return the arguments to the program
func program_args() []string {
return os.Args[2:]
}
|