-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
176 lines (156 loc) · 4.86 KB
/
main.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
package main
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/davecgh/go-spew/spew"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/vault/shamir"
log "github.com/sirupsen/logrus"
"google.golang.org/protobuf/proto"
)
const (
version = "0.3"
)
func readStoredKeys(barrierKeys []byte, masterkey []byte) ([]byte, error) {
blobInfo := &wrapping.EncryptedBlobInfo{}
if err := proto.Unmarshal(barrierKeys, blobInfo); err != nil {
return nil, fmt.Errorf("failed to proto decode stored keys: %s", err)
}
aeadWrapper, err := getWrapper(masterkey)
if err != nil {
return nil, fmt.Errorf("getWrapper: %s", err)
}
pt, err := aeadWrapper.Decrypt(context.Background(), blobInfo, nil)
if err != nil {
return nil, fmt.Errorf("failed to encrypt keys for storage: %s", err)
}
// Decode the barrier entry
var keys [][]byte
if err := json.Unmarshal(pt, &keys); err != nil {
return nil, fmt.Errorf("failed to decode stored keys: %v", err)
}
log.Debugf("key:%s", spew.Sdump(keys[0]))
return keys[0], nil
}
func getBinValue(target string) (ciphertext []byte, err error) {
ciphertext, err = ioutil.ReadFile(target)
if err != nil {
return nil, fmt.Errorf("ReadFile: %s", err)
}
ciphertextBin, err := base64.StdEncoding.DecodeString(fmt.Sprintf("%s", ciphertext))
if err != nil {
return nil, fmt.Errorf("base64 decoding: %s", err)
}
log.Debugf("ciphertextBin: %s", spew.Sdump(ciphertextBin))
return ciphertextBin, nil
}
func main_() int {
log.SetOutput(os.Stdout)
log.SetFormatter(&log.TextFormatter{})
log.Infof("Vault-decrypt starting version %s", version)
barrierUnsealKeysPath := flag.String("barrier-unseal-keys", "tmp/data/core/hsm/barrier-unseal-keys", "Path to a file with the base64 encrypted value of the barrier unseal keys")
keyRingPath := flag.String("key-ring", "tmp/data/core/keyring", "Path to a file with the base64 encrypted value of the keyring")
encryptedKeyPath := flag.String("encrypted-file", "", "Path to the file to decrypt")
encryptedKeyVaultPath := flag.String("encrypted-vault-path", "", "Logical path inside Vault storage to the key")
unsealKeysPath := flag.String("unseal-keys", "", "Path to a file with the unseal keys, one per line")
debug := flag.Bool("debug", false, "Enable debug output (optional)")
flag.Parse()
if len(os.Args) < 10 {
flag.PrintDefaults()
os.Exit(1)
}
log.SetLevel(log.InfoLevel)
if *debug {
log.SetLevel(log.DebugLevel)
}
//Read unseal keys from file
unsealKeysText, err := ioutil.ReadFile(*unsealKeysPath)
if err != nil {
log.Fatalf("ReadFile: %s", err)
return 1
}
unsealKeys := strings.Split(string(unsealKeysText), "\n")
if unsealKeys[len(unsealKeys)-1] == "" {
unsealKeys = unsealKeys[:len(unsealKeys)-1]
}
log.Debugf("Unseal keys=%s", spew.Sdump(unsealKeys))
//Decode base64 shamir keys and combine them
var unsealKeysBins [][]byte
for _, v := range unsealKeys {
tmpBin, err := base64.StdEncoding.DecodeString(v)
if err != nil {
log.Fatalf("Error decoding base64 key:%s", err)
return 1
}
unsealKeysBins = append(unsealKeysBins, tmpBin)
}
var masterKey []byte
if len(unsealKeysBins) > 1 {
masterKey, err = shamir.Combine(unsealKeysBins)
if err != nil {
log.Fatalf("failed to generate key from shares: %s", err)
}
} else {
masterKey = unsealKeysBins[0]
}
log.Debugf("Master key: %s", base64.StdEncoding.EncodeToString(masterKey))
//Read barrier unseal key
barrierKeys, err := getBinValue(*barrierUnsealKeysPath)
if err != nil {
log.Fatalf("failed to read file: %s", err)
return 1
}
unsealKey, err := readStoredKeys(barrierKeys, masterKey)
if err != nil {
log.Fatalf("failed to decrypt unseal keys: %s", err)
return 1
}
log.Debugf("Unseal keys:%s", spew.Sdump(unsealKey))
//Read keyring and decrypt it
keyRingBin, err := getBinValue(*keyRingPath)
if err != nil {
log.Fatalf("failed to read file: %s", err)
return 1
}
keyRingJSON, err := decryptTarget(keyRingBin, unsealKey, "core/keyring")
if err != nil {
log.Fatalf("Error decrypting Keyring:%s", err)
return 1
}
log.Debugf("Keyring:%s", keyRingJSON)
keyring, err := DeserializeKeyring(keyRingJSON)
if err != nil {
log.Fatalf("failed to generate key from shares: %s", err)
}
log.Debugf("Keyring deserialized:%s", spew.Sdump(keyring))
//Decrypt with keyring
cipherBin, err := getBinValue(*encryptedKeyPath)
if err != nil {
log.Fatalf("failed to read file: %s", err)
return 1
}
clear, err := decryptWithKeyring(keyring, cipherBin, *encryptedKeyVaultPath)
if err != nil {
log.Fatalf("failed to read file: %s", err)
return 1
}
log.Infof("Decrypted data:%s", spew.Sdump(clear))
var prettyJSON bytes.Buffer
error := json.Indent(&prettyJSON, clear, "", "\t")
if error != nil {
log.Println("JSON parse error: ", error)
return 1
}
fmt.Printf("%s", prettyJSON.String())
return 0
}
func main() {
os.Exit(main_())
}