-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
91 lines (80 loc) · 2.25 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
package tcecdsa
import (
"crypto/elliptic"
"crypto/rand"
"encoding/asn1"
"fmt"
"io"
"math/big"
)
var zero = new(big.Int)
var one = new(big.Int).SetInt64(1)
type signature struct {
r, s *big.Int
}
// RandomFieldElement returns A random element of the field underlying the given
// curve using the procedure given in [NSA] A.2.1.
// Taken from Golang ECDSA implementation
func RandomFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
params := c.Params()
b := make([]byte, params.BitSize/8+8)
_, err = io.ReadFull(rand, b)
if err != nil {
return
}
k = new(big.Int).SetBytes(b)
n := new(big.Int).Sub(params.N, one)
k.Mod(k, n)
k.Add(k, one)
return
}
// RandomInRange returns a number between an interval [min, max).
func RandomInRange(min, max *big.Int, randSource io.Reader) (r *big.Int, err error) {
if min.Cmp(max) >= 0 {
err = fmt.Errorf("min is equal or more than max")
return
}
sub := new(big.Int).Sub(max, min)
r, err = rand.Int(randSource, sub)
if err != nil {
return
}
r.Add(r, min)
return
}
// HashToInt converts a hash value to an integer. There is some disagreement
// about how this is done. [NSA] suggests that this is done in the obvious
// manner, but [SECG] truncates the hash to the bit-length of the curve order
// first. We follow [SECG] because that's what OpenSSL does. Additionally,
// OpenSSL right shifts excess bits from the number if the hash is too large
// and we mirror that too.
// This function was borrowed from crypto/ecdsa package, and was copied because
// it was not exported, but it is used on ecdsa signatures in Go.
func HashToInt(hash []byte, c elliptic.Curve) *big.Int {
orderBits := c.Params().N.BitLen()
orderBytes := (orderBits + 7) / 8
if len(hash) > orderBytes {
hash = hash[:orderBytes]
}
ret := new(big.Int).SetBytes(hash)
excess := len(hash)*8 - orderBits
if excess > 0 {
ret.Rsh(ret, uint(excess))
}
return ret
}
func MarshalSignature(r, s *big.Int) ([]byte, error) {
return asn1.Marshal(&signature{r, s})
}
func UnmarshalSignature(sigByte []byte) (r, s *big.Int, err error) {
var sig signature
rest, err := asn1.Unmarshal(sigByte, &sig)
if len(rest) > 0 {
return nil, nil, fmt.Errorf("rest should be empty")
}
if err != nil {
return
}
r, s = sig.r, sig.s
return
}