Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/gitpod-db/go/encryption_test.go
2497 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package db_test
6
7
import (
8
"crypto/rand"
9
"encoding/base64"
10
"fmt"
11
db "github.com/gitpod-io/gitpod/components/gitpod-db/go"
12
"github.com/gitpod-io/gitpod/components/gitpod-db/go/dbtest"
13
"github.com/stretchr/testify/require"
14
"testing"
15
)
16
17
func TestAES256CBCCipher_Encrypt_Decrypt(t *testing.T) {
18
secret := "testtesttesttesttesttesttesttest"
19
20
metadata := db.CipherMetadata{
21
Name: "general",
22
Version: 1,
23
}
24
25
cipher, err := db.NewAES256CBCCipher(secret, metadata)
26
require.NoError(t, err)
27
28
data := []byte(`{ "foo": "bar", "another": "one" }`)
29
30
encrypted, err := cipher.Encrypt(data)
31
require.NoError(t, err)
32
33
iv, err := base64.StdEncoding.DecodeString(encrypted.Params.InitializationVector)
34
require.NoError(t, err, "initialization vector must be stored as base64")
35
require.NotEmpty(t, iv, "initialization vector must not be empty")
36
37
decodedCipherText, err := base64.StdEncoding.DecodeString(encrypted.EncodedData)
38
require.NoError(t, err, "encrypted data must be base64 encoded")
39
require.NotEmpty(t, decodedCipherText, "decoded cipher text must not be emtpy")
40
41
require.Equal(t, metadata, encrypted.Metadata)
42
require.NotEmpty(t, encrypted.Params.InitializationVector)
43
44
decrypted, err := cipher.Decrypt(encrypted)
45
require.NoError(t, err)
46
require.Equal(t, data, decrypted)
47
}
48
49
func TestAES256CBCCipher_EncryptedByServer(t *testing.T) {
50
cipher, metadata := dbtest.GetTestCipher(t)
51
encrypted := db.EncryptedData{
52
EncodedData: "YpgOY8ZNV64oG1DXiuCUXKy0thVySbN7uXTQxtC2j2A=",
53
Params: db.KeyParams{
54
InitializationVector: "vpTOAFN5v4kOPsAHBKk+eg==",
55
},
56
Metadata: metadata,
57
}
58
59
decrypted, err := cipher.Decrypt(encrypted)
60
fmt.Println(err)
61
require.NoError(t, err)
62
require.Equal(t, "12345678901234567890", string(decrypted))
63
}
64
65
func TestCipherSet(t *testing.T) {
66
t.Run("errors when no config specified", func(t *testing.T) {
67
_, err := db.NewCipherSet(nil)
68
require.Error(t, err)
69
})
70
71
t.Run("errors when no primary configs", func(t *testing.T) {
72
_, err := db.NewCipherSet([]db.CipherConfig{
73
{
74
Name: "first",
75
Version: 0,
76
Primary: false,
77
Material: "something",
78
},
79
{
80
Name: "second",
81
Version: 0,
82
Primary: false,
83
Material: "something else",
84
},
85
})
86
require.Error(t, err)
87
})
88
89
t.Run("errors when multiple primary configs", func(t *testing.T) {
90
_, err := db.NewCipherSet([]db.CipherConfig{
91
{
92
Name: "first",
93
Version: 0,
94
Primary: true,
95
Material: "something",
96
},
97
{
98
Name: "second",
99
Version: 0,
100
Primary: true,
101
Material: "something else",
102
},
103
})
104
require.Error(t, err)
105
})
106
107
t.Run("uses primary to encrypt", func(t *testing.T) {
108
cipherset, err := db.NewCipherSet([]db.CipherConfig{
109
{
110
Name: "first",
111
Version: 1,
112
Primary: true,
113
Material: base64.StdEncoding.EncodeToString(generateSecret(t, 32)),
114
},
115
{
116
Name: "second",
117
Version: 0,
118
Primary: false,
119
Material: base64.StdEncoding.EncodeToString(generateSecret(t, 32)),
120
},
121
})
122
require.NoError(t, err)
123
124
data := []byte(`random`)
125
encrypted, err := cipherset.Encrypt(data)
126
require.NoError(t, err)
127
require.Equal(t, "first", encrypted.Metadata.Name)
128
require.Equal(t, 1, encrypted.Metadata.Version)
129
})
130
131
t.Run("uses all to decrypt", func(t *testing.T) {
132
data := []byte(`random`)
133
134
// Construct a cipher, and encrypt some data. This serves as an "old" encrypted piece
135
secret := generateSecret(t, 32)
136
metadata := db.CipherMetadata{
137
Name: "second",
138
Version: 0,
139
}
140
oldCipher, err := db.NewAES256CBCCipher(string(secret), metadata)
141
require.NoError(t, err)
142
143
encrypted, err := oldCipher.Encrypt(data)
144
require.NoError(t, err)
145
146
cipherset, err := db.NewCipherSet([]db.CipherConfig{
147
{
148
Name: "first",
149
Version: 0,
150
Primary: true,
151
Material: base64.StdEncoding.EncodeToString(generateSecret(t, 32)),
152
},
153
{
154
Name: metadata.Name,
155
Version: metadata.Version,
156
Primary: false,
157
Material: base64.StdEncoding.EncodeToString(secret),
158
},
159
})
160
require.NoError(t, err)
161
162
decrypted, err := cipherset.Decrypt(encrypted)
163
require.NoError(t, err)
164
require.Equal(t, string(data), string(decrypted))
165
})
166
167
t.Run("no matching metadata returns an error when decrypting", func(t *testing.T) {
168
encrypted := db.EncryptedData{
169
EncodedData: "foobar",
170
Params: db.KeyParams{},
171
Metadata: db.CipherMetadata{
172
Name: "non-existent",
173
Version: 0,
174
},
175
}
176
177
cipherset := dbtest.CipherSet(t)
178
_, err := cipherset.Decrypt(encrypted)
179
require.Error(t, err)
180
})
181
182
}
183
184
func generateSecret(t *testing.T, size int) []byte {
185
t.Helper()
186
187
b := make([]byte, size)
188
_, err := rand.Read(b)
189
require.NoError(t, err)
190
191
return b
192
}
193
194