1
2
3
4
5 package subtle_test
6
7 import (
8 "bytes"
9 "crypto/rand"
10 . "crypto/subtle"
11 "fmt"
12 "io"
13 "testing"
14 )
15
16 func TestXORBytes(t *testing.T) {
17 for n := 1; n <= 1024; n++ {
18 if n > 16 && testing.Short() {
19 n += n >> 3
20 }
21 for alignP := 0; alignP < 8; alignP++ {
22 for alignQ := 0; alignQ < 8; alignQ++ {
23 for alignD := 0; alignD < 8; alignD++ {
24 p := make([]byte, alignP+n, alignP+n+10)[alignP:]
25 q := make([]byte, alignQ+n, alignQ+n+10)[alignQ:]
26 if n&1 != 0 {
27 p = p[:n]
28 } else {
29 q = q[:n]
30 }
31 if _, err := io.ReadFull(rand.Reader, p); err != nil {
32 t.Fatal(err)
33 }
34 if _, err := io.ReadFull(rand.Reader, q); err != nil {
35 t.Fatal(err)
36 }
37
38 d := make([]byte, alignD+n, alignD+n+10)
39 for i := range d {
40 d[i] = 0xdd
41 }
42 want := make([]byte, len(d), cap(d))
43 copy(want[:cap(want)], d[:cap(d)])
44 for i := 0; i < n; i++ {
45 want[alignD+i] = p[i] ^ q[i]
46 }
47
48 if XORBytes(d[alignD:], p, q); !bytes.Equal(d, want) {
49 t.Fatalf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want)
50 }
51 }
52 }
53 }
54 }
55 }
56
57 func TestXorBytesPanic(t *testing.T) {
58 mustPanic(t, "subtle.XORBytes: dst too short", func() {
59 XORBytes(nil, make([]byte, 1), make([]byte, 1))
60 })
61 mustPanic(t, "subtle.XORBytes: dst too short", func() {
62 XORBytes(make([]byte, 1), make([]byte, 2), make([]byte, 3))
63 })
64 }
65
66 func min(a, b []byte) int {
67 n := len(a)
68 if len(b) < n {
69 n = len(b)
70 }
71 return n
72 }
73
74 func BenchmarkXORBytes(b *testing.B) {
75 dst := make([]byte, 1<<15)
76 data0 := make([]byte, 1<<15)
77 data1 := make([]byte, 1<<15)
78 sizes := []int64{1 << 3, 1 << 7, 1 << 11, 1 << 15}
79 for _, size := range sizes {
80 b.Run(fmt.Sprintf("%dBytes", size), func(b *testing.B) {
81 s0 := data0[:size]
82 s1 := data1[:size]
83 b.SetBytes(int64(size))
84 for i := 0; i < b.N; i++ {
85 XORBytes(dst, s0, s1)
86 }
87 })
88 }
89 }
90
91 func mustPanic(t *testing.T, expected string, f func()) {
92 t.Helper()
93 defer func() {
94 switch msg := recover().(type) {
95 case nil:
96 t.Errorf("expected panic(%q), but did not panic", expected)
97 case string:
98 if msg != expected {
99 t.Errorf("expected panic(%q), but got panic(%q)", expected, msg)
100 }
101 default:
102 t.Errorf("expected panic(%q), but got panic(%T%v)", expected, msg, msg)
103 }
104 }()
105 f()
106 }
107
View as plain text