recognizer_test.go raw
1 package ring
2
3 import "testing"
4
5 // TestMatchBitEquality verifies single-bit equality test.
6 func TestMatchBitEquality(t *testing.T) {
7 kp := DefaultHEParams()
8 pk, sk, _ := HEKeyGen(kp)
9
10 for _, a := range []int{0, 1} {
11 for _, b := range []int{0, 1} {
12 ctA := HEEncrypt(pk, a)
13 ctB := HEEncrypt(pk, b)
14 ctMatch := MatchBit(ctA, ctB)
15 got := HEDecrypt(sk, ctMatch)
16
17 want := 0
18 if a == b {
19 want = 1
20 }
21 if got != want {
22 t.Fatalf("MatchBit(%d, %d): got %d, want %d", a, b, got, want)
23 }
24 }
25 }
26 }
27
28 // TestEncryptDecryptBits verifies bit vector round-trip.
29 func TestEncryptDecryptBits(t *testing.T) {
30 kp := DefaultHEParams()
31 pk, sk, _ := HEKeyGen(kp)
32
33 data := []byte{0xAB, 0xCD}
34 enc := EncryptBits(pk, data)
35 dec := DecryptBits(sk, enc)
36
37 if len(dec) != len(data) {
38 t.Fatalf("length mismatch: got %d, want %d", len(dec), len(data))
39 }
40 for i := range data {
41 if dec[i] != data[i] {
42 t.Fatalf("byte[%d]: got %02x, want %02x", i, dec[i], data[i])
43 }
44 }
45 }
46
47 // TestMatchByteSingle verifies per-pair AND for byte matching.
48 func TestMatchByteSingle(t *testing.T) {
49 kp := DefaultHEParams()
50 pk, sk, rlk := HEKeyGen(kp)
51
52 // Matching bytes: all pair-ANDs should be 1.
53 dataByte := byte(0xA5)
54 patByte := byte(0xA5)
55
56 dataBits := make([]*HECiphertext, 8)
57 patBits := make([]*HECiphertext, 8)
58 for i := range 8 {
59 dataBits[i] = HEEncrypt(pk, int((dataByte>>i)&1))
60 patBits[i] = HEEncrypt(pk, int((patByte>>i)&1))
61 }
62
63 pairs := MatchByteSingle(dataBits, patBits, rlk)
64 if len(pairs) != 4 {
65 t.Fatalf("expected 4 pair results, got %d", len(pairs))
66 }
67
68 for i, ct := range pairs {
69 got := HEDecrypt(sk, ct)
70 if got != 1 {
71 t.Fatalf("pair[%d]: got %d, want 1 (matching bytes)", i, got)
72 }
73 }
74 }
75
76 // TestMatchByteSingleMismatch verifies that a different byte produces
77 // at least one pair with value 0.
78 func TestMatchByteSingleMismatch(t *testing.T) {
79 kp := DefaultHEParams()
80 pk, sk, rlk := HEKeyGen(kp)
81
82 dataByte := byte(0xA5)
83 patByte := byte(0x5A) // every bit is different
84
85 dataBits := make([]*HECiphertext, 8)
86 patBits := make([]*HECiphertext, 8)
87 for i := range 8 {
88 dataBits[i] = HEEncrypt(pk, int((dataByte>>i)&1))
89 patBits[i] = HEEncrypt(pk, int((patByte>>i)&1))
90 }
91
92 pairs := MatchByteSingle(dataBits, patBits, rlk)
93
94 anyZero := false
95 for _, ct := range pairs {
96 if HEDecrypt(sk, ct) == 0 {
97 anyZero = true
98 break
99 }
100 }
101 if !anyZero {
102 t.Fatal("all pairs returned 1 for mismatched bytes")
103 }
104 }
105
106 // TestRecognize verifies the full searchable encryption pipeline.
107 func TestRecognize(t *testing.T) {
108 kp := DefaultHEParams()
109 pk, sk, rlk := HEKeyGen(kp)
110
111 // Search for pattern in data.
112 data := []byte("hello")
113 pattern := []byte("ll")
114
115 matches := Recognize(pk, sk, rlk, data, pattern)
116
117 t.Logf("data=%q, pattern=%q, matches=%v", data, pattern, matches)
118
119 // "ll" should appear at position 2 in "hello".
120 found := false
121 for _, pos := range matches {
122 if pos == 2 {
123 found = true
124 }
125 }
126 if !found {
127 t.Fatalf("expected match at position 2, got %v", matches)
128 }
129 }
130
131 // TestRecognizeNoMatch verifies no false positives.
132 func TestRecognizeNoMatch(t *testing.T) {
133 kp := DefaultHEParams()
134 pk, sk, rlk := HEKeyGen(kp)
135
136 data := []byte("abc")
137 pattern := []byte("xy")
138
139 matches := Recognize(pk, sk, rlk, data, pattern)
140
141 if len(matches) > 0 {
142 t.Fatalf("expected no matches, got %v", matches)
143 }
144 }
145
146 // TestRecognizeSingleByte verifies single-byte pattern search.
147 func TestRecognizeSingleByte(t *testing.T) {
148 kp := DefaultHEParams()
149 pk, sk, rlk := HEKeyGen(kp)
150
151 data := []byte{0x42, 0x43, 0x42, 0x44}
152 pattern := []byte{0x42}
153
154 matches := Recognize(pk, sk, rlk, data, pattern)
155
156 t.Logf("pattern=0x42, matches=%v", matches)
157
158 // 0x42 appears at positions 0 and 2.
159 if len(matches) != 2 {
160 t.Fatalf("expected 2 matches, got %d: %v", len(matches), matches)
161 }
162 }
163
164 func BenchmarkMatchBit(b *testing.B) {
165 kp := DefaultHEParams()
166 pk, _, _ := HEKeyGen(kp)
167 ct0 := HEEncrypt(pk, 0)
168 ct1 := HEEncrypt(pk, 1)
169 b.ResetTimer()
170 for range b.N {
171 MatchBit(ct0, ct1)
172 }
173 }
174
175 func BenchmarkMatchByteSingle(b *testing.B) {
176 kp := DefaultHEParams()
177 pk, _, rlk := HEKeyGen(kp)
178 dataBits := make([]*HECiphertext, 8)
179 patBits := make([]*HECiphertext, 8)
180 for i := range 8 {
181 dataBits[i] = HEEncrypt(pk, i%2)
182 patBits[i] = HEEncrypt(pk, i%2)
183 }
184 b.ResetTimer()
185 for range b.N {
186 MatchByteSingle(dataBits, patBits, rlk)
187 }
188 }
189