go-blindsecp256k1/blindsecp256k1_test.go
blindsecp256k1_test.goRaw
1package blindsecp256k1
2
3import (
4 "encoding/hex"
5 "math/big"
6 "testing"
7
8 "github.com/ethereum/go-ethereum/crypto"
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11)
12
13func TestFlow(t *testing.T) {
14 // signer: create new signer key pair
15 sk, err := NewPrivateKey()
16 require.Nil(t, err)
17 signerPubK := sk.Public()
18
19 // signer: when user requests new R parameter to blind a new msg,
20 // create new signerR (public) with its secret k
21 k, signerR, err := NewRequestParameters()
22 require.Nil(t, err)
23
24 // user: blinds the msg using signer's R
25 // msg := new(big.Int).SetBytes([]byte("test"))
26 msg := new(big.Int).SetBytes(crypto.Keccak256([]byte("test")))
27 msgBlinded, userSecretData, err := Blind(msg, signerR)
28 require.Nil(t, err)
29
30 // signer: signs the blinded message using its private key & secret k
31 sBlind, err := sk.BlindSign(msgBlinded, k)
32 require.Nil(t, err)
33
34 // user: unblinds the blinded signature
35 sig := Unblind(sBlind, userSecretData)
36 sigB := sig.Bytes()
37 sig2, err := NewSignatureFromBytes(sigB)
38 assert.Nil(t, err)
39 assert.Equal(t, sig, sig2)
40
41 // signature can be verified with signer PublicKey
42 verified := Verify(msg, sig, signerPubK)
43 assert.True(t, verified)
44}
45
46// func TestSmallBlindedMsg(t *testing.T) {
47// sk, err := NewPrivateKey()
48// require.Nil(t, err)
49// k := big.NewInt(1)
50// smallMsgBlinded := big.NewInt(1)
51//
52// // try to BlindSign a small value
53// _, err = sk.BlindSign(smallMsgBlinded, k)
54// require.NotNil(t, err)
55// require.Equal(t, "mBlinded error: invalid length, need 32 bytes", err.Error())
56// }
57
58func TestHashMOddBytes(t *testing.T) {
59 // This test is made with same values than
60 // https://github.com/arnaucube/blindsecp256k1-js to ensure
61 // compatibility
62 mStr := "3024162961766929396601888431330224482373544644288322432261208139289299439809"
63 m, ok := new(big.Int).SetString(mStr, 10)
64 require.True(t, ok)
65 mBytes := m.Bytes()
66
67 hBytes := crypto.Keccak256(mBytes[3:])
68 h := new(big.Int).SetBytes(hBytes)
69 assert.Equal(t,
70 "57523339312508913023232057765773019244858443678197951618720342803494056599369",
71 h.String())
72
73 hBytes = crypto.Keccak256(append(mBytes, []byte{0x12, 0x34}...))
74 h = new(big.Int).SetBytes(hBytes)
75 assert.Equal(t,
76 "9697834584560956691445940439424778243200861871421750951058436814122640359156",
77 h.String())
78}
79
80// func newBigIntWithBitLen(n int) *big.Int {
81// b := make([]byte, n/8)
82// for i := 0; i < len(b); i++ {
83// b[i] = 255
84// }
85// bi := new(big.Int).SetBytes(b[:])
86// return bi
87// }
88//
89// func TestMinBigIntBytesLen(t *testing.T) {
90// k := big.NewInt(1)
91// sk := PrivateKey(*k)
92//
93// mBlinded := newBigIntWithBitLen(MinBigIntBytesLen)
94// require.Equal(t, MinBigIntBytesLen, mBlinded.BitLen())
95// _, err := sk.BlindSign(mBlinded, k)
96// assert.Nil(t, err)
97//
98// mBlinded = new(big.Int).Div(mBlinded, big.NewInt(2))
99// require.Equal(t, MinBigIntBytesLen-1, mBlinded.BitLen())
100// _, err = sk.BlindSign(mBlinded, k)
101// assert.Equal(t, "mBlinded too small", err.Error())
102// }
103
104func TestPointCompressDecompress(t *testing.T) {
105 p := G
106 b := p.Compress()
107 assert.Equal(t,
108 "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
109 hex.EncodeToString(b[:]))
110 p2, err := DecompressPoint(b)
111 require.Nil(t, err)
112 assert.Equal(t, p, p2)
113
114 for i := 2; i < 1000; i++ {
115 p := G.Mul(big.NewInt(int64(i)))
116 b := p.Compress()
117 assert.Equal(t, 33, len(b))
118
119 p2, err := DecompressPoint(b)
120 require.Nil(t, err)
121 assert.Equal(t, p, p2)
122 }
123}
124
125func TestSignatureCompressDecompress(t *testing.T) {
126 f := G
127 sig := &Signature{
128 S: big.NewInt(1),
129 F: f,
130 }
131 b := sig.Compress()
132 assert.Equal(t,
133 "01000000000000000000000000000000000000000000000000000000000000007"+
134 "9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
135 hex.EncodeToString(b[:]))
136 sig2, err := DecompressSignature(b)
137 require.Nil(t, err)
138 assert.Equal(t, sig, sig2)
139
140 // Q = (P+1)/4
141 Q := new(big.Int).Div(new(big.Int).Add(P,
142 big.NewInt(1)), big.NewInt(4)) // nolint:gomnd
143 f = G
144
145 sig = &Signature{
146 S: Q,
147 F: f,
148 }
149 b = sig.Compress()
150 assert.Equal(t,
151 "0cffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff3f7"+
152 "9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
153 hex.EncodeToString(b[:]))
154 sig2, err = DecompressSignature(b)
155 require.Nil(t, err)
156 require.Equal(t, sig, sig2)
157
158 for i := 2; i < 10; i++ {
159 s := new(big.Int).Mod(new(big.Int).Mul(Q, big.NewInt(int64(i))), P)
160 f := G.Mul(big.NewInt(int64(i)))
161 sig := &Signature{
162 S: s,
163 F: f,
164 }
165 b := sig.Compress()
166 assert.Equal(t, 65, len(b))
167
168 sig2, err := DecompressSignature(b)
169 require.Nil(t, err)
170 assert.Equal(t, sig, sig2)
171 }
172}
173
174func BenchmarkCompressDecompress(b *testing.B) {
175 const n = 256
176 var points [n]*Point
177 var compPoints [n][33]byte
178
179 for i := 0; i < n; i++ {
180 points[i] = G.Mul(big.NewInt(int64(i)))
181 }
182 for i := 0; i < n; i++ {
183 compPoints[i] = points[i].Compress()
184 }
185
186 b.Run("Compress", func(b *testing.B) {
187 for i := 0; i < b.N; i++ {
188 _ = points[i%n].Compress()
189 }
190 })
191 b.Run("DecompressPoint", func(b *testing.B) {
192 for i := 0; i < b.N; i++ {
193 _, _ = DecompressPoint(compPoints[i%n])
194 }
195 })
196}