-
Notifications
You must be signed in to change notification settings - Fork 151
/
cloudkms.go
130 lines (99 loc) · 3.45 KB
/
cloudkms.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
package encryption
import (
"context"
"encoding/base64"
"fmt"
"github.com/tink-crypto/tink-go-gcpkms/integration/gcpkms"
"github.com/tink-crypto/tink-go/aead"
"github.com/tink-crypto/tink-go/core/registry"
"github.com/tink-crypto/tink-go/keyset"
"google.golang.org/api/option"
)
type cloudkmsEncryptionService struct {
key *aead.KMSEnvelopeAEAD
privateEc256Handle *keyset.Handle
publicEc256Handle *keyset.Handle
}
// NewCloudKMSEncryption creates a GCP CloudKMS-backed encryption service.
func NewCloudKMSEncryption(keyUri string, credentialsJSON, privateEc256, publicEc256 []byte) (*cloudkmsEncryptionService, error) {
client, err := gcpkms.NewClientWithOptions(context.Background(), keyUri, option.WithCredentialsJSON(credentialsJSON))
if err != nil {
return nil, err
}
return newWithClient(client, keyUri, privateEc256, publicEc256)
}
func GenerateJWTKeysetsFromCloudKMS(keyUri string, credentialsJSON []byte) (privateEc256 []byte, publicEc256 []byte, err error) {
client, err := gcpkms.NewClientWithOptions(context.Background(), keyUri, option.WithCredentialsJSON(credentialsJSON))
if err != nil {
return nil, nil, err
}
return generateJWTKeysetsWithClient(keyUri, client)
}
func generateJWTKeysetsWithClient(keyUri string, client registry.KMSClient) (privateEc256 []byte, publicEc256 []byte, err error) {
registry.RegisterKMSClient(client)
remote, err := client.GetAEAD(keyUri)
if err != nil {
return nil, nil, err
}
return generateJWTKeysets(remote)
}
func newWithClient(client registry.KMSClient, keyUri string, privateEc256, publicEc256 []byte) (*cloudkmsEncryptionService, error) {
registry.RegisterKMSClient(client)
dek := aead.AES128CTRHMACSHA256KeyTemplate()
template, err := aead.CreateKMSEnvelopeAEADKeyTemplate(keyUri, dek)
if err != nil {
return nil, err
}
// get the remote KEK from the client
remote, err := client.GetAEAD(keyUri)
if err != nil {
return nil, err
}
envelope := aead.NewKMSEnvelopeAEAD2(template, remote)
if envelope == nil {
return nil, fmt.Errorf("failed to create envelope")
}
privateEc256Handle, err := handleFromBytes(privateEc256, remote)
if err != nil {
return nil, err
}
publicEc256Handle, err := handleFromBytes(publicEc256, remote)
if err != nil {
return nil, err
}
return &cloudkmsEncryptionService{
key: envelope,
privateEc256Handle: privateEc256Handle,
publicEc256Handle: publicEc256Handle,
}, nil
}
func (svc *cloudkmsEncryptionService) Encrypt(plaintext []byte, dataId string) ([]byte, error) {
return encrypt(svc.key, plaintext, dataId)
}
func (svc *cloudkmsEncryptionService) Decrypt(ciphertext []byte, dataId string) ([]byte, error) {
return decrypt(svc.key, ciphertext, dataId)
}
func (svc *cloudkmsEncryptionService) EncryptString(plaintext string, dataId string) (string, error) {
b, err := encrypt(svc.key, []byte(plaintext), dataId)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(b), nil
}
func (svc *cloudkmsEncryptionService) DecryptString(ciphertext string, dataId string) (string, error) {
decoded, err := base64.StdEncoding.DecodeString(ciphertext)
if err != nil {
return "", err
}
b, err := decrypt(svc.key, decoded, dataId)
if err != nil {
return "", err
}
return string(b), nil
}
func (svc *cloudkmsEncryptionService) GetPrivateJWTHandle() *keyset.Handle {
return svc.privateEc256Handle
}
func (svc *cloudkmsEncryptionService) GetPublicJWTHandle() *keyset.Handle {
return svc.publicEc256Handle
}