-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencrypter_test.go
133 lines (121 loc) · 4.21 KB
/
encrypter_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
// SPDX-FileCopyrightText: Winni Neessen <wn@neessen.dev>
//
// SPDX-License-Identifier: MIT
package iocrypter
import (
"bytes"
"crypto/rand"
"errors"
"io"
"strings"
"testing"
)
// testPassword is a constant string representing a password used for testing purposes.
var testPassword = []byte(`:wPIuo[F#Gnh6*lmzc'_bmYpY!UV)Tt1`)
func TestNewEncrypter(t *testing.T) {
t.Run("normal encrypter creation", func(t *testing.T) {
buffer := bytes.NewBuffer(nil)
encrypter, err := NewEncrypter(buffer, testPassword)
if err != nil {
t.Fatalf("failed to create encrypter: %s", err)
}
if encrypter == nil {
t.Fatal("encrypter is nil")
}
})
t.Run("encrypter creation with nil passphrase should fail", func(t *testing.T) {
buffer := bytes.NewBuffer(nil)
_, err := NewEncrypter(buffer, nil)
if err == nil {
t.Fatal("expected encrypter creation to fail with nil passphrase")
}
if !errors.Is(err, ErrPassPhraseEmpty) {
t.Errorf("expected error to be %s, got %s", ErrPassPhraseEmpty, err)
}
})
}
func TestNewEncrypterWithSettings(t *testing.T) {
t.Run("normal encrypter creation", func(t *testing.T) {
buffer := bytes.NewBuffer(nil)
encrypter, err := NewEncrypterWithSettings(buffer, testPassword, NewArgon2Settings())
if err != nil {
t.Fatalf("failed to create encrypter: %s", err)
}
if encrypter == nil {
t.Fatal("encrypter is nil")
}
})
t.Run("encrypter creation fails with broken random reader", func(t *testing.T) {
defaultRandReader := rand.Reader
t.Cleanup(func() { rand.Reader = defaultRandReader })
rand.Reader = &failReadWriter{failOnRead: 0}
buffer := bytes.NewBuffer(nil)
_, err := NewEncrypterWithSettings(buffer, testPassword, NewArgon2Settings())
if err == nil {
t.Fatal("expected encrypter creation to fail with broken random reader")
}
expErr := "failed to generate random salt"
if !strings.Contains(err.Error(), expErr) {
t.Errorf("expected error to contain %s, got %s", expErr, err)
}
})
t.Run("encrypter creation fails with broken random reader on 2nd read", func(t *testing.T) {
defaultRandReader := rand.Reader
t.Cleanup(func() { rand.Reader = defaultRandReader })
rand.Reader = &failReadWriter{failOnRead: 1}
buffer := bytes.NewBuffer(nil)
_, err := NewEncrypterWithSettings(buffer, testPassword, NewArgon2Settings())
if err == nil {
t.Fatal("expected encrypter creation to fail with broken random reader")
}
expErr := "failed to generate random iv"
if !strings.Contains(err.Error(), expErr) {
t.Errorf("expected error to contain %s, got %s", expErr, err)
}
})
t.Run("encrypter fails encrypting into broken writer", func(t *testing.T) {
buffer := bytes.NewBufferString("This is a test")
encrypter, err := NewEncrypterWithSettings(buffer, testPassword, NewArgon2Settings())
if err != nil {
t.Fatalf("failed to create encrypter: %s", err)
}
reader := &failReadWriter{failOnRead: 0}
if _, err = io.Copy(reader, encrypter); err == nil {
t.Error("expected encrypter to fail with broken writer")
}
})
t.Run("encrypter fails encrypting from broken reader", func(t *testing.T) {
reader := &failReadWriter{failOnRead: 0}
encrypter, err := NewEncrypterWithSettings(reader, testPassword, NewArgon2Settings())
if err != nil {
t.Fatalf("failed to create encrypter: %s", err)
}
buffer := bytes.NewBuffer(nil)
if _, err = io.Copy(buffer, encrypter); err == nil {
t.Error("expected encrypter to fail with broken reader")
}
})
}
// failReadWriter is type that satisfies the io.ReadWriter interface. All it does is fail
// on the Read and Write operation. It can fail on a specific read operations and is
// therefore useful to test consecutive reads with errors.
type failReadWriter struct {
failOnRead uint8
currentRead uint8
readFunc func([]byte) (int, error)
}
// Read implements the io.Reader interface for the failReadWriter type
func (r *failReadWriter) Read(p []byte) (int, error) {
if r.currentRead == r.failOnRead {
return 0, errors.New("intentionally failing")
}
r.currentRead++
if r.readFunc != nil {
return r.readFunc(p)
}
return len(p), nil
}
// Write implements the io.Writer interface for the failReadWriter type
func (r *failReadWriter) Write([]byte) (int, error) {
return 0, errors.New("intentionally failing")
}