This repository has been archived by the owner on Jun 11, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
client.go
152 lines (125 loc) · 4.59 KB
/
client.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
package main
import (
"encoding/json"
"fmt"
"net/url"
)
// EncryptionStrategy is a generic encryption mechanism
type EncryptionStrategy interface {
Encrypt([]byte) (string, error)
}
// DecryptionStrategy is a generic decryption mechanism
type DecryptionStrategy interface {
Decrypt(envelope string) ([]byte, error)
}
// CompositeDecryptionStrategy multiplexes other decryption strategies {NACL, KMS}
type CompositeDecryptionStrategy struct {
Strategies map[string]DecryptionStrategy
}
// Decrypt decrypts an envelope
func (k *CompositeDecryptionStrategy) Decrypt(envelope string) ([]byte, error) {
// Get the type of encryption {NACL, KMS}
envelopeType := extractEnvelopeType(envelope)
strategy := k.Strategies[envelopeType]
if strategy != nil {
return strategy.Decrypt(envelope)
}
return nil, fmt.Errorf("Not configured for decrypting ENC[%s,..] values", envelopeType)
}
// Add a new decryption strategy
func (k *CompositeDecryptionStrategy) Add(envelopeType string, strategy DecryptionStrategy) {
k.Strategies[envelopeType] = strategy
}
func newCompositeDecryptionStrategy() *CompositeDecryptionStrategy {
return &CompositeDecryptionStrategy{Strategies: make(map[string]DecryptionStrategy)}
}
// KeyEncryptionStrategy decrypts using in-memory keys
type KeyEncryptionStrategy struct {
PublicKey, PrivateKey *[32]byte
}
// Encrypt encrypts a buffer and returns an envelope
func (k *KeyEncryptionStrategy) Encrypt(plaintext []byte) (string, error) {
return encryptEnvelope(k.PublicKey, k.PrivateKey, plaintext)
}
func newKeyEncryptionStrategy(publicKey *[32]byte, privateKey *[32]byte) *KeyEncryptionStrategy {
return &KeyEncryptionStrategy{PublicKey: publicKey, PrivateKey: privateKey}
}
// KeyDecryptionStrategy decrypts using in-memory keys
type KeyDecryptionStrategy struct {
PublicKey, PrivateKey *[32]byte
}
// Decrypt decrypts an envelope
func (k *KeyDecryptionStrategy) Decrypt(envelope string) ([]byte, error) {
return decryptEnvelope(k.PublicKey, k.PrivateKey, envelope)
}
func newKeyDecryptionStrategy(publicKey *[32]byte, privateKey *[32]byte) *KeyDecryptionStrategy {
return &KeyDecryptionStrategy{PublicKey: publicKey, PrivateKey: privateKey}
}
// DaemonDecryptionStrategy decrypts using the secretary daemon
type DaemonDecryptionStrategy struct {
DaemonURL, AppID, AppVersion, TaskID string
MasterKey, DeployKey, ServiceKey *[32]byte
}
func newDaemonDecryptionStrategy(
daemonURL string, appID string, appVersion string, taskID string,
masterKey *[32]byte, deployKey *[32]byte, serviceKey *[32]byte) *DaemonDecryptionStrategy {
return &DaemonDecryptionStrategy{
DaemonURL: daemonURL, AppID: appID, AppVersion: appVersion, TaskID: taskID,
MasterKey: masterKey, DeployKey: deployKey, ServiceKey: serviceKey}
}
// Decrypt decrypts an envelope
func (r *DaemonDecryptionStrategy) Decrypt(envelope string) ([]byte, error) {
message := DaemonRequest{
AppID: r.AppID, AppVersion: r.AppVersion, TaskID: r.TaskID,
RequestedSecret: envelope,
}
encoded, err := json.Marshal(message)
if err != nil {
return nil, err
}
// Encrypt with service key and send to daemon
if r.ServiceKey != nil {
encryptedEnvelope, err := encryptEnvelope(r.MasterKey, r.ServiceKey, encoded)
if err != nil {
return nil, err
}
encoded = []byte(encryptedEnvelope)
}
// Encrypt with deploy key and send to daemon
requestEnvelope, err := encryptEnvelope(r.MasterKey, r.DeployKey, encoded)
if err != nil {
return nil, err
}
// Envelope is already encrypted with service key
response, err := httpPostForm(fmt.Sprintf("%s/v1/decrypt", r.DaemonURL), url.Values{
"appid": {r.AppID},
"appversion": {r.AppVersion},
"taskid": {r.TaskID},
"envelope": {requestEnvelope}})
if err != nil {
return nil, fmt.Errorf("Failed to decrypt using daemon (%s)", err)
}
// Decrypt response using deploy key
response, err = decryptEnvelope(r.MasterKey, r.DeployKey, string(response))
if err != nil {
return nil, fmt.Errorf("Failed to decrypt daemon response using deploy key (%s)", err)
}
// Decrypt response using service key
if r.ServiceKey != nil {
response, err = decryptEnvelope(r.MasterKey, r.ServiceKey, string(response))
if err != nil {
return nil, fmt.Errorf("Failed to decrypt daemon response using service key (%s)", err)
}
}
// Unpack response struct
var parsedResponse DaemonResponse
err = json.Unmarshal(response, &parsedResponse)
if err != nil {
return nil, fmt.Errorf("Failed to parse JSON respons (%s)", err)
}
plaintext, err := decode(parsedResponse.PlaintextSecret)
if err != nil {
return nil, fmt.Errorf("Failed to base64 decode plaintext secret (%s)", err)
}
return plaintext, nil
}