forked from drand/tlock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtlock_test.go
322 lines (248 loc) · 9.96 KB
/
tlock_test.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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
package tlock_test
import (
"bytes"
_ "embed" // Calls init function.
"encoding/json"
"os"
"strings"
"testing"
"time"
"github.com/drand/drand/chain"
"github.com/drand/drand/crypto"
bls "github.com/drand/kyber-bls12381"
"github.com/drand/tlock"
"github.com/drand/tlock/networks/http"
"github.com/stretchr/testify/require"
)
var (
//go:embed test_artifacts/data.txt
dataFile []byte
)
const (
testnetHost = "https://pl-us.testnet.drand.sh/"
testnetChainHash = "cc9c398442737cbd141526600919edd69f1d6f9b4adb67e4d912fbc64341a9a5"
mainnetHost = "https://api.drand.sh/"
mainnetChainHash = "52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971"
)
func TestEarlyDecryptionWithDuration(t *testing.T) {
for host, hash := range map[string]string{testnetHost: testnetChainHash, mainnetHost: mainnetChainHash} {
network, err := http.NewNetwork(host, hash)
require.NoError(t, err)
// =========================================================================
// Encrypt
// Read the plaintext data to be encrypted.
in, err := os.Open("test_artifacts/data.txt")
require.NoError(t, err)
defer in.Close()
// Write the encoded information to this buffer.
var cipherData bytes.Buffer
// Enough duration to check for a non-existent beacon.
duration := 10 * time.Second
roundNumber := network.RoundNumber(time.Now().Add(duration))
err = tlock.New(network).Encrypt(&cipherData, in, roundNumber)
require.NoError(t, err)
// =========================================================================
// Decrypt
// Write the decoded information to this buffer.
var plainData bytes.Buffer
// We DO NOT wait for the future beacon to exist.
err = tlock.New(network).Decrypt(&plainData, &cipherData)
require.ErrorIs(t, err, tlock.ErrTooEarly)
}
}
func TestEarlyDecryptionWithRound(t *testing.T) {
network, err := http.NewNetwork(testnetHost, testnetChainHash)
require.NoError(t, err)
// =========================================================================
// Encrypt
// Read the plaintext data to be encrypted.
in, err := os.Open("test_artifacts/data.txt")
require.NoError(t, err)
defer in.Close()
var cipherData bytes.Buffer
futureRound := network.RoundNumber(time.Now().Add(1 * time.Minute))
err = tlock.New(network).Encrypt(&cipherData, in, futureRound)
require.NoError(t, err)
// =========================================================================
// Decrypt
// Write the decoded information to this buffer.
var plainData bytes.Buffer
// We DO NOT wait for the future beacon to exist.
err = tlock.New(network).Decrypt(&plainData, &cipherData)
require.ErrorIs(t, err, tlock.ErrTooEarly)
}
func TestEncryptionWithDuration(t *testing.T) {
if testing.Short() {
t.Skip("skipping live testing in short mode")
}
network, err := http.NewNetwork(testnetHost, testnetChainHash)
require.NoError(t, err)
// =========================================================================
// Encrypt
// Read the plaintext data to be encrypted.
in, err := os.Open("test_artifacts/data.txt")
require.NoError(t, err)
defer in.Close()
// Write the encoded information to this buffer.
var cipherData bytes.Buffer
// Enough duration to check for a non-existent beacon.
duration := 4 * time.Second
roundNumber := network.RoundNumber(time.Now().Add(duration))
err = tlock.New(network).Encrypt(&cipherData, in, roundNumber)
require.NoError(t, err)
// =========================================================================
// Decrypt
time.Sleep(5 * time.Second)
// Write the decoded information to this buffer.
var plainData bytes.Buffer
err = tlock.New(network).Decrypt(&plainData, &cipherData)
require.NoError(t, err)
if !bytes.Equal(plainData.Bytes(), dataFile) {
t.Fatalf("decrypted file is invalid; expected %d; got %d", len(dataFile), len(plainData.Bytes()))
}
}
func TestEncryptionWithRound(t *testing.T) {
if testing.Short() {
t.Skip("skipping live testing in short mode")
}
network, err := http.NewNetwork(testnetHost, testnetChainHash)
require.NoError(t, err)
// =========================================================================
// Encrypt
// Read the plaintext data to be encrypted.
in, err := os.Open("test_artifacts/data.txt")
require.NoError(t, err)
defer in.Close()
// Write the encoded information to this buffer.
var cipherData bytes.Buffer
futureRound := network.RoundNumber(time.Now().Add(6 * time.Second))
err = tlock.New(network).Encrypt(&cipherData, in, futureRound)
require.NoError(t, err)
// =========================================================================
// Decrypt
var plainData bytes.Buffer
// Wait for the future beacon to exist.
time.Sleep(10 * time.Second)
err = tlock.New(network).Decrypt(&plainData, &cipherData)
require.NoError(t, err)
if !bytes.Equal(plainData.Bytes(), dataFile) {
t.Fatalf("decrypted file is invalid; expected %d; got %d", len(dataFile), len(plainData.Bytes()))
}
}
func TestTimeLockUnlock(t *testing.T) {
network, err := http.NewNetwork(testnetHost, testnetChainHash)
require.NoError(t, err)
futureRound := network.RoundNumber(time.Now())
id, err := network.Signature(futureRound)
require.NoError(t, err)
data := []byte(`anything`)
cipherText, err := tlock.TimeLock(network.Scheme(), network.PublicKey(), futureRound, data)
require.NoError(t, err)
beacon := chain.Beacon{
Round: futureRound,
Signature: id,
}
b, err := tlock.TimeUnlock(network.Scheme(), network.PublicKey(), beacon, cipherText)
require.NoError(t, err)
if !bytes.Equal(data, b) {
t.Fatalf("unexpected bytes; expected len %d; got %d", len(data), len(b))
}
}
func TestCannotEncryptWithPointAtInfinity(t *testing.T) {
suite := bls.NewBLS12381Suite()
t.Run("on G2", func(t *testing.T) {
infinity := suite.G2().Scalar().Zero()
pointAtInfinity := suite.G2().Point().Mul(infinity, nil)
_, err := tlock.TimeLock(*crypto.NewPedersenBLSUnchainedSwapped(), pointAtInfinity, 10, []byte("deadbeef"))
require.ErrorIs(t, err, tlock.ErrInvalidPublicKey)
})
t.Run("on G1", func(t *testing.T) {
infinity := suite.G1().Scalar().Zero()
pointAtInfinity := suite.G1().Point().Mul(infinity, nil)
_, err := tlock.TimeLock(*crypto.NewPedersenBLSUnchained(), pointAtInfinity, 10, []byte("deadbeef"))
require.ErrorIs(t, err, tlock.ErrInvalidPublicKey)
})
}
func TestDecryptText(t *testing.T) {
cipher := `-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHRsb2NrIDM5MTUwNiA1MmRiOWJhNzBl
MGNjMGY2ZWFmNzgwM2RkMDc0NDdhMWY1NDc3NzM1ZmQzZjY2MTc5MmJhOTQ2MDBj
ODRlOTcxCmxkby91Wkx4eW1rc3Z4WDNIVWxDREpEdm5sWE1qeFU1K09JditIMFlK
ak5sUFQwbWwvNUtyemUxQnhTT2RNTkkKRXF3ZDBVV1RBWU1PVHBlV0R3L2d0c2hN
OUhkWUE0YzJJdGMxcUFoRElUR2NKQkh0Nnc5N2dIUldadVZ4UU5yaApONWNPNyty
QkJRSkY4MlFRRkJZVUMxNGpiL1VZYjNGaDFsUVNuelVic0dVCi0tLSAxb1NNRnp6
M2NqcDBjT3FVdmtIQnQ5Y044MUlsV3hZM29GZVg5T05hSzdFCjkZYt1Cam0OPjdn
WdBQADOMF88wDRmZEnDw+D1j/8NrJXLI87enseShAns+L/NkNGhA8oiA+ZxaTbfs
wcryvxRQprkmX2IEfSUWZWyCTV47cA+5XEdfpFK0Ull7VaTh7dhkcozwc5kruI8Z
1txsd/vjXpKRj199cfL6tEIH0fR+re6AHhCRljKWhsUpCyGuRnBFO5/KpVsTPx3h
hbioFa3010UG
-----END AGE ENCRYPTED FILE-----`
t.Run("With valid network", func(tt *testing.T) {
network, err := http.NewNetwork(mainnetHost, mainnetChainHash)
require.NoError(tt, err)
testReader := strings.NewReader(cipher)
var plainData bytes.Buffer
err = tlock.New(network).Decrypt(&plainData, testReader)
require.NoError(tt, err)
type Message struct {
Time int `json:"Time"`
Option string `json:"option"`
Address string `json:"Address"`
}
expected := Message{1693810319389, "Yes\n", "0x8f794a441b5cc022926027d29fa1ce173793976577d614abc25921b225f99db7"}
var fromJson Message
err = json.Unmarshal(plainData.Bytes(), &fromJson)
require.NoError(tt, err)
require.Equal(tt, expected, fromJson)
})
t.Run("With invalid network", func(tt *testing.T) {
network, err := http.NewNetwork(testnetHost, testnetChainHash)
require.NoError(tt, err)
testReader := strings.NewReader(cipher)
var plainData bytes.Buffer
err = tlock.New(network).Decrypt(&plainData, testReader)
require.ErrorIs(tt, err, tlock.ErrWrongChainhash)
})
}
func TestInteropWithJS(t *testing.T) {
t.Run("on Mainnet with G1 sigs", func(t *testing.T) {
cipher := `-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHRsb2NrIDMzOTU5MiA1MmRiOWJhNzBl
MGNjMGY2ZWFmNzgwM2RkMDc0NDdhMWY1NDc3NzM1ZmQzZjY2MTc5MmJhOTQ2MDBj
ODRlOTcxCmpUd2pKVnN4ZHpBOVJkZk4vRDhFM0Ira3AvNTVDTHVGMlFnaTE4b1Z1
aHdFL1d6SUxZQk5VNkZPRUM5MVRIZW8KRk5pSnN4RUppU3pqbnRGRHZCWlpxaHRx
UHRyL3dyZXRnYmhsN0JSZm9KM1hPMy9qUzZFL0prVldqeEhWZWMzVQoxenZIY2o3
TFJjYlFQaVFuT2NoUnZxbWxTS0I2YWFVenlzdjNjdTJwQUhvCi0tLSBNbnJqbTJ1
cFFvS3l2azkrSmlaM1BjNWtLYUhpMktSOEk1VkdsUmJQMmZzCtj+TQ33fW5scRgm
iQdyc3S+14kzFECervdIV0YEQNMYJczz6dAHu1C3vCvbFRs=
-----END AGE ENCRYPTED FILE-----`
expected := "hello quicknet"
network, err := http.NewNetwork(mainnetHost, mainnetChainHash)
require.NoError(t, err)
testReader := strings.NewReader(cipher)
var plainData bytes.Buffer
err = tlock.New(network).Decrypt(&plainData, testReader)
require.NoError(t, err)
require.Equal(t, expected, plainData.String())
})
t.Run("on Testnet with G1 sigs", func(t *testing.T) {
cipher := `-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHRsb2NrIDE1MzAwNDUgY2M5YzM5ODQ0
MjczN2NiZDE0MTUyNjYwMDkxOWVkZDY5ZjFkNmY5YjRhZGI2N2U0ZDkxMmZiYzY0
MzQxYTlhNQp1QjNLbmlaeVFDbGk1d0N4b25OL2UvQzFYMmI1ZzMyWW01VWRwVEtR
aGtQM3l4TUMxdWhlaFdDZ0NRS0hKcDU5CkV0UkNXazhCckNlWVArcnduZjR2OVd3
dWpFWk11TGp1SUt1Q3F1SXdNcEdUaHc0VXJEbEVablU5ZndPZDBkcXgKejd6aXZR
bFFVQU44ekhZWjhwM2RJekR4NC9la25OQWk5UHhUN1daYTFCTQotLS0gNXZDS3lY
ZlVySU92d29LZEhGR2h6ZUZiVitQSjBsNEVnM1JtWC9INm9YWQoyPsJWIBkmJPZi
oG32+guUclyoVQKHLIGYYAQ5QjSP0TRi6NqURkKBMpPyUe/D
-----END AGE ENCRYPTED FILE-----`
expected := "hello quicknet"
network, err := http.NewNetwork(testnetHost, testnetChainHash)
require.NoError(t, err)
testReader := strings.NewReader(cipher)
var plainData bytes.Buffer
err = tlock.New(network).Decrypt(&plainData, testReader)
require.NoError(t, err)
require.Equal(t, expected, plainData.String())
})
}