forked from wal-g/wal-g
/
key.go
162 lines (131 loc) · 3.85 KB
/
key.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
package awskms
import (
"crypto/rand"
"sync"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/kms"
)
// SymmetricKey is AWS KMS implementation of crypto.SymmetricKey interface
type SymmetricKey struct {
SymmetricKey []byte
SymmetricKeyLen int
EncryptedSymmetricKey []byte
EncryptedSymmetricKeyLen int
KeyID string
Region string
mutex sync.RWMutex
}
// Generate symmetric key
func (symmetricKey *SymmetricKey) Generate() error {
symmetricKey.mutex.RLock()
key := make([]byte, symmetricKey.SymmetricKeyLen)
symmetricKey.mutex.RUnlock()
_, err := rand.Read(key)
if err == nil {
symmetricKey.mutex.Lock()
symmetricKey.SymmetricKey = key
symmetricKey.mutex.Unlock()
}
return err
}
// Encrypt symmetric key with AWS KMS
func (symmetricKey *SymmetricKey) Encrypt() error {
kmsConfig := aws.NewConfig()
if symmetricKey.Region != "" {
kmsConfig = kmsConfig.WithRegion(symmetricKey.Region)
}
kmsSession, err := session.NewSession()
if err != nil {
return err
}
svc := kms.New(kmsSession, kmsConfig)
symmetricKey.mutex.RLock()
input := &kms.EncryptInput{
KeyId: aws.String(symmetricKey.KeyID),
Plaintext: symmetricKey.SymmetricKey,
}
symmetricKey.mutex.RUnlock()
result, err := svc.Encrypt(input)
if err == nil {
symmetricKey.mutex.Lock()
symmetricKey.EncryptedSymmetricKey = result.CiphertextBlob
symmetricKey.mutex.Unlock()
}
return err
}
// Decrypt symmetric key with AWS KMS
func (symmetricKey *SymmetricKey) Decrypt() error {
kmsConfig := aws.NewConfig()
if symmetricKey.Region != "" {
kmsConfig = kmsConfig.WithRegion(symmetricKey.Region)
}
kmsSession, err := session.NewSession()
if err != nil {
return err
}
svc := kms.New(kmsSession, kmsConfig)
symmetricKey.mutex.RLock()
input := &kms.DecryptInput{
CiphertextBlob: symmetricKey.EncryptedSymmetricKey,
}
symmetricKey.mutex.RUnlock()
result, err := svc.Decrypt(input)
if err == nil {
symmetricKey.mutex.Lock()
symmetricKey.SymmetricKey = result.Plaintext
symmetricKey.mutex.Unlock()
}
return err
}
// GetKey returna unencrypted symmetric key
func (symmetricKey *SymmetricKey) GetKey() []byte {
symmetricKey.mutex.RLock()
defer symmetricKey.mutex.RUnlock()
return symmetricKey.SymmetricKey
}
// GetEncryptedKey returns encrypted symmetric key
func (symmetricKey *SymmetricKey) GetEncryptedKey() []byte {
symmetricKey.mutex.RLock()
defer symmetricKey.mutex.RUnlock()
return symmetricKey.EncryptedSymmetricKey
}
// SetKey set unencrypted symmetric key
func (symmetricKey *SymmetricKey) SetKey(key []byte) error {
symmetricKey.mutex.Lock()
symmetricKey.SymmetricKey = key
symmetricKey.mutex.Unlock()
return nil
}
// SetEncryptedKey set encrypted symmetric key
func (symmetricKey *SymmetricKey) SetEncryptedKey(encryptedKey []byte) error {
symmetricKey.mutex.Lock()
symmetricKey.EncryptedSymmetricKey = encryptedKey
symmetricKey.mutex.Unlock()
return nil
}
// GetKeyID returns AWS KMS key ID
func (symmetricKey *SymmetricKey) GetKeyID() string {
symmetricKey.mutex.RLock()
defer symmetricKey.mutex.RUnlock()
return symmetricKey.KeyID
}
// GetEncryptedKeyLen returns encrypted key length
func (symmetricKey *SymmetricKey) GetEncryptedKeyLen() int {
symmetricKey.mutex.RLock()
defer symmetricKey.mutex.RUnlock()
return symmetricKey.EncryptedSymmetricKeyLen
}
// GetKeyLen returns key length
func (symmetricKey *SymmetricKey) GetKeyLen() int {
symmetricKey.mutex.RLock()
defer symmetricKey.mutex.RUnlock()
return symmetricKey.SymmetricKeyLen
}
// NewSymmetricKey creates new symmetric AWS KMS key object
func NewSymmetricKey(kmsKeyID string, keyLen int, encryptedKeyLen int, kmsRegion string) *SymmetricKey {
return &SymmetricKey{SymmetricKeyLen: keyLen,
EncryptedSymmetricKeyLen: encryptedKeyLen,
KeyID: kmsKeyID,
Region: kmsRegion}
}