github.com/ezoic/ws@v1.0.4-0.20220713205711-5c1d69e074c5/cipher_test.go (about) 1 package ws 2 3 import ( 4 "fmt" 5 "math/rand" 6 "reflect" 7 "testing" 8 ) 9 10 func TestCipher(t *testing.T) { 11 type test struct { 12 name string 13 in []byte 14 mask [4]byte 15 offset int 16 } 17 cases := []test{ 18 { 19 name: "simple", 20 in: []byte("Hello, XOR!"), 21 mask: [4]byte{1, 2, 3, 4}, 22 }, 23 { 24 name: "simple", 25 in: []byte("Hello, XOR!"), 26 mask: [4]byte{255, 255, 255, 255}, 27 }, 28 } 29 for offset := 0; offset < 4; offset++ { 30 for tail := 0; tail < 8; tail++ { 31 for b64 := 0; b64 < 3; b64++ { 32 var ( 33 ln = remain[offset] 34 rn = tail 35 n = b64*8 + ln + rn 36 ) 37 38 p := make([]byte, n) 39 rand.Read(p) 40 41 var m [4]byte 42 rand.Read(m[:]) 43 44 cases = append(cases, test{ 45 in: p, 46 mask: m, 47 offset: offset, 48 }) 49 } 50 } 51 } 52 for _, test := range cases { 53 t.Run(test.name, func(t *testing.T) { 54 // naive implementation of xor-cipher 55 exp := cipherNaive(test.in, test.mask, test.offset) 56 57 res := make([]byte, len(test.in)) 58 copy(res, test.in) 59 Cipher(res, test.mask, test.offset) 60 61 if !reflect.DeepEqual(res, exp) { 62 t.Errorf("Cipher(%v, %v):\nact:\t%v\nexp:\t%v\n", test.in, test.mask, res, exp) 63 } 64 }) 65 } 66 } 67 68 func TestCipherChops(t *testing.T) { 69 for n := 2; n <= 1024; n <<= 1 { 70 t.Run(fmt.Sprintf("%d", n), func(t *testing.T) { 71 p := make([]byte, n) 72 b := make([]byte, n) 73 var m [4]byte 74 75 _, err := rand.Read(p) 76 if err != nil { 77 t.Fatal(err) 78 } 79 _, err = rand.Read(m[:]) 80 if err != nil { 81 t.Fatal(err) 82 } 83 84 exp := cipherNaive(p, m, 0) 85 86 for i := 1; i <= n; i <<= 1 { 87 copy(b, p) 88 s := n / i 89 90 for j := s; j <= n; j += s { 91 l, r := j-s, j 92 Cipher(b[l:r], m, l) 93 if !reflect.DeepEqual(b[l:r], exp[l:r]) { 94 t.Errorf("unexpected Cipher([%d:%d]) = %x; want %x", l, r, b[l:r], exp[l:r]) 95 return 96 } 97 } 98 } 99 100 l := 0 101 copy(b, p) 102 for l < n { 103 r := rand.Intn(n-l) + l + 1 104 Cipher(b[l:r], m, l) 105 if !reflect.DeepEqual(b[l:r], exp[l:r]) { 106 t.Errorf("unexpected Cipher([%d:%d]):\nact:\t%v\nexp:\t%v\nact:\t%#x\nexp:\t%#x\n\n", l, r, b[l:r], exp[l:r], b[l:r], exp[l:r]) 107 return 108 } 109 l = r 110 } 111 }) 112 } 113 } 114 115 func cipherNaive(p []byte, m [4]byte, pos int) []byte { 116 r := make([]byte, len(p)) 117 copy(r, p) 118 cipherNaiveNoCp(r, m, pos) 119 return r 120 } 121 122 func cipherNaiveNoCp(p []byte, m [4]byte, pos int) []byte { 123 for i := 0; i < len(p); i++ { 124 p[i] ^= m[(pos+i)%4] 125 } 126 return p 127 } 128 129 func BenchmarkCipher(b *testing.B) { 130 for _, bench := range []struct { 131 size int 132 offset int 133 }{ 134 { 135 size: 7, 136 offset: 1, 137 }, 138 { 139 size: 125, 140 }, 141 { 142 size: 1024, 143 }, 144 { 145 size: 4096, 146 }, 147 { 148 size: 4100, 149 offset: 4, 150 }, 151 { 152 size: 4099, 153 offset: 3, 154 }, 155 { 156 size: (1 << 15) + 7, 157 offset: 49, 158 }, 159 } { 160 bts := make([]byte, bench.size) 161 _, err := rand.Read(bts) 162 if err != nil { 163 b.Fatal(err) 164 } 165 166 var mask [4]byte 167 _, err = rand.Read(mask[:]) 168 if err != nil { 169 b.Fatal(err) 170 } 171 172 //b.Run(fmt.Sprintf("naive_bytes=%d;offset=%d", bench.size, bench.offset), func(b *testing.B) { 173 // for i := 0; i < b.N; i++ { 174 // cipherNaiveNoCp(bts, mask, bench.offset) 175 // } 176 //}) 177 b.Run(fmt.Sprintf("bytes=%d;offset=%d", bench.size, bench.offset), func(b *testing.B) { 178 for i := 0; i < b.N; i++ { 179 Cipher(bts, mask, bench.offset) 180 } 181 }) 182 } 183 }