github.com/cranelv/ethereum_mpc@v0.0.0-20191031014521-23aeb1415092/mpcService/crypto/mpc_functions.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/rand"
     6  	"errors"
     7  	"math/big"
     8  	"github.com/ethereum/go-ethereum/crypto"
     9  	"github.com/ethereum/go-ethereum/common/math"
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/ethereum/go-ethereum/log"
    12  	"crypto/elliptic"
    13  	"io"
    14  )
    15  var (
    16  	Secp256k1N, _  = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
    17  	Secp256k1halfN = new(big.Int).Div(Secp256k1N, big.NewInt(2))
    18  	one = new(big.Int).SetInt64(1)
    19  )
    20  func UintRand(MaxValue uint64) (uint64, error) {
    21  	num, err := rand.Int(rand.Reader, new(big.Int).SetUint64(MaxValue))
    22  	if err != nil {
    23  		return 0, err
    24  	}
    25  
    26  	return num.Uint64(), nil
    27  }
    28  // randFieldElement returns a random element of the field underlying the given
    29  // curve using the procedure given in [NSA] A.2.1.
    30  func RandFieldElement(c elliptic.Curve,) (k *big.Int, err error) {
    31  	params := c.Params()
    32  	b := make([]byte, params.BitSize/8+8)
    33  	_, err = io.ReadFull(rand.Reader, b)
    34  	if err != nil {
    35  		return
    36  	}
    37  
    38  	k = new(big.Int).SetBytes(b)
    39  	n := new(big.Int).Sub(params.N, one)
    40  	k.Mod(k, n)
    41  	k.Add(k, one)
    42  	return
    43  }
    44  
    45  func GetRandCoefficients(num int) ([]*big.Int, error) {
    46  	randCoefficient := make([]*big.Int, num)
    47  	for i := 0; i < num; i++ {
    48  		key, err := RandFieldElement(crypto.S256())
    49  		if err != nil {
    50  			return nil, err
    51  		}
    52  		randCoefficient[i] = key
    53  	}
    54  
    55  	return randCoefficient, nil
    56  }
    57  
    58  func EvaluatePoly(coefficient []*big.Int, x *big.Int) *big.Int {
    59  	degree := len(coefficient) - 1
    60  	sumx := make([]big.Int, degree+1)
    61  	for i := 0; i <= degree; i++ {
    62  		sumx[i].Set(coefficient[i])
    63  	}
    64  
    65  	for i := 1; i <= degree; i++ {
    66  		for j := i; j <= degree; j++ {
    67  			sumx[j].Mul(&sumx[j], x)
    68  			sumx[j].Mod(&sumx[j], Secp256k1N)
    69  		}
    70  	}
    71  
    72  	sum := big.NewInt(0)
    73  	for i := 0; i < len(sumx); i++ {
    74  		sum.Add(sum, &sumx[i])
    75  		sum.Mod(sum, Secp256k1N)
    76  	}
    77  
    78  	return sum
    79  }
    80  
    81  func evaluateB(x []*big.Int) []*big.Int {
    82  	k := len(x)
    83  	b := make([]*big.Int, k)
    84  	for i := 0; i < k; i++ {
    85  		b[i] = evaluateb(x, i)
    86  	}
    87  
    88  	return b
    89  }
    90  
    91  func evaluateb(x []*big.Int, i int) *big.Int {
    92  	k := len(x)
    93  	sum := big.NewInt(1)
    94  	temp1 := big.NewInt(1)
    95  	temp2 := big.NewInt(1)
    96  	for j := 0; j < k; j++ {
    97  		if j != i {
    98  			temp1.Sub(x[j], x[i])
    99  			temp1.ModInverse(temp1, Secp256k1N)
   100  			temp2.Mul(x[j], temp1)
   101  			sum.Mul(sum, temp2)
   102  			sum.Mod(sum, Secp256k1N)
   103  		} else {
   104  			continue
   105  		}
   106  	}
   107  
   108  	return sum
   109  }
   110  
   111  // Lagrange's polynomial interpolation algorithm
   112  func Lagrange(f []*big.Int, x []*big.Int) *big.Int {
   113  	degree := len(x) - 1
   114  	b := evaluateB(x)
   115  	s := big.NewInt(0)
   116  	temp1 := big.NewInt(1)
   117  
   118  	for i := 0; i < degree+1; i++ {
   119  		temp1.Mul(f[i], b[i])
   120  		s.Add(s, temp1)
   121  		s.Mod(s, Secp256k1N)
   122  	}
   123  
   124  	return s
   125  }
   126  
   127  func TransSignature(R *big.Int, S *big.Int, V uint64) ([]byte, error) {
   128  	if S.Cmp(new(big.Int).Div(Secp256k1N, big.NewInt(2))) > 0 {
   129  		V ^= 1
   130  		S.Sub(Secp256k1N,S)
   131  	}
   132  
   133  	sig := make([]byte, 65)
   134  	copy(sig[:], math.PaddedBigBytes(R, 32))
   135  	copy(sig[32:], math.PaddedBigBytes(S, 32))
   136  	sig[64] = byte(V)
   137  	return sig, nil
   138  }
   139  
   140  func SenderEcrecover(sighash, sig []byte) (common.Address, error) {
   141  	log.Info("SenderEcrecover, sigHash:%s, sig:%s", common.ToHex(sighash), common.ToHex(sig))
   142  
   143  	pub, err := crypto.Ecrecover(sighash, sig)
   144  	if err != nil {
   145  		log.Error("SenderEcrecover, crypto Ecrecover fail, err:%s", err.Error())
   146  		return common.Address{}, err
   147  	}
   148  	if len(pub) == 0 || pub[0] != 4 {
   149  		log.Error("SenderEcrecover, pub's value isn't zero in first byte")
   150  		return common.Address{}, errors.New("invalid public key")
   151  	}
   152  	var addr common.Address
   153  	copy(addr[:], crypto.Keccak256(pub[1:])[12:])
   154  	return addr, nil
   155  }
   156  
   157  func ValidatePublicKey(k *ecdsa.PublicKey) bool {
   158  	return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0
   159  }
   160  
   161  func ValidatePrivateKey(k *big.Int) bool {
   162  	if k == nil || k.Sign() == 0 {
   163  		return false
   164  	}
   165  
   166  	return true
   167  }