85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
package starkware
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"math/big"
|
|
"strings"
|
|
)
|
|
|
|
func GenerateKRfc6979(msgHash, priKey *big.Int, seed int) *big.Int {
|
|
msgHash = big.NewInt(0).Set(msgHash) // copy
|
|
bitMod := msgHash.BitLen() % 8
|
|
if bitMod <= 4 && bitMod >= 1 && msgHash.BitLen() > 248 {
|
|
msgHash.Mul(msgHash, big.NewInt(16))
|
|
}
|
|
var extra []byte
|
|
if seed > 0 {
|
|
buf := new(bytes.Buffer)
|
|
var data interface{}
|
|
if seed < 256 {
|
|
data = uint8(seed)
|
|
} else if seed < 65536 {
|
|
data = uint16(seed)
|
|
} else if seed < 4294967296 {
|
|
data = uint32(seed)
|
|
} else {
|
|
data = uint64(seed)
|
|
}
|
|
_ = binary.Write(buf, binary.BigEndian, data)
|
|
extra = buf.Bytes()
|
|
}
|
|
return generateSecret(EcOrder, priKey, sha256.New, msgHash.Bytes(), extra)
|
|
}
|
|
|
|
type Signature struct {
|
|
R string `json:"r"`
|
|
S string `json:"s"`
|
|
}
|
|
|
|
func Sign(messageHash string, privateKey string) Signature {
|
|
if strings.HasPrefix(privateKey, "0x") {
|
|
privateKey = privateKey[2:]
|
|
}
|
|
privKey, _ := new(big.Int).SetString(privateKey, 16)
|
|
msgHash, _ := new(big.Int).SetString(messageHash, 10)
|
|
seed := 0
|
|
EcGen := pedersenCfg.ConstantPoints[1]
|
|
alpha := pedersenCfg.ALPHA
|
|
nBit := big.NewInt(0).Exp(big.NewInt(2), NElementBitsEcdsa, nil)
|
|
for {
|
|
k := GenerateKRfc6979(msgHash, privKey, seed)
|
|
// Update seed for next iteration in case the value of k is bad.
|
|
if seed == 0 {
|
|
seed = 1
|
|
} else {
|
|
seed += 1
|
|
}
|
|
// Cannot fail because 0 < k < EC_ORDER and EC_ORDER is prime.
|
|
x := ecMult(k, EcGen, alpha, FieldPrime)[0]
|
|
// !(1 <= x < 2 ** N_ELEMENT_BITS_ECDSA)
|
|
if !(x.Cmp(one) > 0 && x.Cmp(nBit) < 0) {
|
|
continue
|
|
}
|
|
// msg_hash + r * priv_key
|
|
x1 := big.NewInt(0).Add(msgHash, big.NewInt(0).Mul(x, privKey))
|
|
// (msg_hash + r * priv_key) % EC_ORDER == 0
|
|
if big.NewInt(0).Mod(x1, EcOrder).Cmp(zero) == 0 {
|
|
continue
|
|
}
|
|
// w = div_mod(k, msg_hash + r * priv_key, EC_ORDER)
|
|
w := divMod(k, x1, EcOrder)
|
|
// not (1 <= w < 2 ** N_ELEMENT_BITS_ECDSA)
|
|
if !(w.Cmp(one) > 0 && w.Cmp(nBit) < 0) {
|
|
continue
|
|
}
|
|
s1 := divMod(one, w, EcOrder)
|
|
return Signature{
|
|
R: "0x" + fmt.Sprintf("%x", x),
|
|
S: "0x" + fmt.Sprintf("%x", s1),
|
|
}
|
|
}
|
|
}
|