-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathpgp.go
225 lines (185 loc) · 5.79 KB
/
pgp.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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package database
import (
"bytes"
"errors"
"log"
"sort"
"github.com/nikirill/go-crypto/openpgp"
"github.com/si-co/vpir-code/lib/merkle"
"github.com/si-co/vpir-code/lib/pgp"
"github.com/si-co/vpir-code/lib/utils"
)
const numKeysToDBLengthRatio float32 = 0.1
func GenerateRealKeyDB(dataPaths []string) (*DB, error) {
log.Printf("Loading keys: %v\n", dataPaths)
keys, err := pgp.LoadKeysFromDisk(dataPaths)
if err != nil {
return nil, err
}
// Sort the keys by id, higher first, to make sure that
// all the servers end up with an identical hash table.
sortById(keys)
// only information needed for FSS-based schemes
info := Info{NumColumns: len(keys),
Merkle: &Merkle{ProofLen: 0, Root: []byte{0}}, // only for tests compatibility}
}
// create empty database
db := NewKeysDB(info)
// iterate and embed keys
for i := 0; i < len(keys); i++ {
// useless to store keys for FSS queries
//key := field.BytesToElements(keys[i].Packet)
//db.Entries = append(db.Entries, key...)
keyInfo, err := GetKeyInfoFromPacket(keys[i].Packet)
if err != nil {
log.Fatalf("error getting info from a key block: %v", err)
}
db.KeysInfo = append(db.KeysInfo, keyInfo)
}
return db, nil
}
func GenerateRealKeyBytes(dataPaths []string, rebalanced bool) (*Bytes, error) {
log.Printf("Bytes db rebalanced: %v, loading keys: %v\n", rebalanced, dataPaths)
keys, err := pgp.LoadKeysFromDisk(dataPaths)
if err != nil {
return nil, err
}
// Sort the keys by id, higher first, to make sure that
// all the servers end up with an identical hash table.
sortById(keys)
// decide on the length of the hash table
preSquareNumBlocks := int(float32(len(keys)) * numKeysToDBLengthRatio)
numRows, numColumns := CalculateNumRowsAndColumns(preSquareNumBlocks, rebalanced)
ht := makeHashTable(keys, numRows*numColumns)
// get the maximum byte length of the values in the hashTable
// +1 takes into account the padding 0x80 that is always added.
blockLen := utils.MaxBytesLength(ht) + 1
// create all zeros db
db := InitBytes(numRows, numColumns, blockLen)
// order blocks because of map
blocks := make([][]byte, numRows*numColumns)
for k, v := range ht {
// appending only 0x80 (without zeros)
blocks[k] = PadWithSignalByte(v)
}
// add blocks to the db with the according padding and store the length
for k, block := range blocks {
db.BlockLengths[k] = len(block)
db.Entries = append(db.Entries, block...)
}
return db, nil
}
func GenerateRealKeyMerkle(dataPaths []string, rebalanced bool) (*Bytes, error) {
log.Printf("Merkle db rebalanced: %v, loading keys: %v\n", rebalanced, dataPaths)
keys, err := pgp.LoadKeysFromDisk(dataPaths)
if err != nil {
return nil, err
}
// Sort the keys by id, higher first, to make sure that
// all the servers end up with an identical hash table.
sortById(keys)
// decide on the length of the hash table
preSquareNumBlocks := int(float32(len(keys)) * numKeysToDBLengthRatio)
numRows, numColumns := CalculateNumRowsAndColumns(preSquareNumBlocks, rebalanced)
ht := makeHashTable(keys, numRows*numColumns)
// map into blocks
blocks := make([][]byte, numRows*numColumns)
for k, v := range ht {
// appending only 0x80 (without zeros)
blocks[k] = PadWithSignalByte(v)
}
// generate tree
tree, err := merkle.New(blocks)
if err != nil {
return nil, err
}
proofLen := tree.EncodedProofLength()
maxBlockLen := 0
blockLens := make([]int, numRows*numColumns)
for i := 0; i < numRows*numColumns; i++ {
// we add +1 for appending 0x80 to the proof
blockLens[i] = len(blocks[i]) + proofLen + 1
if blockLens[i] > maxBlockLen {
maxBlockLen = blockLens[i]
}
}
entries := makeMerkleEntries(blocks, tree, numRows, numColumns, maxBlockLen)
m := &Bytes{
Entries: entries,
Info: Info{
NumRows: numRows,
NumColumns: numColumns,
BlockSize: maxBlockLen,
BlockLengths: blockLens,
PIRType: "merkle",
Merkle: &Merkle{Root: tree.Root(), ProofLen: proofLen},
},
}
return m, nil
}
func makeHashTable(keys []*pgp.Key, tableLen int) map[int][]byte {
// prepare db
db := make(map[int][]byte)
// range over all id,v pairs and assign every pair to a given bucket
for _, key := range keys {
hashKey := int(HashToIndex(key.ID, tableLen))
db[hashKey] = append(db[hashKey], key.Packet...)
}
return db
}
// Simple ISO/IEC 7816-4 padding where 0x80 is appended to the block, then
// zeros to make up to blockLen
func PadBlock(block []byte, blockLen int) []byte {
block = append(block, byte(0x80))
zeros := make([]byte, blockLen-(len(block)%blockLen))
return append(block, zeros...)
}
func PadWithSignalByte(block []byte) []byte {
return append(block, byte(0x80))
}
func UnPadBlock(block []byte) []byte {
// remove zeros
block = bytes.TrimRightFunc(block, func(b rune) bool {
return b == 0
})
// remove 0x80 preceding zeros
return block[:len(block)-1]
}
func sortById(keys []*pgp.Key) {
sort.Slice(keys, func(i, j int) bool {
return keys[i].ID > keys[j].ID
})
}
func maxKeyLength(keys []*pgp.Key) int {
max := 0
for i := 0; i < len(keys); i++ {
if len(keys[i].Packet) > max {
max = len(keys[i].Packet)
}
}
return max
}
// GetKeyInfoFromPacket parses packet bytes and returns information about the key
func GetKeyInfoFromPacket(pkt []byte) (*KeyInfo, error) {
// parse the input bytes as a key ring
reader := bytes.NewReader(pkt)
el, err := openpgp.ReadKeyRing(reader)
if err != nil {
return nil, err
}
// the key ring is supposed to have only one Entity
if len(el) != 1 {
return nil, errors.New("more than one openpgp entity in a key block")
}
// retrieve bit length
bl, err := el[0].PrimaryKey.BitLength()
if err != nil {
bl = 0
}
return &KeyInfo{
UserId: el[0].PrimaryIdentity().UserId,
CreationTime: el[0].PrimaryKey.CreationTime,
PubKeyAlgo: el[0].PrimaryKey.PubKeyAlgo,
BitLength: bl,
}, nil
}