-
Notifications
You must be signed in to change notification settings - Fork 84
/
rsa_encryption.go
176 lines (153 loc) · 4.74 KB
/
rsa_encryption.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
174
175
176
// TODO: replace ExtractPublicKeyPemBase64 it with ExtractPublicKeyPem
// In fact, we never use base64 representation of public key except of case
// when we use it as a key for database.
// So PEM should be encrypted to base64 only and inside database layer
package rsaencryption
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"strings"
"github.com/pkg/errors"
"github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
)
var keySize = 2048
// GenerateKeys using rsa random generate keys and return []byte bas64
func GenerateKeys() ([]byte, []byte, error) {
// generate random private key (secret)
sk, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
return nil, nil, errors.Wrap(err, "Failed to generate rsa key")
}
// retrieve public key from the newly generated secret
pk := &sk.PublicKey
// convert to bytes
skPem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(sk),
},
)
pkBytes, err := x509.MarshalPKIXPublicKey(pk)
if err != nil {
return nil, nil, errors.Wrap(err, "Failed to marshal public key")
}
pkPem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pkBytes,
},
)
return pkPem, skPem, nil
}
// DecodeKey with secret key (rsa) and hash (base64), return the decrypted key
func DecodeKey(sk *rsa.PrivateKey, hash []byte) ([]byte, error) {
decryptedKey, err := rsa.DecryptPKCS1v15(rand.Reader, sk, hash)
if err != nil {
return nil, errors.Wrap(err, "could not decrypt key")
}
return decryptedKey, nil
}
// ConvertPemToPrivateKey return rsa private key from secret key
func ConvertPemToPrivateKey(skPem string) (*rsa.PrivateKey, error) {
block, _ := pem.Decode([]byte(skPem))
if block == nil {
return nil, errors.New("decode PEM block")
}
b := block.Bytes
return parsePrivateKey(b)
}
// HashRsaKey return sha256 hash of rsa private key
func HashRsaKey(keyBytes []byte) (string, error) {
hash := sha256.Sum256(keyBytes)
keyString := fmt.Sprintf("%x", hash)
return keyString, nil
}
// ConvertEncryptedPemToPrivateKey return rsa private key from secret key
func ConvertEncryptedPemToPrivateKey(pemData []byte, password string) (*rsa.PrivateKey, error) {
if strings.TrimSpace(password) == "" {
return nil, errors.New("Password required for encrypted PEM block")
}
// Unmarshal the JSON-encoded data
var data map[string]interface{}
if err := json.Unmarshal(pemData, &data); err != nil {
return nil, fmt.Errorf("parse JSON data: %w", err)
}
// Decrypt the private key using keystorev4
decryptedBytes, err := keystorev4.New().Decrypt(data, password)
if err != nil {
return nil, fmt.Errorf("decrypt private key: %w", err)
}
// Parse the decrypted PEM data
block, _ := pem.Decode(decryptedBytes)
if block == nil {
return nil, errors.New("parse PEM block")
}
// Parse the RSA private key
rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("parse RSA private key: %w", err)
}
return rsaKey, nil
}
func parsePrivateKey(derBytes []byte) (*rsa.PrivateKey, error) {
parsedSk, err := x509.ParsePKCS1PrivateKey(derBytes)
if err != nil {
return nil, errors.Wrap(err, "Failed to parse private key")
}
return parsedSk, nil
}
// ConvertPemToPublicKey return rsa public key from public key pem
func ConvertPemToPublicKey(pubPem []byte) (*rsa.PublicKey, error) {
block, _ := pem.Decode(pubPem)
if block == nil {
return nil, errors.New("failed to parse PEM block containing the public key")
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, errors.Wrap(err, "failed to parse DER encoded public key")
}
if pub, ok := pub.(*rsa.PublicKey); ok {
return pub, nil
} else {
return nil, errors.New("unknown type of public key")
}
}
// PrivateKeyToByte converts privateKey to []byte
func PrivateKeyToByte(sk *rsa.PrivateKey) []byte {
return pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(sk),
},
)
}
// ExtractPublicKey get public key from private key and return base64 encoded public key
func ExtractPublicKey(sk *rsa.PrivateKey) (string, error) {
pkBytes, err := x509.MarshalPKIXPublicKey(&sk.PublicKey)
if err != nil {
return "", errors.Wrap(err, "Failed to marshal private key")
}
pemByte := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pkBytes,
},
)
return base64.StdEncoding.EncodeToString(pemByte), nil
}
// ExtractPrivateKey gets private key and returns base64 encoded private key
func ExtractPrivateKey(sk *rsa.PrivateKey) string {
pemByte := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(sk),
},
)
return base64.StdEncoding.EncodeToString(pemByte)
}