benchmark_test.go raw
1 package encryption
2
3 import (
4 "testing"
5
6 "next.orly.dev/pkg/nostr/interfaces/signer/p8k"
7 "lukechampine.com/frand"
8 )
9
10 // createTestConversationKey creates a test conversation key
11 func createTestConversationKey() []byte {
12 return frand.Bytes(32)
13 }
14
15 // createTestKeyPair creates a key pair for ECDH testing
16 func createTestKeyPair() (*p8k.Signer, []byte) {
17 signer := p8k.MustNew()
18 if err := signer.Generate(); err != nil {
19 panic(err)
20 }
21 return signer, signer.Pub()
22 }
23
24 // BenchmarkNIP44Encrypt benchmarks NIP-44 encryption
25 func BenchmarkNIP44Encrypt(b *testing.B) {
26 conversationKey := createTestConversationKey()
27 plaintext := []byte("This is a test message for encryption benchmarking")
28
29 b.ResetTimer()
30 b.ReportAllocs()
31
32 for i := 0; i < b.N; i++ {
33 _, err := Encrypt(conversationKey, plaintext, nil)
34 if err != nil {
35 b.Fatal(err)
36 }
37 }
38 }
39
40 // BenchmarkNIP44EncryptSmall benchmarks encryption of small messages
41 func BenchmarkNIP44EncryptSmall(b *testing.B) {
42 conversationKey := createTestConversationKey()
43 plaintext := []byte("a")
44
45 b.ResetTimer()
46 b.ReportAllocs()
47
48 for i := 0; i < b.N; i++ {
49 _, err := Encrypt(conversationKey, plaintext, nil)
50 if err != nil {
51 b.Fatal(err)
52 }
53 }
54 }
55
56 // BenchmarkNIP44EncryptLarge benchmarks encryption of large messages
57 func BenchmarkNIP44EncryptLarge(b *testing.B) {
58 conversationKey := createTestConversationKey()
59 plaintext := make([]byte, 4096)
60 for i := range plaintext {
61 plaintext[i] = byte(i % 256)
62 }
63
64 b.ResetTimer()
65 b.ReportAllocs()
66
67 for i := 0; i < b.N; i++ {
68 _, err := Encrypt(conversationKey, plaintext, nil)
69 if err != nil {
70 b.Fatal(err)
71 }
72 }
73 }
74
75 // BenchmarkNIP44Decrypt benchmarks NIP-44 decryption
76 func BenchmarkNIP44Decrypt(b *testing.B) {
77 conversationKey := createTestConversationKey()
78 plaintext := []byte("This is a test message for encryption benchmarking")
79 ciphertext, err := Encrypt(conversationKey, plaintext, nil)
80 if err != nil {
81 b.Fatal(err)
82 }
83
84 b.ResetTimer()
85 b.ReportAllocs()
86
87 for i := 0; i < b.N; i++ {
88 _, err := Decrypt(conversationKey, ciphertext)
89 if err != nil {
90 b.Fatal(err)
91 }
92 }
93 }
94
95 // BenchmarkNIP44DecryptSmall benchmarks decryption of small messages
96 func BenchmarkNIP44DecryptSmall(b *testing.B) {
97 conversationKey := createTestConversationKey()
98 plaintext := []byte("a")
99 ciphertext, err := Encrypt(conversationKey, plaintext, nil)
100 if err != nil {
101 b.Fatal(err)
102 }
103
104 b.ResetTimer()
105 b.ReportAllocs()
106
107 for i := 0; i < b.N; i++ {
108 _, err := Decrypt(conversationKey, ciphertext)
109 if err != nil {
110 b.Fatal(err)
111 }
112 }
113 }
114
115 // BenchmarkNIP44DecryptLarge benchmarks decryption of large messages
116 func BenchmarkNIP44DecryptLarge(b *testing.B) {
117 conversationKey := createTestConversationKey()
118 plaintext := make([]byte, 4096)
119 for i := range plaintext {
120 plaintext[i] = byte(i % 256)
121 }
122 ciphertext, err := Encrypt(conversationKey, plaintext, nil)
123 if err != nil {
124 b.Fatal(err)
125 }
126
127 b.ResetTimer()
128 b.ReportAllocs()
129
130 for i := 0; i < b.N; i++ {
131 _, err := Decrypt(conversationKey, ciphertext)
132 if err != nil {
133 b.Fatal(err)
134 }
135 }
136 }
137
138 // BenchmarkNIP44RoundTrip benchmarks encrypt/decrypt round trip
139 func BenchmarkNIP44RoundTrip(b *testing.B) {
140 conversationKey := createTestConversationKey()
141 plaintext := []byte("This is a test message for encryption benchmarking")
142
143 b.ResetTimer()
144 b.ReportAllocs()
145
146 for i := 0; i < b.N; i++ {
147 ciphertext, err := Encrypt(conversationKey, plaintext, nil)
148 if err != nil {
149 b.Fatal(err)
150 }
151 _, err = Decrypt(conversationKey, ciphertext)
152 if err != nil {
153 b.Fatal(err)
154 }
155 }
156 }
157
158 // BenchmarkNIP4Encrypt benchmarks NIP-4 encryption
159 func BenchmarkNIP4Encrypt(b *testing.B) {
160 key := createTestConversationKey()
161 msg := []byte("This is a test message for NIP-4 encryption benchmarking")
162
163 b.ResetTimer()
164 b.ReportAllocs()
165
166 for i := 0; i < b.N; i++ {
167 _, err := EncryptNip4(msg, key)
168 if err != nil {
169 b.Fatal(err)
170 }
171 }
172 }
173
174 // BenchmarkNIP4Decrypt benchmarks NIP-4 decryption
175 func BenchmarkNIP4Decrypt(b *testing.B) {
176 key := createTestConversationKey()
177 msg := []byte("This is a test message for NIP-4 encryption benchmarking")
178 ciphertext, err := EncryptNip4(msg, key)
179 if err != nil {
180 b.Fatal(err)
181 }
182
183 b.ResetTimer()
184 b.ReportAllocs()
185
186 for i := 0; i < b.N; i++ {
187 decrypted, err := DecryptNip4(ciphertext, key)
188 if err != nil {
189 b.Fatal(err)
190 }
191 if len(decrypted) == 0 {
192 b.Fatal("decrypted message is empty")
193 }
194 }
195 }
196
197 // BenchmarkNIP4RoundTrip benchmarks NIP-4 encrypt/decrypt round trip
198 func BenchmarkNIP4RoundTrip(b *testing.B) {
199 key := createTestConversationKey()
200 msg := []byte("This is a test message for NIP-4 encryption benchmarking")
201
202 b.ResetTimer()
203 b.ReportAllocs()
204
205 for i := 0; i < b.N; i++ {
206 ciphertext, err := EncryptNip4(msg, key)
207 if err != nil {
208 b.Fatal(err)
209 }
210 _, err = DecryptNip4(ciphertext, key)
211 if err != nil {
212 b.Fatal(err)
213 }
214 }
215 }
216
217 // BenchmarkGenerateConversationKey benchmarks conversation key generation
218 func BenchmarkGenerateConversationKey(b *testing.B) {
219 signer1, _ := createTestKeyPair()
220 signer2, _ := createTestKeyPair()
221
222 // Get compressed public keys
223 pub1, err := signer1.PubCompressed()
224 if err != nil {
225 b.Fatal(err)
226 }
227 pub2, err := signer2.PubCompressed()
228 if err != nil {
229 b.Fatal(err)
230 }
231
232 b.ResetTimer()
233 b.ReportAllocs()
234
235 for i := 0; i < b.N; i++ {
236 _, err := GenerateConversationKey(signer1.Sec(), pub1)
237 if err != nil {
238 b.Fatal(err)
239 }
240 // Use signer2's pubkey for next iteration to vary inputs
241 pub1 = pub2
242 }
243 }
244
245 // BenchmarkCalcPadding benchmarks padding calculation
246 func BenchmarkCalcPadding(b *testing.B) {
247 sizes := []int{
248 1, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
249 }
250
251 b.ResetTimer()
252 b.ReportAllocs()
253
254 for i := 0; i < b.N; i++ {
255 size := sizes[i%len(sizes)]
256 _ = calcPadding(size)
257 }
258 }
259
260 // BenchmarkGetKeys benchmarks key derivation
261 func BenchmarkGetKeys(b *testing.B) {
262 conversationKey := createTestConversationKey()
263 nonce := frand.Bytes(32)
264
265 b.ResetTimer()
266 b.ReportAllocs()
267
268 for i := 0; i < b.N; i++ {
269 _, _, _, err := MessageKeys(conversationKey, nonce)
270 if err != nil {
271 b.Fatal(err)
272 }
273 }
274 }
275
276 // BenchmarkEncryptInternal benchmarks internal encrypt function
277 func BenchmarkEncryptInternal(b *testing.B) {
278 key := createTestConversationKey()
279 nonce := frand.Bytes(12)
280 message := make([]byte, 256)
281 for i := range message {
282 message[i] = byte(i % 256)
283 }
284
285 b.ResetTimer()
286 b.ReportAllocs()
287
288 for i := 0; i < b.N; i++ {
289 _, err := chacha20_(key, nonce, message)
290 if err != nil {
291 b.Fatal(err)
292 }
293 }
294 }
295
296 // BenchmarkSHA256Hmac benchmarks HMAC calculation
297 func BenchmarkSHA256Hmac(b *testing.B) {
298 key := createTestConversationKey()
299 nonce := frand.Bytes(32)
300 ciphertext := make([]byte, 256)
301 for i := range ciphertext {
302 ciphertext[i] = byte(i % 256)
303 }
304
305 b.ResetTimer()
306 b.ReportAllocs()
307
308 for i := 0; i < b.N; i++ {
309 _, err := sha256Hmac(key, ciphertext, nonce)
310 if err != nil {
311 b.Fatal(err)
312 }
313 }
314 }
315