diff --git a/group.go b/group.go index 538300ffe..130cb57fe 100644 --- a/group.go +++ b/group.go @@ -35,6 +35,9 @@ type Scalar interface { // SetInt64 sets the receiver to a small integer value. SetInt64(v int64) Scalar + // SetIntString sets the receiver to a string encoded integer value. + SetIntString(v string) (Scalar, error) + // Set to the additive identity (0). Zero() Scalar diff --git a/group/edwards25519/scalar.go b/group/edwards25519/scalar.go index c295a5d5f..2a44b9ac7 100644 --- a/group/edwards25519/scalar.go +++ b/group/edwards25519/scalar.go @@ -59,6 +59,14 @@ func (s *scalar) SetInt64(v int64) kyber.Scalar { return s.setInt(mod.NewInt64(v, primeOrder)) } +func (s *scalar) SetIntString(v string) (kyber.Scalar, error) { + i, ok := new(big.Int).SetString(v, 0) + if !ok { + return nil, errors.New("invalid scalar string") + } + return s.setInt(mod.NewInt(i, primeOrder)), nil +} + func (s *scalar) toInt() *mod.Int { return mod.NewIntBytes(s.v[:], primeOrder, defaultEndianess) } diff --git a/group/mod/int.go b/group/mod/int.go index 741b5ca0e..a8d969414 100644 --- a/group/mod/int.go +++ b/group/mod/int.go @@ -6,6 +6,7 @@ import ( "crypto/cipher" "encoding/hex" "errors" + "fmt" "io" "math/big" @@ -173,6 +174,15 @@ func (i *Int) SetInt64(v int64) kyber.Scalar { return i } +func (i *Int) SetIntString(v string) (kyber.Scalar, error) { + bigV := new(big.Int) + bigV, ok := bigV.SetString(v, 0) + if !ok { + return nil, fmt.Errorf("unable to set string number: %v", v) + } + return i.Init(bigV, i.M), nil +} + // Int64 returns the int64 representation of the value. // If the value is not representable in an int64 the result is undefined. func (i *Int) Int64() int64 { diff --git a/pairing/bls12381/circl/scalar.go b/pairing/bls12381/circl/scalar.go index 17046ae44..f4d7e284f 100644 --- a/pairing/bls12381/circl/scalar.go +++ b/pairing/bls12381/circl/scalar.go @@ -2,6 +2,7 @@ package circl import ( "crypto/cipher" + "fmt" "io" "math/big" @@ -62,6 +63,14 @@ func (s *Scalar) SetInt64(v int64) kyber.Scalar { return s } +func (s *Scalar) SetIntString(v string) (kyber.Scalar, error) { + err := s.inner.SetString(v) + if err != nil { + return nil, fmt.Errorf("unable to set string number: %v", err) + } + return s, nil +} + func (s *Scalar) Zero() kyber.Scalar { s.inner.SetUint64(0); return s } func (s *Scalar) Add(a, b kyber.Scalar) kyber.Scalar { diff --git a/share/vss/pedersen/vss_test.go b/share/vss/pedersen/vss_test.go index ec903bbea..697e48a4e 100644 --- a/share/vss/pedersen/vss_test.go +++ b/share/vss/pedersen/vss_test.go @@ -64,7 +64,10 @@ func TestMinimumT(t *testing.T) { func TestVSSWhole(t *testing.T) { dealer, verifiers := genAll() + vssWhole(t, dealer, verifiers, secret) +} +func vssWhole(t *testing.T, dealer *Dealer, verifiers []*Verifier, secret kyber.Scalar) { // 1. dispatch deal resps := make([]*Response, nbVerifiers) encDeals, err := dealer.EncryptedDeals() @@ -591,6 +594,15 @@ func TestVSSContext(t *testing.T) { assert.Len(t, c, suite.Hash().Size()) } +func TestDeterministicStringSecret(t *testing.T) { + deterministicSec, err := suite.Scalar().SetIntString("0x123456789abcdef") + require.NoError(t, err) + dealer, err := NewDealer(suite, dealerSec, deterministicSec, verifiersPub, vssThreshold) + require.NoError(t, err) + verifiers := genVerifiers() + vssWhole(t, dealer, verifiers, deterministicSec) +} + func genPair() (kyber.Scalar, kyber.Point) { secret := suite.Scalar().Pick(suite.RandomStream()) public := suite.Point().Mul(secret, nil) @@ -612,13 +624,16 @@ func genDealer() *Dealer { } func genAll() (*Dealer, []*Verifier) { - dealer := genDealer() + return genDealer(), genVerifiers() +} + +func genVerifiers() []*Verifier { var verifiers = make([]*Verifier, nbVerifiers) for i := 0; i < nbVerifiers; i++ { v, _ := NewVerifier(suite, verifiersSec[i], dealerPub, verifiersPub) verifiers[i] = v } - return dealer, verifiers + return verifiers } func randomBytes(n int) []byte {