-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdb.go
181 lines (150 loc) · 4.29 KB
/
db.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package database
import (
"crypto"
"encoding/binary"
"io"
"math"
"math/rand"
"time"
"golang.org/x/xerrors"
"github.com/cloudflare/circl/group"
"github.com/nikirill/go-crypto/openpgp/packet"
"github.com/si-co/vpir-code/lib/field"
"github.com/si-co/vpir-code/lib/matrix"
"github.com/si-co/vpir-code/lib/utils"
"golang.org/x/crypto/blake2b"
)
type DB struct {
KeysInfo []*KeyInfo
Entries []uint32
Info
}
type KeyInfo struct {
UserId *packet.UserId
CreationTime time.Time
PubKeyAlgo packet.PublicKeyAlgorithm
BitLength uint16
}
type Info struct {
NumRows int
NumColumns int
BlockSize int
BlockLengths []int // length of data in blocks defined in number of elements
// PIR type: classical, merkle
PIRType string
*Auth
*Merkle
}
// Auth is authentication information for the single-server setting
type Auth struct {
DigestLWE *matrix.Matrix
DigestLWE128 *matrix.Matrix128
// The global digest that is a hash of all the row digests. Public.
Digest []byte
// One digest per row, authenticating all the elements in that row.
// also used in the integrity amplification scheme to store
// all the digests
SubDigests []byte
// length in bytes of the subdiget
SubDigestLength int
// ECC group and hash algorithm used for digest computation and PIR itself
Group group.Group
Hash crypto.Hash
// Due to lack of the size functions in the lib API, we store it in the db info
ElementSize int
ScalarSize int
}
// Merkle is the info needed for the Merkle-tree based approach
type Merkle struct {
Root []byte
ProofLen int
}
func NewKeysDB(info Info) *DB {
return &DB{
Info: info,
KeysInfo: make([]*KeyInfo, 0),
Entries: make([]uint32, 0),
}
}
func NewBitsDB(info Info) *DB {
return &DB{
Info: info,
Entries: make([]uint32, info.NumRows*info.NumColumns*info.BlockSize),
}
}
func CreateRandomBitsDB(rnd io.Reader, dbLen, numRows, blockLen int) (*DB, error) {
numColumns := dbLen / (8 * field.Bytes * numRows * blockLen)
// handle very small db
if numColumns == 0 {
numColumns = 1
}
info := Info{
NumColumns: numColumns,
NumRows: numRows,
BlockSize: blockLen,
}
n := numRows * numColumns * blockLen
numBytesToRead := n*field.Bytes + 1
randBytes := make([]byte, numBytesToRead)
if _, err := io.ReadFull(rnd, randBytes[:]); err != nil {
return nil, xerrors.Errorf("failed to read random randBytes: %v", err)
}
db := NewBitsDB(info)
field.BytesToElements(db.Entries, randBytes)
// add block lengths also in this case for compatibility
db.BlockLengths = make([]int, numRows*numColumns)
for i := 0; i < n; i++ {
db.BlockLengths[i/blockLen] = blockLen
}
return db, nil
}
func CreateRandomKeysDB(rnd io.Reader, numIdentifiers int) (*DB, error) {
// only used for eval, so fine to init the seed for
// non-crypto PRG with fixed number
rand.Seed(int64(2<<32 - 7))
keysInfo := make([]*KeyInfo, numIdentifiers)
for i := 0; i < numIdentifiers; i++ {
// random creation date
ct := utils.Randate()
// random algorithm, taken from random permutation of
// https://pkg.go.dev/golang.org/x/crypto/openpgp/packet#PublicKeyAlgorithm
algorithms := []packet.PublicKeyAlgorithm{1, 16, 17, 18, 19}
pka := algorithms[rand.Intn(len(algorithms))]
// random userd id
// By convention, this takes the form "Full Name (Comment) <[email protected]>"
// which is split out in the fields below.
// For testing purposes, only random email and other fields empty strings
id := packet.NewUserId("", "", utils.Ranstring(32))
keysInfo[i] = &KeyInfo{
UserId: id,
CreationTime: ct,
PubKeyAlgo: pka,
}
}
// only information needed for FSS-based schemes
info := Info{NumColumns: numIdentifiers}
return &DB{
KeysInfo: keysInfo,
Info: info,
}, nil
}
// HashToIndex hashes the given id to an index for a database of the given
// length
func HashToIndex(id string, length int) uint32 {
hash := blake2b.Sum256([]byte(id))
return binary.BigEndian.Uint32(hash[:4]) % uint32(length)
}
func CalculateNumRowsAndColumns(numBlocks int, matrix bool) (numRows, numColumns int) {
if matrix {
utils.IncreaseToNextSquare(&numBlocks)
numColumns = int(math.Sqrt(float64(numBlocks)))
numRows = numColumns
} else {
numColumns = numBlocks
numRows = 1
}
return
}
func (d *DB) SizeGiB() float64 {
return float64(len(d.Entries)*16) * 9.313e-10
}