-
Notifications
You must be signed in to change notification settings - Fork 1
/
multisig_test.go
225 lines (193 loc) · 8.66 KB
/
multisig_test.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// Copyright (C) 2019 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// go-algorand is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
package crypto
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func MultisigSigPrint(sig MultisigSig) {
fmt.Println("version", sig.Version)
fmt.Println("threshold", sig.Threshold)
fmt.Println("number of keys", len(sig.Subsigs))
for i := 0; i < len(sig.Subsigs); i++ {
fmt.Println("the ", i, "th key/sig pair")
fmt.Println(sig.Subsigs[i].Key)
fmt.Println(sig.Subsigs[i].Sig)
}
}
// test cases for address generation
// detect invalid threshold and versions
//
func TestMultisigAddr(t *testing.T) {
var s Seed
var userkeypair []*SecretKey
var pk []PublicKey
var err error
version := uint8(1)
threshold := uint8(3)
userkeypair = make([]*SecretKey, 4)
for i := 0; i < 4; i++ {
RandBytes(s[:])
userkeypair[i] = GenerateSignatureSecrets(s)
}
pk = make([]PublicKey, 2)
pk[0] = userkeypair[0].SignatureVerifier
pk[1] = userkeypair[1].SignatureVerifier
// test if invalid threshold can be detected
// #keys= 2 < threshold = 3
_, err = MultisigAddrGen(version, threshold, pk)
require.Error(t, err, "MultisigAddr: unable to detect invalid threshold (keys == %d, threshold == %d)", len(pk), threshold)
// #keys = 3 == threshold = 3
pk = append(pk, userkeypair[2].SignatureVerifier)
_, err = MultisigAddrGen(version, threshold, pk)
require.NoError(t, err, "MultisigAddr: unexpected failure generating message digest with %d keys and a threshold of %d", len(pk), threshold)
// #keys = 4 > threshold = 3
pk = append(pk, userkeypair[3].SignatureVerifier)
_, err = MultisigAddrGen(version, threshold, pk)
require.NoError(t, err, "MultisigAddr: unexpected failure generating message digest with %d keys and a threshold of %d", len(pk), threshold)
}
// this test generates a set of 4 public keys for a threshold of 3
// signs with 3 keys to get 3 signatures
// assembles 3 signatures, verify the msig
func TestMultisig(t *testing.T) {
var msig MultisigSig
var sigs []MultisigSig
var s Seed
var userkeypair []*SecretKey
var pk []PublicKey
var err error
var addr Digest
version := uint8(1)
threshold := uint8(3)
txid := TestingHashable{[]byte("test: txid 1000")}
userkeypair = make([]*SecretKey, 5)
for i := 0; i < 5; i++ {
RandBytes(s[:])
userkeypair[i] = GenerateSignatureSecrets(s)
}
// addr = hash (... |pk0|pk1|pk2|pk3), pk4 is not included
pk = make([]PublicKey, 4)
pk[0] = userkeypair[0].SignatureVerifier
pk[1] = userkeypair[1].SignatureVerifier
pk[2] = userkeypair[2].SignatureVerifier
pk[3] = userkeypair[3].SignatureVerifier
addr, err = MultisigAddrGen(version, threshold, pk)
require.NoError(t, err, "Multisig: unexpected failure generating message digest")
// now testing signing functions
// check if invalid version can be detected
_, err = MultisigSign(txid, addr, version+1, threshold, pk, *userkeypair[0])
require.Error(t, err, "should be able to detect invalid version number")
// check if invalid secret key can be detected
_, err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[4])
require.Error(t, err, "should be able to detect invalid secret key used")
// test assembling
// test1: assemble a single signature -- should return failure
sigs = make([]MultisigSig, 1)
sigs[0], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[3])
require.NoError(t, err, "Multisig: unexpected failure in multisig signing")
_, err = MultisigAssemble(sigs)
require.Error(t, err, "should be able to detect insufficient signatures for assembling")
// test2: assemble 3 signatures
// signing three signatures with pk0, pk1 and pk2
sigs = make([]MultisigSig, 3)
sigs[0], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[0])
require.NoError(t, err, "Multisig: unexpected failure in generating sig from pk 0")
sigs[1], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[1])
require.NoError(t, err, "Multisig: unexpected failure in generating sig from pk 1")
sigs[2], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[2])
require.NoError(t, err, "Multisig: unexpected failure in generating sig from pk 2")
msig, err = MultisigAssemble(sigs)
require.NoError(t, err, "Multisig: unexpected failure when assembling multisig")
verify, err := MultisigVerify(txid, addr, msig)
require.True(t, verify, "Multisig: verification failed, verify flag was false")
require.NoError(t, err, "Multisig: unexpected verification failure with err")
}
// test multisig merge functions
// 1. assembles 2 signatures, adds a 3rd one to form msig1
// 2. verifies msig1
// 3. assembles 4th and 5th to get msig2
// 4. merge msig1 and msig2
// 5. verify the merged one
func TestMultisigAddAndMerge(t *testing.T) {
var msig1 MultisigSig
var msig2 MultisigSig
var sigs []MultisigSig
var s Seed
var userkeypair []*SecretKey
var pk []PublicKey
var err error
var addr Digest
version := uint8(1)
threshold := uint8(3)
txid := TestingHashable{[]byte("test: txid 1000")}
userkeypair = make([]*SecretKey, 5)
RandBytes(s[:])
pk = make([]PublicKey, 5)
for i := 0; i < 5; i++ {
userkeypair[i] = GenerateSignatureSecrets(s)
pk[i] = userkeypair[i].SignatureVerifier
}
// addr = hash (... |pk0|pk1|pk2|pk3|pk4)
addr, err = MultisigAddrGen(version, threshold, pk)
require.NoError(t, err, "Multisig: unexpected failure generating message digest")
// msig1 = {sig0,sig1}
sigs = make([]MultisigSig, 2)
sigs[0], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[0])
require.NoError(t, err, "Multisig: unexpected failure signing with pk 0")
sigs[1], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[1])
require.NoError(t, err, "Multisig: unexpected failure signing with pk 1")
msig1, err = MultisigAssemble(sigs)
require.NoError(t, err, "Multisig: unexpected failure assembling message from signatures 0 and 1")
// add sig3 to msig and then verify
sigs = make([]MultisigSig, 1)
sigs[0], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[2])
require.NoError(t, err, "Multisig: unexpected failure signing with pk 2")
err = MultisigAdd(sigs, &msig1)
require.NoError(t, err, "Multisig: unexpected err adding pk 2 signature to that of pk 0 and 1")
verify, err := MultisigVerify(txid, addr, msig1)
require.True(t, verify, "Multisig: verification failed, verify flag was false")
require.NoError(t, err, "Multisig: unexpected verification failure with err")
// msig2 = {sig3, sig4}
sigs = make([]MultisigSig, 2)
sigs[0], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[3])
require.NoError(t, err, "Multisig: unexpected failure signing with pk 3")
sigs[1], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[4])
require.NoError(t, err, "Multisig: unexpected failure signing with pk 4")
msig2, err = MultisigAssemble(sigs)
require.NoError(t, err, "Multisig: unexpected failure assembling message from signatures 3 and 4")
// merge two msigs and then verify
msigt, err := MultisigMerge(msig1, msig2)
require.NoError(t, err, "Multisig: unexpected failure merging multisig messages {0, 1, 2} and {3, 4}")
verify, err = MultisigVerify(txid, addr, msigt)
require.True(t, verify, "Multisig: verification failed, verify flag was false")
require.NoError(t, err, "Multisig: unexpected verification failure with err")
// create a valid duplicate on purpose
// msig1 = {sig0, sig1, sig2}
// msig2 = {sig2, sig3, sig4}
// then verify the merged signature
sigs = make([]MultisigSig, 1)
sigs[0], err = MultisigSign(txid, addr, version, threshold, pk, *userkeypair[2])
require.NoError(t, err, "Multisig: unexpected failure signing with pk 2")
err = MultisigAdd(sigs, &msig2)
require.NoError(t, err, "Multisig: unexpected failure adding pk 2 signature to that of pk 3 and 4")
msigt, err = MultisigMerge(msig1, msig2)
require.NoError(t, err, "Multisig: unexpected failure merging multisig messages {0, 1, 2} and {2, 3, 4}")
verify, err = MultisigVerify(txid, addr, msigt)
require.True(t, verify, "Multisig: verification failed, verify flag was false")
require.NoError(t, err, "Multisig: unexpected verification failure with err")
return
}