forked from taurushq-io/multi-party-sig
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pedersen.go
127 lines (106 loc) · 3.16 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
package pedersen
import (
"fmt"
"io"
"github.com/cronokirby/saferith"
"github.com/taurusgroup/multi-party-sig/internal/params"
"github.com/taurusgroup/multi-party-sig/pkg/math/arith"
)
type Error string
const (
ErrNilFields Error = "contains nil field"
ErrSEqualT Error = "S cannot be equal to T"
ErrNotValidModN Error = "S and T must be in [1,…,N-1] and coprime to N"
)
func (e Error) Error() string {
return fmt.Sprintf("pedersen: %s", string(e))
}
type Parameters struct {
n *arith.Modulus
s, t *saferith.Nat
}
// New returns a new set of Pedersen parameters.
// Assumes ValidateParameters(n, s, t) returns nil.
func New(n *arith.Modulus, s, t *saferith.Nat) *Parameters {
return &Parameters{
s: s,
t: t,
n: n,
}
}
// ValidateParameters check n, s and t, and returns an error if any of the following is true:
// - n, s, or t is nil.
// - s, t are not in [1, …,n-1].
// - s, t are not coprime to N.
// - s = t.
func ValidateParameters(n *saferith.Modulus, s, t *saferith.Nat) error {
if n == nil || s == nil || t == nil {
return ErrNilFields
}
// s, t ∈ ℤₙˣ
if !arith.IsValidNatModN(n, s, t) {
return ErrNotValidModN
}
// s ≡ t
if _, eq, _ := s.Cmp(t); eq == 1 {
return ErrSEqualT
}
return nil
}
// N = p•q, p ≡ q ≡ 3 mod 4.
func (p Parameters) N() *saferith.Modulus { return p.n.Modulus }
// N, but as an arith modulus, which is sometimes useful
func (p Parameters) NArith() *arith.Modulus { return p.n }
// S = r² mod N.
func (p Parameters) S() *saferith.Nat { return p.s }
// T = Sˡ mod N.
func (p Parameters) T() *saferith.Nat { return p.t }
// Commit computes sˣ tʸ (mod N)
//
// x and y are taken as saferith.Int, because we want to keep these values in secret,
// in general. The commitment produced, on the other hand, hides their values,
// and can be safely shared.
func (p Parameters) Commit(x, y *saferith.Int) *saferith.Nat {
sx := p.n.ExpI(p.s, x)
ty := p.n.ExpI(p.t, y)
result := sx.ModMul(sx, ty, p.n.Modulus)
return result
}
// Verify returns true if sᵃ tᵇ ≡ S Tᵉ (mod N).
func (p Parameters) Verify(a, b, e *saferith.Int, S, T *saferith.Nat) bool {
if a == nil || b == nil || S == nil || T == nil || e == nil {
return false
}
nMod := p.n.Modulus
if !arith.IsValidNatModN(nMod, S, T) {
return false
}
sa := p.n.ExpI(p.s, a) // sᵃ (mod N)
tb := p.n.ExpI(p.t, b) // tᵇ (mod N)
lhs := sa.ModMul(sa, tb, nMod) // lhs = sᵃ⋅tᵇ (mod N)
te := p.n.ExpI(T, e) // Tᵉ (mod N)
rhs := te.ModMul(te, S, nMod) // rhs = S⋅Tᵉ (mod N)
return lhs.Eq(rhs) == 1
}
// WriteTo implements io.WriterTo and should be used within the hash.Hash function.
func (p *Parameters) WriteTo(w io.Writer) (int64, error) {
if p == nil {
return 0, io.ErrUnexpectedEOF
}
nAll := int64(0)
buf := make([]byte, params.BytesIntModN)
// write N, S, T
for _, i := range []*saferith.Nat{p.n.Nat(), p.s, p.t} {
i.FillBytes(buf)
n, err := w.Write(buf)
nAll += int64(n)
if err != nil {
return nAll, err
}
}
return nAll, nil
}
// Domain implements hash.WriterToWithDomain, and separates this type within hash.Hash.
func (Parameters) Domain() string {
return "Pedersen Parameters"
}