-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
helper.go
173 lines (140 loc) · 4.48 KB
/
helper.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package rsa
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
aes "github.com/eminmuhammadi/davinci/aes"
)
const __ENCRYPTED_PRIVATE_KEY__ = "ENCRYPTED PRIVATE KEY"
const __ENCRYPTED_PUBLIC_KEY__ = "ENCRYPTED PUBLIC KEY"
const __PRIVATE_KEY__ = "RSA PRIVATE KEY"
const __PUBLIC_KEY__ = "RSA PUBLIC KEY"
// Generates a new RSA key pair.
func generateRsaKeys(bits int) (*rsa.PrivateKey, *rsa.PublicKey) {
privKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
panic(fmt.Sprintf("failed to generate private key: %s", err))
}
return privKey, &privKey.PublicKey
}
// Rsa encrypts plaintext with RSA public key.
func encryptUsingPublicKey(pub *rsa.PublicKey, plaintext []byte) []byte {
hash := sha256.New()
ciphertext, err := rsa.EncryptOAEP(hash, rand.Reader, pub, plaintext, nil)
if err != nil {
panic(fmt.Sprintf("failed to encrypt plaintext: %s", err))
}
return ciphertext
}
// Rsa decrypts ciphertext with RSA private key.
func decryptUsingPrivateKey(priv *rsa.PrivateKey, ciphertext []byte) []byte {
hash := sha256.New()
plaintext, err := rsa.DecryptOAEP(hash, rand.Reader, priv, ciphertext, nil)
if err != nil {
panic(fmt.Sprintf("failed to decrypt ciphertext: %s", err))
}
return plaintext
}
// PemToPrivateKey converts pem string to a private key.
func PemToPrivateKey(privKey []byte, passphrase string) *rsa.PrivateKey {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(privKey); block == nil {
panic("failed to decode PEM block containing the key")
}
// Decrypt the private key if a passphrase is provided
if block.Type == __ENCRYPTED_PRIVATE_KEY__ {
if passphrase == "" {
panic("passphrase is required to decrypt the public key")
}
block.Bytes = []byte(aes.DecryptGCM256(string(block.Bytes), passphrase))
}
// Parse the private key
var parsedKey interface{}
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
panic(fmt.Sprintf("failed to parse private key: %s", err))
}
var privKeyParsed *rsa.PrivateKey
var ok bool
if privKeyParsed, ok = parsedKey.(*rsa.PrivateKey); !ok {
panic("failed to parse private key")
}
return privKeyParsed
}
// PemToPublicKey converts pem string to a public key.
func PemToPublicKey(pubKey []byte, passphrase string) *rsa.PublicKey {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(pubKey); block == nil {
panic("failed to parse PEM block containing the key")
}
// Decrypt the private key if a passphrase is provided
if block.Type == __ENCRYPTED_PUBLIC_KEY__ {
if passphrase == "" {
panic("passphrase is required to decrypt the public key")
}
block.Bytes = []byte(aes.DecryptGCM256(string(block.Bytes), passphrase))
}
// Parse the public key
var parsedKey interface{}
if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
panic(fmt.Sprintf("failed to parse public key: %s", err))
}
var publicKeyParsed *rsa.PublicKey
var ok bool
if publicKeyParsed, ok = parsedKey.(*rsa.PublicKey); !ok {
panic("key is not an RSA public key")
}
return publicKeyParsed
}
// PrivateKeyToBytes converts a private key to bytes.
func PrivateKeyToBytes(privKey *rsa.PrivateKey, passphrase string) []byte {
privASN1, err := x509.MarshalPKCS8PrivateKey(privKey)
if err != nil {
panic(fmt.Sprint("marshal private key:", err))
}
block := &pem.Block{
Type: __PRIVATE_KEY__,
Bytes: privASN1,
}
// Encrypt the private key if a passphrase is provided
if passphrase != "" {
block = &pem.Block{
Type: __ENCRYPTED_PRIVATE_KEY__,
Headers: map[string]string{
"Proc-Type": "4,ENCRYPTED",
"DEK-Info": fmt.Sprintf("AES-256-GCM,%x", sha256.Sum256([]byte(passphrase))),
},
Bytes: []byte(aes.EncryptGCM256(string(privASN1), passphrase)),
}
}
return pem.EncodeToMemory(block)
}
// PublicKeyToBytes converts a public key to bytes.
func PublicKeyToBytes(pub *rsa.PublicKey, passphrase string) []byte {
pubASN1, err := x509.MarshalPKIXPublicKey(pub)
if err != nil {
panic(fmt.Sprint("marshal public key:", err))
}
block := &pem.Block{
Type: __PUBLIC_KEY__,
Bytes: pubASN1,
}
// Encrypt the private key if a passphrase is provided
if passphrase != "" {
block = &pem.Block{
Type: __ENCRYPTED_PUBLIC_KEY__,
Headers: map[string]string{
"Proc-Type": "4,ENCRYPTED",
"DEK-Info": fmt.Sprintf("AES-256-GCM,%x", sha256.Sum256([]byte(passphrase))),
},
Bytes: []byte(aes.EncryptGCM256(string(pubASN1), passphrase)),
}
}
return pem.EncodeToMemory(block)
}