-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathfield.go
121 lines (107 loc) · 2.78 KB
/
field.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
package field
import (
"encoding/binary"
"io"
"github.com/si-co/vpir-code/lib/utils"
)
type Element uint32
const (
ModP = uint32(2147483647) // 2^31 - 1
Bytes = 4
Bits = 31
Mask = 127
ConcurrentExecutions = 4
)
func NegateVector(in []uint32) []uint32 {
for i := range in {
in[i] = ModP - in[i]
}
return in
}
// Element converts input bytes into a field toElement.
// It sources a new random byte string in the rare case
// when the input bytes convert to ModP
func toElement(in []byte) uint32 {
// Clearing the top most bit of uint32
in[0] &= Mask
// Take the first Bytes bytes
//out := *(*uint32)(unsafe.Pointer(&in))
out := binary.BigEndian.Uint32(in[:Bytes])
// Make sure that toElement is not equal 2^31 - 1
for out == ModP {
var buf [Bytes]byte
_, err := utils.RandomPRG().Read(buf[:])
if err != nil {
panic("error in randomness")
}
out = binary.BigEndian.Uint32(buf[:])
}
return out
}
func RandElementWithPRG(rnd io.Reader) uint32 {
var buf [Bytes]byte
var out = ModP
// Make sure that toElement is not equal 2^31 - 1
for out == ModP {
_, err := rnd.Read(buf[:])
if err != nil {
panic("error in randomness")
}
// Clearing the top most bit of uint32
buf[0] &= Mask
out = binary.BigEndian.Uint32(buf[:])
}
return out
}
func RandElement() uint32 {
return RandElementWithPRG(utils.RandomPRG())
}
func RandVectorWithPRG(length int, rnd io.Reader) []uint32 {
bytesLength := length * Bytes
buf := make([]byte, bytesLength)
_, err := rnd.Read(buf)
if err != nil {
panic("error in randomness")
}
out := make([]uint32, length)
for i := range out {
//Clearing the top most bit of uint32
buf[i*Bytes] &= Mask
out[i] = binary.BigEndian.Uint32(buf[i*Bytes : (i+1)*Bytes])
for out[i] == ModP {
out[i] = RandElementWithPRG(rnd)
}
}
return out
}
func RandVector(length int) []uint32 {
return RandVectorWithPRG(length, utils.RandomPRG())
}
func BytesToElements(out []uint32, in []byte) {
//if len(in) % Bytes != 0 {
// padding := make([]byte, Bytes-len(in) % Bytes)
// in = append(in, padding...)
//}
for i := range out {
out[i] = toElement(in[i*Bytes : (i+1)*Bytes])
}
}
// VectorToBytes extracts bytes from a vector of field elements. Assume that
// only 3 bytes worth of data are embedded in each field toElement and therefore
// strips the initial zero from each field toElement.
func VectorToBytes(in interface{}) []byte {
switch vec := in.(type) {
case []uint32:
elemSize := Bytes - 1
out := make([]byte, len(vec)*elemSize)
for i, e := range vec {
fieldBytes := make([]byte, Bytes)
binary.BigEndian.PutUint32(fieldBytes, e)
// strip first zero and copy to the output
copy(out[i*elemSize:(i+1)*elemSize], fieldBytes[1:])
}
return out
default:
return nil
}
}