-
Notifications
You must be signed in to change notification settings - Fork 31
/
utils.go
156 lines (133 loc) · 3.76 KB
/
utils.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
package sssa
import (
"bytes"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"fmt"
"math"
"math/big"
"strings"
)
var prime *big.Int
/**
* Returns a random number from the range (0, prime-1) inclusive
**/
func random() *big.Int {
result := big.NewInt(0).Set(prime)
result = result.Sub(result, big.NewInt(1))
result, _ = rand.Int(rand.Reader, result)
return result
}
/**
* Converts a byte array into an a 256-bit big.Int, arraied based upon size of
* the input byte; all values are right-padded to length 256, even if the most
* significant bit is zero.
**/
func splitByteToInt(secret []byte) []*big.Int {
hex_data := hex.EncodeToString(secret)
count := int(math.Ceil(float64(len(hex_data)) / 64.0))
result := make([]*big.Int, count)
for i := 0; i < count; i++ {
if (i+1)*64 < len(hex_data) {
result[i], _ = big.NewInt(0).SetString(hex_data[i*64:(i+1)*64], 16)
} else {
data := strings.Join([]string{hex_data[i*64:], strings.Repeat("0", 64-(len(hex_data)-i*64))}, "")
result[i], _ = big.NewInt(0).SetString(data, 16)
}
}
return result
}
/**
* Converts an array of big.Ints to the original byte array, removing any
* least significant nulls
**/
func mergeIntToByte(secret []*big.Int) []byte {
var hex_data = ""
for i := range secret {
tmp := fmt.Sprintf("%x", secret[i])
hex_data += strings.Join([]string{strings.Repeat("0", (64 - len(tmp))), tmp}, "")
}
result, _ := hex.DecodeString(hex_data)
result = bytes.TrimRight(result, "\x00")
return result
}
/**
* Evauluates a polynomial with coefficients specified in reverse order:
* evaluatePolynomial([a, b, c, d], x):
* returns a + bx + cx^2 + dx^3
**/
func evaluatePolynomial(polynomial []*big.Int, value *big.Int) *big.Int {
last := len(polynomial) - 1
var result *big.Int = big.NewInt(0).Set(polynomial[last])
for s := last - 1; s >= 0; s-- {
result = result.Mul(result, value)
result = result.Add(result, polynomial[s])
result = result.Mod(result, prime)
}
return result
}
/**
* inNumbers(array, value) returns boolean whether or not value is in array
**/
func inNumbers(numbers []*big.Int, value *big.Int) bool {
for n := range numbers {
if numbers[n].Cmp(value) == 0 {
return true
}
}
return false
}
/**
* Returns the big.Int number base10 in base64 representation; note: this is
* not a string representation; the base64 output is exactly 256 bits long
**/
func toBase64(number *big.Int) string {
hexdata := fmt.Sprintf("%x", number)
for i := 0; len(hexdata) < 64; i++ {
hexdata = "0" + hexdata
}
bytedata, success := hex.DecodeString(hexdata)
if success != nil {
fmt.Println("Error!")
fmt.Println("hexdata: ", hexdata)
fmt.Println("bytedata: ", bytedata)
fmt.Println(success)
}
return base64.URLEncoding.EncodeToString(bytedata)
}
/**
* Returns the number base64 in base 10 big.Int representation; note: this is
* not coming from a string representation; the base64 input is exactly 256
* bits long, and the output is an arbitrary size base 10 integer.
*
* Returns -1 on failure
**/
func fromBase64(number string) *big.Int {
bytedata, err := base64.URLEncoding.DecodeString(number)
if err != nil {
return big.NewInt(-1)
}
hexdata := hex.EncodeToString(bytedata)
result, ok := big.NewInt(0).SetString(hexdata, 16)
if ok == false {
return big.NewInt(-1)
}
return result
}
/**
* Computes the multiplicative inverse of the number on the field prime; more
* specifically, number * inverse == 1; Note: number should never be zero
**/
func modInverse(number *big.Int) *big.Int {
copy := big.NewInt(0).Set(number)
copy = copy.Mod(copy, prime)
pcopy := big.NewInt(0).Set(prime)
x := big.NewInt(0)
y := big.NewInt(0)
copy.GCD(x, y, pcopy, copy)
result := big.NewInt(0).Set(prime)
result = result.Add(result, y)
result = result.Mod(result, prime)
return result
}