forked from scorum/bitshares-go
/
ecdsa.go
81 lines (67 loc) · 2 KB
/
ecdsa.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
package rfc6979
import (
"crypto/ecdsa"
"crypto/elliptic"
"hash"
"math/big"
//"log"
//"encoding/hex"
)
// SignECDSA signs an arbitrary length hash (which should be the result of
// hashing a larger message) using the private key, priv. It returns the
// signature as a pair of integers.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
func SignECDSA(priv *ecdsa.PrivateKey, hash []byte, alg func() hash.Hash, nonce int) (r, s *big.Int, err error) {
c := priv.PublicKey.Curve
N := c.Params().N
//log.Println("e=", hex.EncodeToString(hash)) // OK
//log.Println("N=", hex.EncodeToString(N.Bytes())) // OK
var hash_clone = make([]byte, len(hash))
copy(hash_clone, hash)
//log.Println("generateSecret- nonce=", nonce)
generateSecret(priv /* N, priv.D, */, alg, hash_clone, func(k *big.Int) bool {
inv := new(big.Int).ModInverse(k, N)
r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
r.Mod(r, N)
if r.Sign() == 0 {
//log.Println("r.Sign() == 0")
return false
}
e := hashToInt(hash_clone, c)
s = new(big.Int).Mul(priv.D, r)
s.Add(s, e)
s.Mul(s, inv)
s.Mod(s, N)
if s.Sign() == 0 {
//log.Println("s.Sign() == 0")
return false
}
return true
}, nonce)
//log.Println("enforce low S values, see bip62: 'low s values in signatures'");
// enforce low S values, see bip62: 'low s values in signatures'
N_OVER_TWO := new(big.Int).Div(N, big.NewInt(2))
if s.Cmp(N_OVER_TWO) > 0 {
s = new(big.Int).Sub(N, s)
}
return
}
// copied from crypto/ecdsa
func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
var hash_clone = make([]byte, len(hash))
copy(hash_clone, hash)
orderBits := c.Params().N.BitLen()
orderBytes := (orderBits + 7) / 8
if len(hash_clone) > orderBytes {
hash_clone = hash_clone[:orderBytes]
}
ret := new(big.Int).SetBytes(hash_clone)
excess := len(hash_clone)*8 - orderBits
if excess > 0 {
ret.Rsh(ret, uint(excess))
}
return ret
}