/
rsa.go
153 lines (138 loc) · 3.96 KB
/
rsa.go
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
package main
import (
"crypto"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/pem"
"flag"
"hash"
"io/ioutil"
"log"
)
const (
KeyFile = "rsa.key"
SignatureFile = "rsa.sig"
EncryptedFile = "rsa.enc"
)
var (
keySize = flag.Int("keysize", 2048, "The size of the key in bits")
do = flag.String("do", "encrypt", "The operation to perform, decrypt or encrypt (default)")
message = flag.String("message", "The revolution has begun!", "The message to encrypt")
hashAlgorithm = flag.String("algorithm", "sha256", "The hash algorithm to use. Must be one of md5, sha1, sha256 (default), sha512")
)
func MakeKey() *rsa.PrivateKey {
key, err := rsa.GenerateKey(rand.Reader, *keySize)
if err != nil {
log.Fatalf("failed to create RSA key: %s", err)
}
return key
}
func SaveKey(filename string, key *rsa.PrivateKey) {
block := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
err := ioutil.WriteFile(filename, pem.EncodeToMemory(block), 0644)
if err != nil {
log.Fatalf("failed saving key to %s: %s", filename, err)
}
}
func ReadKey(filename string) (*rsa.PrivateKey, error) {
bytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
block, _ := pem.Decode(bytes)
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return key, nil
}
func Key() *rsa.PrivateKey {
key, err := ReadKey(KeyFile)
if err != nil {
log.Printf("failed to read key, creating a new one: %s", err)
key = MakeKey()
SaveKey(KeyFile, key)
}
return key
}
func HashAlgorithm() (hash.Hash, crypto.Hash) {
switch *hashAlgorithm {
case "md5":
return md5.New(), crypto.MD5
case "sha1":
return sha1.New(), crypto.SHA1
case "sha256":
return sha256.New(), crypto.SHA256
case "sha512":
return sha512.New(), crypto.SHA512
default:
log.Fatalf("%s is not a valid hash algorithm. Must be one of md5, sha1, sha256, sha512")
}
panic("not reachable")
}
func HashMessage(data []byte) []byte {
h, _ := HashAlgorithm()
h.Write(data)
return h.Sum(nil)
}
func Encrypt() {
h, ha := HashAlgorithm()
key := Key()
encrypted, err := rsa.EncryptOAEP(h, rand.Reader, &key.PublicKey, []byte(*message), nil)
if err != nil {
log.Fatalf("encryption failed: %s", err)
}
signature, err := rsa.SignPKCS1v15(rand.Reader, key, ha, HashMessage(encrypted))
if err != nil {
log.Fatalf("signing failed; %s", err)
}
err = ioutil.WriteFile(EncryptedFile, encrypted, 0644)
if err != nil {
log.Fatalf("failed saving encrypted data: %s", err)
}
err = ioutil.WriteFile(SignatureFile, signature, 0644)
if err != nil {
log.Fatalf("failed saving signature data: %s", err)
}
}
func Decrypt() {
key := Key()
h, ha := HashAlgorithm()
encrypted, err := ioutil.ReadFile(EncryptedFile)
if err != nil {
log.Fatalf("failed reading encrypted data: %s", err)
}
signature, err := ioutil.ReadFile(SignatureFile)
if err != nil {
log.Fatalf("failed saving signature data: %s", err)
}
if err = rsa.VerifyPKCS1v15(&key.PublicKey, ha, HashMessage(encrypted), signature); err != nil {
log.Fatalf("message not valid: %s", err)
} else {
log.Printf("message is valid!")
}
plaintext, err := rsa.DecryptOAEP(h, rand.Reader, key, encrypted, nil)
if err != nil {
log.Fatalf("failed decrypting: %s", err)
}
log.Printf("decrypted message: %s", plaintext)
}
func main() {
flag.Parse()
switch *do {
case "encrypt":
Encrypt()
case "decrypt":
Decrypt()
default:
log.Fatalf("%s is not a valid operation. Must be one of encrypt or decrypt")
}
}