forked from ahenzinger/simplepir
-
Notifications
You must be signed in to change notification settings - Fork 1
/
lhe.go
90 lines (70 loc) · 2.06 KB
/
lhe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package pir
import (
"github.com/henrycg/simplepir/matrix"
)
type SecretLHE[T matrix.Elem] struct {
query *matrix.Matrix[T]
secret *matrix.Matrix[T]
interm *matrix.Matrix[T]
arr *matrix.Matrix[T]
}
func (s *SecretLHE[T]) Secret() *matrix.Matrix[T] {
return s.secret
}
func (c *Client[T]) PreprocessQueryLHE() *SecretLHE[T] {
inSecret := c.GenerateSecret()
return c.PreprocessQueryLHEGivenSecret(inSecret)
}
func (c *Client[T]) PreprocessQueryLHEGivenSecret(inSecret *matrix.Matrix[T]) *SecretLHE[T] {
if (c.dbinfo.Ne != 1) || ((1 << c.dbinfo.RowLength) > c.params.P) {
panic("Not yet supported.")
}
// checks that p is a power of 2 (since q must be)
if (c.params.P & (c.params.P - 1)) != 0 {
panic("LHE requires p | q.")
}
s := c.PreprocessQueryGivenSecret(inSecret)
return &SecretLHE[T]{
query: s.query,
secret: s.secret,
interm: s.interm,
arr: nil,
}
}
func (c *Client[T]) QueryLHEPreprocessed(arrIn *matrix.Matrix[T], s *SecretLHE[T]) *Query[T] {
arr := arrIn.Copy()
if arr.Rows() != c.dbinfo.M || arr.Cols() != 1 {
panic("Parameter mismatch")
}
s.arr = arr
arr.MulConst(T(c.params.Delta))
arr.AppendZeros(s.query.Rows() - arrIn.Rows())
s.query.Add(arr)
return &Query[T] { s.query }
}
func (c *Client[T]) QueryLHE(arrIn *matrix.Matrix[T]) (*SecretLHE[T], *Query[T]) {
s := c.PreprocessQueryLHE()
q := c.QueryLHEPreprocessed(arrIn, s)
return s, q
}
func (c *Client[T]) DecodeManyLHE(ans *matrix.Matrix[T]) *matrix.Matrix[T] {
out := matrix.Zeros[T](ans.Rows(), 1)
for row := uint64(0); row < ans.Rows(); row++ {
noised := uint64(ans.Get(row, 0))
//log.Printf("noised[%v] = %v [Delta=%v]", row, noised, c.params.Delta)
denoised := c.params.Round(noised)
out.Set(row, 0, T(denoised % c.params.P))
}
return out
}
func (c *Client[T]) RecoverManyLHE(s *SecretLHE[T], ansIn *Answer[T]) *matrix.Matrix[T] {
if (c.dbinfo.Ne != 1) {
panic("Not yet supported")
}
if s.interm == nil {
s.interm = matrix.Mul(c.hint, s.secret)
}
ans := ansIn.Answer.Copy()
ans.Sub(s.interm)
return c.DecodeManyLHE(ans)
}