@@ -3,6 +3,7 @@ package api
33import (
44 "bytes"
55 "context"
6+ crand "crypto/rand"
67 "encoding/base64"
78 "encoding/binary"
89 "encoding/hex"
@@ -17,12 +18,12 @@ import (
1718 "github.com/MixinNetwork/tip/crypto"
1819 "github.com/MixinNetwork/tip/keeper"
1920 "github.com/MixinNetwork/tip/store"
20- "github.com/drand/kyber"
21- "github.com/drand/kyber/pairing/bn256"
22- "github.com/drand/kyber/share"
23- "github.com/drand/kyber/util/random"
2421 "github.com/stretchr/testify/require"
2522 "github.com/unrolled/render"
23+ "go.dedis.ch/kyber/v4"
24+ "go.dedis.ch/kyber/v4/pairing/bn256"
25+ "go.dedis.ch/kyber/v4/share"
26+ "go.dedis.ch/kyber/v4/util/random"
2627)
2728
2829type signStoreStub struct {
@@ -182,6 +183,79 @@ func TestSignSuccess(t *testing.T) {
182183 require .Equal (uint64 (1 ), binary .BigEndian .Uint64 (plain [assignorOffset + 136 :]))
183184}
184185
186+ func TestSignMatchesLegacyKyberFixture (t * testing.T ) {
187+ require := require .New (t )
188+
189+ const (
190+ serverKeyHex = "1d86753d770a1ced1103edb2ffd11728ee4ab6aed41094732c1748c72f2e181d"
191+ userKeyHex = "8bee954d5315684caa46d78fb8456a165bdd0cb44643d335a6b15c21d8c1872b"
192+ shareHex = "000000030e296d4c585d3aca61ebaf6a0e56ec11288baf0ab2b659d78a7b661a782fe092"
193+ ephemeralHex = "2b5a6b0cb9576ea218d081baa14d2cea82a6839165a29b3bdfc6ef8582b0ce5a"
194+ watcherHex = "2b5a6b0cb9576ea218d081baa14d2cea82a6839165a29b3bdfc6ef8582b0ce5a"
195+
196+ legacyRequestIdentity = "5JmMpYk6NEw3uMzciJ99iTpA9m5oLw3c8ocXd29CphTfdwc45FH3SFXYXKKATQqoF6FQHfCS9jZmSPpPbRuB1sj61QU2NxZ4388NVuXhXLLXfFp9gfKHSTtkGnSdsz8JyeZ3fKHD5ni8QVXXHkuftMdvkPswT2VmnyaMuRv3Dddt2sNk4EF3LL"
197+ legacyRequestSignature = "63abc17b385815e0636e690e582184bccdfbf64cc124828ce77964dfc0a174fb5756021009e35d30954f15ab923c9793e7f109a0c2f23a7e08da4fe58d93e3ee"
198+ legacyRequestData = "AAECAwQFBgcICQoL6WEvq0fOzUj9nxQTHRPzgwrEOk_n0VEjb6SAvDvhpZ-xStL3ki2iVh-DRyA570SZTl7tPacABMcVpXN6eMhjyU1p9iqjAOPid8oIVdS6xmq5N7OcNdtayngyHbWpKlERMh1_M_MCOxJV4xLg7tamdG5cdc9UBE5LItT-VmvxCrCyCOBQFZDqCiBF7Vhk9D8pzy9s147Zd9W1vJEPYquY_f1WPuXBnN5SpFn7e6zP1hbFssFZQtky_wmSBFtmN8dqvcyrIOH86gfivxUtGDSr5LjH3TV7DvOZfUqp43Ei4hPPlKHMSocoGHjYNhF3N58AggxsrLeLMW4Q77q4JQWd0HNaoZ3ugPjiyqlOnV5u9t1bZlPuhGSG9_4MCdpjHh_nJDrxgVIor9byghX_4Gd-bqxc21s6POUqB6yddyKS564nQX2h-SrgVHg7q5tFIDkM7vQT-wSd8nY763j4pt3d46qXCcnmFhWOcxukaFUhRy5NooVEBswtbY3sO5GxkV7MaQMu-znw4_FKpDtDJKfM-6-z0m7vFEby"
199+ legacyResponseCipher = "101112131415161718191a1b945842ae16cb61ef53e877257e70603814ed2f7aafe2acdc0b6a17dc7ea3bb017a5273a5df9e682444582718d8d1d9665a28f63ce07c14debc5bd0334653c28d7bae1d6dd71812ea84e971b05e6aecbddb39eb1cfff3b6bce8daa9c09e6a53714cd7f1f9f5c7a7d2c75e2b922abc19814390c9e09ad0094056c1a6d8636164e8b745ec6cb42c5fbe3d7dc7d71c55e507df3834b7b6b352285f52ca5cf8d978f2a201b70a506f8ba6fe5014d3a66929cc20886f79f14ddf0062d6afc7d66ab3b3dff58c9f2e7a69ee707ba0c10118d1179ec64bb84e462477f11b4e0bf28d4a25e8de03110b49c8ea4955"
200+ legacyResponseSignature = "7aba122edfcb613222322591ec133db26bcb5e70137334ce170d4b3baf72c79c676deb1b6146aa19caa6883b1dd50379ef8614e8f18c6078a68c15573bfbd18e"
201+ legacyResponsePlain = "00000000000004d200033e110b613b00caea0e0918da2f657595d749341a3c59f49b6163d64d3ed085271d939fe87abe13c16f892fcf4ea4e87c5b795e3983603ef5c7d6b0c1ed3095ad81e40f672aaf99d6a698ff4c57e2cc8ca9d15c1b295baff02de4569fa70ab21e44ec5aaa20c790ece45396c9124094c0ba4933e2bd6e9739ec7d9f74d6dfd8f529fe0e728169ee71856a62f59421a9a71b3426b817ca5c6ecac6b5e274dc0fef5b725833ebca07180a8031e9b44bcd1e852a017d6f4d85044af0e419f65bf3b117979d157ea0e87b0000000000000007"
202+ )
203+
204+ nonceBytes , err := hex .DecodeString ("000102030405060708090a0b101112131415161718191a1b" )
205+ require .NoError (err )
206+ oldReader := crand .Reader
207+ crand .Reader = bytes .NewReader (nonceBytes )
208+ t .Cleanup (func () {
209+ crand .Reader = oldReader
210+ })
211+
212+ serverKey , err := crypto .PrivateKeyFromHex (serverKeyHex )
213+ require .NoError (err )
214+ serverPub := crypto .PublicKey (serverKey )
215+ user , err := crypto .PrivateKeyFromHex (userKeyHex )
216+ require .NoError (err )
217+ ephmr , err := hex .DecodeString (ephemeralHex )
218+ require .NoError (err )
219+
220+ req := makeAPISignRequest (user , serverPub , ephmr , nil , 1234 , uint64 (keeper .EphemeralGracePeriod ), "" , watcherHex )
221+ require .Equal (legacyRequestIdentity , req .Identity )
222+ require .Equal (legacyRequestSignature , req .Signature )
223+ require .Equal (legacyRequestData , req .Data )
224+
225+ shareBytes , err := hex .DecodeString (shareHex )
226+ require .NoError (err )
227+ priv := & share.PriShare {
228+ I : binary .BigEndian .Uint32 (shareBytes [:4 ]),
229+ V : bn256 .NewSuiteG2 ().Scalar ().SetBytes (shareBytes [4 :]),
230+ }
231+ store := newSignStoreStub ()
232+ store .writeSignRequestFn = func (assignor , watcher []byte ) (time.Time , int , error ) {
233+ require .Equal (crypto .PublicKeyBytes (crypto .PublicKey (user )), assignor )
234+ require .Equal (ephmr , watcher )
235+ return time .Unix (1700000100 , 123 ), 7 , nil
236+ }
237+
238+ data , sigHex , err := sign (serverKey , store , req , priv )
239+ require .NoError (err )
240+ require .Equal (legacyResponseSignature , sigHex )
241+
242+ body := data .(map [string ]any )
243+ require .Equal (legacyResponseCipher , body ["cipher" ])
244+
245+ payload , err := json .Marshal (data )
246+ require .NoError (err )
247+ sig , err := hex .DecodeString (sigHex )
248+ require .NoError (err )
249+ require .NoError (crypto .Verify (serverPub , payload , sig ))
250+
251+ cipher , err := hex .DecodeString (body ["cipher" ].(string ))
252+ require .NoError (err )
253+ plain := crypto .DecryptECDH (serverPub , user , cipher )
254+ require .Equal (legacyResponsePlain , hex .EncodeToString (plain ))
255+ require .Equal (uint64 (1234 ), binary .BigEndian .Uint64 (plain [:8 ]))
256+ require .Equal (uint64 (7 ), binary .BigEndian .Uint64 (plain [len (plain )- 8 :]))
257+ }
258+
185259func TestSignMapsErrors (t * testing.T ) {
186260 require := require .New (t )
187261
0 commit comments