package crypto import ( "bytes" "math/big" "testing" ) func TestConstantTimeByteCompare(t *testing.T) { cases := []struct { x, y []byte r int expectErr bool }{ {x: []byte{}, y: []byte{}, r: 0}, {x: []byte{40}, y: []byte{30}, r: 1}, {x: []byte{30}, y: []byte{40}, r: -1}, {x: []byte{60, 40, 30, 10, 20}, y: []byte{50, 30, 20, 0, 10}, r: 1}, {x: []byte{50, 30, 20, 0, 10}, y: []byte{60, 40, 30, 10, 20}, r: -1}, {x: nil, y: []byte{}, r: 0}, {x: []byte{}, y: nil, r: 0}, {x: []byte{}, y: []byte{10}, expectErr: true}, {x: []byte{10}, y: []byte{}, expectErr: true}, {x: []byte{10, 20}, y: []byte{10}, expectErr: true}, } for _, tt := range cases { compare, err := ConstantTimeByteCompare(tt.x, tt.y) if (err != nil) != tt.expectErr { t.Fatalf("expectErr=%v, got %v", tt.expectErr, err) } if e, a := tt.r, compare; e != a { t.Errorf("expect %v, got %v", e, a) } } } func BenchmarkConstantTimeCompare(b *testing.B) { x, y := big.NewInt(1023), big.NewInt(1024) b.ResetTimer() for i := 0; i < b.N; i++ { ConstantTimeByteCompare(x.Bytes(), y.Bytes()) } } func BenchmarkCompare(b *testing.B) { x, y := big.NewInt(1023).Bytes(), big.NewInt(1024).Bytes() b.ResetTimer() for i := 0; i < b.N; i++ { bytes.Compare(x, y) } } func mustBigInt(s string) *big.Int { b, ok := (&big.Int{}).SetString(s, 16) if !ok { panic("can't parse as big.Int") } return b }