-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathpoint.go
90 lines (77 loc) · 2.16 KB
/
point.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 server
import (
"math/bits"
"runtime"
"github.com/dkales/dpf-go/dpf"
"github.com/lukechampine/fastxor"
"github.com/si-co/vpir-code/lib/database"
)
// PIR is the server for the information theoretic classical PIR scheme
// working in GF(2).
// This scheme is used for point queries, both in the authenticated and
// unauthenticated setting. The former adds Merkle-tree based authentication
// information to the database entries, but this is trasparent from the server
// perspective and only changes the database creation.
type PIR struct {
numServers int
db *database.Bytes
cores int
}
// NewPIR return a server for the information theoretic single-bit
// scheme, working both with the vector and the rebalanced representation of
// the database.
func NewPIR(db *database.Bytes, cores ...int) *PIR {
if len(cores) == 0 {
return &PIR{
db: db,
cores: runtime.NumCPU(),
}
}
return &PIR{db: db, cores: cores[0]}
}
func NewPIRTwo(db *database.Bytes, cores ...int) *PIR {
p := NewPIR(db, cores...)
p.numServers = 2
return p
}
// DBInfo returns database info
func (s *PIR) DBInfo() *database.Info {
return &s.db.Info
}
// AnswerBytes computes the answer for the given query encoded in bytes
func (s *PIR) AnswerBytes(q []byte) ([]byte, error) {
return s.Answer(q), nil
}
// Answer computes the answer for the given query
func (s *PIR) Answer(q []byte) []byte {
nRows := s.db.NumRows
nCols := s.db.NumColumns
// use DPF for 2-servers
if s.numServers == 2 {
q = dpf.EvalFull(q, uint64(bits.Len(uint(nCols))))
}
var prevPos, nextPos int
out := make([]byte, nRows*s.db.BlockSize)
for i := 0; i < nRows; i++ {
for j := 0; j < nCols; j++ {
nextPos += s.db.BlockLengths[i*nCols+j]
}
xorValues(
s.db.Entries[prevPos:nextPos],
s.db.BlockLengths[i*nCols:(i+1)*nCols],
q,
out[i*s.db.BlockSize:(i+1)*s.db.BlockSize])
prevPos = nextPos
}
return out
}
// XORs entries and q block by block of size bl
func xorValues(entries []byte, blockLens []int, q []byte, out []byte) {
pos := 0
for j := range blockLens {
if (q[j/8]>>(j%8))&1 == byte(1) {
fastxor.Bytes(out, out, entries[pos:pos+blockLens[j]])
}
pos += blockLens[j]
}
}