// // Copyright Coinbase, Inc. All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // package sharing import ( "fmt" "io" "source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves" ) type FeldmanVerifier struct { Commitments []curves.Point } func (v FeldmanVerifier) Verify(share *ShamirShare) error { curve := curves.GetCurveByName(v.Commitments[0].CurveName()) err := share.Validate(curve) if err != nil { return err } x := curve.Scalar.New(int(share.Id)) i := curve.Scalar.One() rhs := v.Commitments[0] for j := 1; j < len(v.Commitments); j++ { i = i.Mul(x) rhs = rhs.Add(v.Commitments[j].Mul(i)) } sc, _ := curve.Scalar.SetBytes(share.Value) lhs := v.Commitments[0].Generator().Mul(sc) if lhs.Equal(rhs) { return nil } else { return fmt.Errorf("not equal") } } type Feldman struct { Threshold, Limit uint32 Curve *curves.Curve } func NewFeldman(threshold, limit uint32, curve *curves.Curve) (*Feldman, error) { if limit < threshold { return nil, fmt.Errorf("limit cannot be less than threshold") } if threshold < 2 { return nil, fmt.Errorf("threshold cannot be less than 2") } if limit > 255 { return nil, fmt.Errorf("cannot exceed 255 shares") } if curve == nil { return nil, fmt.Errorf("invalid curve") } return &Feldman{threshold, limit, curve}, nil } func (f Feldman) Split(secret curves.Scalar, reader io.Reader) (*FeldmanVerifier, []*ShamirShare, error) { if secret.IsZero() { return nil, nil, fmt.Errorf("invalid secret") } shamir := &Shamir{ threshold: f.Threshold, limit: f.Limit, curve: f.Curve, } shares, poly := shamir.getPolyAndShares(secret, reader) verifier := new(FeldmanVerifier) verifier.Commitments = make([]curves.Point, f.Threshold) for i := range verifier.Commitments { verifier.Commitments[i] = f.Curve.ScalarBaseMult(poly.Coefficients[i]) } return verifier, shares, nil } func (f Feldman) LagrangeCoeffs(shares map[uint32]*ShamirShare) (map[uint32]curves.Scalar, error) { shamir := &Shamir{ threshold: f.Threshold, limit: f.Limit, curve: f.Curve, } identities := make([]uint32, 0) for _, xi := range shares { identities = append(identities, xi.Id) } return shamir.LagrangeCoeffs(identities) } func (f Feldman) Combine(shares ...*ShamirShare) (curves.Scalar, error) { shamir := &Shamir{ threshold: f.Threshold, limit: f.Limit, curve: f.Curve, } return shamir.Combine(shares...) } func (f Feldman) CombinePoints(shares ...*ShamirShare) (curves.Point, error) { shamir := &Shamir{ threshold: f.Threshold, limit: f.Limit, curve: f.Curve, } return shamir.CombinePoints(shares...) }