github.com/simonmittag/ws@v1.1.0-rc.5.0.20210419231947-82b846128245/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  }