-
Notifications
You must be signed in to change notification settings - Fork 6
/
commitment.go
130 lines (103 loc) · 3.38 KB
/
commitment.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
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
// https://spdx.org/licenses/MIT.html
package frost
import (
"errors"
"fmt"
"slices"
group "github.com/bytemare/crypto"
"github.com/bytemare/frost/internal"
)
var errDecodeCommitmentLength = errors.New("failed to decode commitment: invalid length")
// Commitment is a participant's one-time commitment holding its identifier, and hiding and binding nonces.
type Commitment struct {
Identifier *group.Scalar
HidingNonce *group.Element
BindingNonce *group.Element
}
// Encode returns the serialized byte encoding of a participant's commitment.
func (c Commitment) Encode() []byte {
id := c.Identifier.Encode()
hNonce := c.HidingNonce.Encode()
bNonce := c.BindingNonce.Encode()
out := make([]byte, len(id)+len(hNonce)+len(bNonce))
copy(out, id)
copy(out[len(id):], hNonce)
copy(out[len(id)+len(hNonce):], bNonce)
return out
}
// DecodeCommitment attempts to deserialize the encoded commitment given as input, and to return it.
func DecodeCommitment(cs Ciphersuite, data []byte) (*Commitment, error) {
g := cs.Configuration().Ciphersuite.Group
scalarLength := g.ScalarLength()
elementLength := g.ElementLength()
if len(data) != scalarLength+2*elementLength {
return nil, errDecodeCommitmentLength
}
c := &Commitment{
Identifier: g.NewScalar(),
HidingNonce: g.NewElement(),
BindingNonce: g.NewElement(),
}
if err := c.Identifier.Decode(data[:scalarLength]); err != nil {
return nil, fmt.Errorf("failed to decode commitment identifier: %w", err)
}
if err := c.HidingNonce.Decode(data[:scalarLength]); err != nil {
return nil, fmt.Errorf("failed to decode commitment hiding nonce: %w", err)
}
if err := c.BindingNonce.Decode(data[:scalarLength]); err != nil {
return nil, fmt.Errorf("failed to decode commitment binding nonce: %w", err)
}
return c, nil
}
// CommitmentList is a sortable list of commitments.
type CommitmentList []*Commitment
func cmpID(a, b *Commitment) int {
switch {
case a.Identifier.Equal(b.Identifier) == 1: // a == b
return 0
case a.Identifier.LessOrEqual(b.Identifier) == 1: // a < b
return -1
default:
return 1
}
}
// Sort sorts the list the ascending order of identifiers.
func (c CommitmentList) Sort() {
slices.SortFunc(c, cmpID)
}
// IsSorted returns whether the list is sorted in ascending order by identifier.
func (c CommitmentList) IsSorted() bool {
return slices.IsSortedFunc(c, cmpID)
}
// Encode serializes a whole commitment list.
func (c CommitmentList) Encode() []byte {
var encoded []byte
for _, l := range c {
e := internal.Concatenate(l.Identifier.Encode(), l.HidingNonce.Encode(), l.BindingNonce.Encode())
encoded = append(encoded, e...)
}
return encoded
}
// Participants returns the list of participants in the commitment list.
func (c CommitmentList) Participants() []*group.Scalar {
identifiers := make([]*group.Scalar, len(c))
for i, l := range c {
identifiers[i] = l.Identifier
}
return identifiers
}
// Get returns the commitment of the participant with the corresponding identifier, or nil if it was not found.
func (c CommitmentList) Get(identifier *group.Scalar) *Commitment {
for _, com := range c {
if com.Identifier.Equal(identifier) == 1 {
return com
}
}
return nil
}