-
Notifications
You must be signed in to change notification settings - Fork 1
/
pedersen.go
152 lines (131 loc) · 3.99 KB
/
pedersen.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// Copyright Coinbase, Inc. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
package sharing
import (
"fmt"
"io"
"github.com/coinbase/kryptology/pkg/core/curves"
)
// Pedersen Verifiable Secret Sharing Scheme
type Pedersen struct {
threshold, limit uint32
curve *curves.Curve
generator curves.Point
}
type PedersenVerifier struct {
Generator curves.Point
Commitments []curves.Point
}
func (pv PedersenVerifier) Verify(share, blindShare *ShamirShare) error {
curve := curves.GetCurveByName(pv.Generator.CurveName())
if err := share.Validate(curve); err != nil {
return err
}
if err := blindShare.Validate(curve); err != nil {
return err
}
x := curve.Scalar.New(int(share.Id))
i := curve.Scalar.One()
rhs := pv.Commitments[0]
for j := 1; j < len(pv.Commitments); j++ {
i = i.Mul(x)
rhs = rhs.Add(pv.Commitments[j].Mul(i))
}
sc, _ := curve.Scalar.SetBytes(share.Value)
bsc, _ := curve.Scalar.SetBytes(blindShare.Value)
g := pv.Commitments[0].Generator().Mul(sc)
h := pv.Generator.Mul(bsc)
lhs := g.Add(h)
if lhs.Equal(rhs) {
return nil
} else {
return fmt.Errorf("not equal")
}
}
// PedersenResult contains all the data from calling Split
type PedersenResult struct {
Blinding curves.Scalar
BlindingShares, SecretShares []*ShamirShare
FeldmanVerifier *FeldmanVerifier
PedersenVerifier *PedersenVerifier
}
// NewPedersen creates a new pedersen VSS
func NewPedersen(threshold, limit uint32, generator curves.Point) (*Pedersen, 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")
}
curve := curves.GetCurveByName(generator.CurveName())
if curve == nil {
return nil, fmt.Errorf("invalid curve")
}
if generator == nil {
return nil, fmt.Errorf("invalid generator")
}
if !generator.IsOnCurve() || generator.IsIdentity() {
return nil, fmt.Errorf("invalid generator")
}
return &Pedersen{threshold, limit, curve, generator}, nil
}
// Split creates the verifiers, blinding and shares
func (pd Pedersen) Split(secret curves.Scalar, reader io.Reader) (*PedersenResult, error) {
// generate a random blinding factor
blinding := pd.curve.Scalar.Random(reader)
shamir := Shamir{pd.threshold, pd.limit, pd.curve}
// split the secret into shares
shares, poly := shamir.getPolyAndShares(secret, reader)
// split the blinding into shares
blindingShares, polyBlinding := shamir.getPolyAndShares(blinding, reader)
// Generate the verifiable commitments to the polynomial for the shares
blindedverifiers := make([]curves.Point, pd.threshold)
verifiers := make([]curves.Point, pd.threshold)
// ({p0 * G + b0 * H}, ...,{pt * G + bt * H})
for i, c := range poly.Coefficients {
s := pd.curve.ScalarBaseMult(c)
b := pd.generator.Mul(polyBlinding.Coefficients[i])
bv := s.Add(b)
blindedverifiers[i] = bv
verifiers[i] = s
}
verifier1 := &FeldmanVerifier{Commitments: verifiers}
verifier2 := &PedersenVerifier{Commitments: blindedverifiers, Generator: pd.generator}
return &PedersenResult{
blinding, blindingShares, shares, verifier1, verifier2,
}, nil
}
func (pd Pedersen) LagrangeCoeffs(shares map[uint32]*ShamirShare) (map[uint32]curves.Scalar, error) {
shamir := &Shamir{
threshold: pd.threshold,
limit: pd.limit,
curve: pd.curve,
}
identities := make([]uint32, 0)
for _, xi := range shares {
identities = append(identities, xi.Id)
}
return shamir.LagrangeCoeffs(identities)
}
func (pd Pedersen) Combine(shares ...*ShamirShare) (curves.Scalar, error) {
shamir := &Shamir{
threshold: pd.threshold,
limit: pd.limit,
curve: pd.curve,
}
return shamir.Combine(shares...)
}
func (pd Pedersen) CombinePoints(shares ...*ShamirShare) (curves.Point, error) {
shamir := &Shamir{
threshold: pd.threshold,
limit: pd.limit,
curve: pd.curve,
}
return shamir.CombinePoints(shares...)
}