From 7c81836bd1dd04e36a130eaa634e956ec0455b0c Mon Sep 17 00:00:00 2001 From: Zhongxi Shen Date: Thu, 21 Sep 2023 15:05:21 -0600 Subject: [PATCH] fix(sdk-lib-mpc): use rejection sampling for range proof challenge TICKET: HSM-165 --- .../test/v2/fixtures/tss/ecdsaFixtures.ts | 4 + modules/bitgo/test/v2/unit/tss/ecdsa.ts | 6 +- .../src/account-lib/mpc/tss/ecdsa/ecdsa.ts | 16 ++ .../src/account-lib/mpc/tss/ecdsa/types.ts | 2 + modules/sdk-core/src/bitgo/tss/ecdsa/ecdsa.ts | 14 +- .../sdk-lib-mpc/src/tss/ecdsa/rangeproof.ts | 166 +++++++++++++----- modules/sdk-lib-mpc/src/tss/ecdsa/types.ts | 2 + 7 files changed, 157 insertions(+), 53 deletions(-) diff --git a/modules/bitgo/test/v2/fixtures/tss/ecdsaFixtures.ts b/modules/bitgo/test/v2/fixtures/tss/ecdsaFixtures.ts index ac98b0b2b7..0573897627 100644 --- a/modules/bitgo/test/v2/fixtures/tss/ecdsaFixtures.ts +++ b/modules/bitgo/test/v2/fixtures/tss/ecdsaFixtures.ts @@ -413,6 +413,7 @@ export const mockSignRT = { z: 'f2d3b33a5bf7f12088a278c6977a123b8beb170e3646f0563073929e7eb4f531a4bc7aadb14ab0890458339b97098e135c347add506b4d5240a8b063b8787cbc721e8b3a1c459d84ed690420b4496e60247415ad51b9898224002a2a0a4666b06395e291607acacd3ab178ba0a39eb33b18ca6715808e4fc5a4e6408fa0a3d9bb993a0fdb227a0d3b2ccd5073f1663354949edd78bb0fca1f2f1fa19c4177dbc37038b0ef5f396b2b617d06f90b1257c3052a03cfd2d16a22047d90105971c40bd6c231f7441ff930c978eda4b9cc239087cf0a98be71d872c4e4c56b2cdd26cd78ee0deb050701000c279910598f26bf780f57672cda230f3a6afc9a6eba084ec7304f392cef10799b4ba03d72b7ea5c4e473269ed2fc63e01f73dafc65548f37ae6b238afb106061e7f5fe837ffcc998b96f0d10b0d891c90b1255964e383e57be95a81353722402034fba518ae4cd57fcab5c07f6d18a6132a9deef2c614690f8565815e67aa6b9f84b1f4639d5466b4db2e85ade1706418327319477c87a', u: '200e6456d7d16f243c9f22cd961b629636cf961f770422b22d0629b2483623ef412ab975e2f08230935f37f8479c563cf49549554f3387e3435e6e2d8913bc81a40d8bfb8ff49c6be9aaea16cfc7f4942f0f0cd8954600e7b1156e9758dc29966de97f85e0ba3615b8a8583aa54f84bcfd0c6a312e99c96bbe27032fbc1e72943aef49872bcecb1495074b4fcbdfc725f1786f4e8a2190cc030da47b573716020245ea5640e309caaf2e246db7b7f67efb554292f000dea4305fbdaeda0c01bddeb9083ec2d604df22768806729ef1cdcf837dac5b51a35d179bad3a692524cc020dad4b7d682a11bfbfbbd9715cba7e4de3830a86ec6c2bc7cee3eb3649b09cfafa786dede00c272792824384f8ecbbf81ec7067b5942a42fd8176b7e72e766390d8a9393dfc2e8bfd7c7986783e8cb87923d607ccb02075932211e8625ae579e0dda8be4ae8c9dcf112fa42d88eed4209b49e36f9ab944f9b06312ed8d3423e85cc953eed439f7a21aaa2ec6a46d40f45544af8313edf172faa3349ee5982ea4ba82a25d9f19a82055a0e6136258ea7a6e337c71898ad279acad5acabdab31b747fb8ca42e7191609477ac605d768721a81db12988c2e35871a8ceaf6d7bae05267c93eab0237655b58dd67b8a9562d02536bb73e8c66e1109ce4a00d003036e36cf9f586b7bcb3a4e283535cea07636577631f44bc81328a370a38c837aa1b432b75e23988f51ec4371cb6e9d4f882e9ba557ce722a1bcef4c0f7bce8f8b38adf3303a7cda8656069d93af433bea36dc1b1659574cb48ac7c4fc0fad9b16ebe49312f2080922ed5f257100472af27d4a7dd23203860cdc11881e7142d221f5c06edd507a3e000fb867bdaebc16b9b44274d39c4d40a1d76923bc02ea42fc60eeb027d822f1f11d195eb9cc554cbb83a903de0b23ca0675584c76f02ee28fbce0aa3e19419c4bc1a4fa470771660038870d6eb15d4117a78c1b8049045d8b8aa05f6dbc55eaf232d83e2aab9eaba2174bf9e89ca5a4bced72cfa86c3ef3a3e1424e624a9e567519d6625b7a9fd03f0a6b96183be384951aae82cc37ba6d8bf', w: 'ac601f2c19eddb8ab4b7359d5504ae82efa5be55c71f053dce6583af691315ac9e7a8a4bfb42d0b437cb9ad2bc61983566bbacf9ef5eb596157116f442cd535bdfc037ad655147ea235229a87f19b45d7893cf3ac5f8765a75a0057d03ab3576bbca056db233f137281d3059baa861ee3c7c4e6a5399f69a88ad176d070409136ed6df4e8cc78a0aa43673a3e3517008d0f8bec0ee0ad8c3a4aba42e2871da26e2ce29645fe5d9e3f251af86c6fbe35b20dd9250d53ccbb382b69b7c3edee979ee736006ae24325914ce25f79424d3a34587ecd09f1ee1d8450bc5d05531b43aa40fb9d0eacaac8ccc5d91902c60d8a2d2c77287d4491656572b4cc767752858736d5213b1eaad6b73ae77fa5928af4e7edc726c417a0a9a049038bcb5fa36676db105fd3ffaacd4ff24f6d5463da1300bef3ffb0ff4a95915330cebfbdbe293c9511a1689cc1f343234636a4543049d44fb2757fd241e0ee3e25d6b83ed523edaebdad60acef9a6fc4b420af17b98e93e72f2020470faf73b27ce172d673d6e', + nonce: undefined, s: '34fe0101b0d0c6b01f1cad888ab019b9cb64f96194509523422f8564a0113a9070aed1c52d80e1142f11812d3813686b42d6cdfaed78eb4991f0bf4010bd8e0a384f5e56361f9123c24852fc65d6a1e11b75cb5f4a72ffc6aaad1ba075ea0d7787eedb9d83fc3a226bf3dc60dd321a6fd2085afb094b5573c1fcf44f8d415d7749732214c4b17e4e109af42966cfdf9b4e952583e2095b4dbc35f4883f3dccc59676f0536de429053ae6a57f87755993c24f14caa02946992ac2b958e55613e07e1bab395ff1b632d8ada48776eb137837be82a6c049ef3c8a67bb31681d43de7f8362f5fad49f1f1398f87bfb3aaccfd8903f0b0fee5420798e13cee4328446cbe9b238a53bd6852fc341a9355b4c876ae808f21bb0ae0fcfa7e9f0d08b7a980b45c5b3f39ce3ed2d19b791e9ad1aa01ed82766b85ad8d351db035f98dc8f9d6cffefbefed92e95c526c1865fe8213f185b19b3090309c2e17b200797de40c04fd5658c262c37ed9d19b063da0841f3652da0ba05f4c896ce611175e7186ead', s1: '824994a14f5ceb2c3b4750875c578133612c5046852a894f62e2b0aa0633e59dd1bfc7dce1eb781e3577a28bea4c2a6dee321433c76ba90374aa70d7d16f8380129ad08628db2fdfa85673de6a08184f84df6a920ec1a58c76178bb8484800a8', s2: 'dc8492e5c15ec3f945eebc4f5a78594a2cff34f2c59270d020cc8608283defcca6eef04a8ae72708dd99cfbfa3ee98e7e47d6bd7708244e9cf1c6c66e3c979b60dfa9eb0955c7f1504dbe37ac7fe5fb9b89869ff91717a800d02a9553d00fed1fe0da2c6718046c3286914841292474be339453732c887a425ca53c36e73e51c79e04e53a025b40ba4854d66dfab9f8f5d6d5debf4f6a908556ab87248839188c526dc6530eb9159fee2d911983ef82761ac042603b3ced88d55428437ba047fc7b07d40fb2c4b2a7784208522060e1fafa7e352001af6fe814a83726b7b7602263e6baa85a852ad89c236c19f03bfc9fb614ef3e3eb6f98280e3666abe265a1ce93d516f94b79720a29c5c58cef40dd9df4956b5627107460649a979ebc6da941bd09c79d99046081244a87b77852d7e185c174a6a0089014f3759f3d75e942c504808ac4e39cfd626738ec05f1ef31316a91803761c2c18879e59c746d1f24888f0136f35cfe347f53c2760cbd926aa4341cb78b58de023a137ea4c9f7674b39385a1c781d32c51c58e6a76aa30db8692d7c0344110377f0a8e177b091889f8ba15c29c593371f381fbffdc8f7287c2ef9b5235ebe2586e92a3e868a1a53d130c97a3ddfa7fdb6e8d0256ddae343edc7e76999f0e92936dce04918bb5d6cad', @@ -449,6 +450,7 @@ export const mockAShare = { z: '6d9f9979d0c9e87d7ee74d37a18ec71976eee44b078c5a9408a143f1496e8b0992946b2c18d779f03faca04db1ad1b6fb138f99893d0d9319550bd6e9e7fdd6ad4f54cab6654e65bf946186df6a394a8a7dc7564fe9db1e4ea6817ee2147d290311d3f55d89710e2d435ba33174725041056ab4e572d1815046931185c9e4e945b4d2374c24e31fb0a9f83832ddb6e813321a867444a9ef2d0c981b4456766e3c3ea64269de648a0b742582a71a8d839afa729b8c3adae9ba899ad32e925bac0d64d6853ee68f8d6d0b429f3f01c6f5fc952b53c83b785fd7a4af664865e9386870ed2f2ed4cec898eb00c6cc925a8d326bc60bd8b409af7a027f76aa688a4cb50483d99fd6b8dd91fd31a9858bdee9cb1b4c12127fca39840292a6adc5db4d0b2741b9ca7fc34721a58fc195ceb584e4984449696a56fb54dcd07385c96949b7c2bb8f2a358baa8bec64c2189709701d7bc1f912d2b83ac9d7d44de23c6db6ac7178c505943049ee8c0f9fc3b3ddafadb42fed25368b2a611fdf2b316059a9f', u: '84a3b389be244f035cc5bc3f563cf780c10147df576b8f615cfcf29f66cfdbe9a8c527067814cfaaf4a1a190684761f97fdf7c0ee1de3974e5271f102cf47fbaf05365007c647047f7615d9c4882159ee325ab293bcba4f1b09d09ad3f1808917c610f5375c39b13d0783a7bf865c7c599a57f873711c9e143d59d8e6c53b7753888ddc84063be7cf0e8aedd8b990629767a69d16f5c8db16a41860322a12995aadbbe65d38bb455fdb176bd3140e219932be479389317737b7447f41ea7da2fb27e9519050b4b6798644aacf4659a436e91b69374a303052c44aa71c9aea000a49843d5c7ef37a59c620a6bda467467a01158b38e09dec258191cf68566cb18ae4bcd9ea97bb71a542d39d257d59ff6b7ff602412e738765664280a5d73a98d1aaedb8276141fe73e87bd079b46a0ca69340b352230b5c15b107dc5bd4c091c0c8cb078d5f4b9aed474cf8c18a9eac32db5cf9563d137c877f9a1ca996b2a713316134f22b1c91b34d261127c1550dfda74cadd086d4d2e50ed25a35c029be96dfa6219490486abe6b974fae70cc0815e681574fce4e9b6df48614f94cc97b047e272ad99868534a1b335b652dce0147669b00182f7e22d6d10b6220bf066224f1b33a30c3a819ca332af17c0b5375175e159dda9b31d764fe6626b38915728b73faed0208082691f8d5222cc12f0412ee23decb81f84a998cbe518d68602f4b32e3bdb80e3f4b80600ccc2adc3331c71402485d56bdc820d9cf82034116a4bcd7948132af7c3227bc625e736ac075cd29fc2eb59e5ceb5b3e1d4651792dd103e3c9053004ac0aafeef4bf41a554f2f4bb6216f9744adaa2f1ce05c92ecb7041ba90bf41f7f3fadaddbb1ec3bfad84ba8db783b5065abda6fc20be807d2619955a4765779c27e36ed1a53b70ae2073e416f1ba109cbcff50bb5d9a692308a4ab907ff306a19afda653037ded3556f7c1012ad484a4de2ad852b955ac5ee6203444487113a70f708d8e66672207661464decdad8dea33faaf32521780e106cdcd1e344762c840fd70a840434edc42f1b01dfe77280a1ccc9c22a9672c11621ca', w: '505a09cc4d19e03b0592bd52ee634face2a0d30b49edbe26e082b8a473266ed764c0e3cfbdf8df8acfa790e9cf6a1fa53e5df1da3fd3a3fa2a076cad96d2d1dae5a502e1cfc831ceb12a31a4cf03ceddaab85a450700d5102cbfc7bd19d4e4a32c3b6f77f0c0b7e3b6c2bd32cc5ddebbef9984281001b0c60e5cf4da5960ee139e9cb132cb84ac922615b5d1fe358f5515f2cfa659a7a75c258d9681919ea53a43721841c464075216d4e8bedf123a2b183c1e6921cb91da106b23ad7617578d15b8f0f9164b7275d1a7103e889e62d4eeb213028969cacc1d9732ea278e19292268605e4de97318d65a8d5c1ad4837b4fc16fe690b2818d487a4f7642020be87ecc55c3f6bdfc8b44665db816645f5f3f68af02e75cedc23105634d84f1591e44679829891998a394545c66ac55e51c44335ae4abd6997950019e121c4fe1c87bab15fda4e20abb26fdd513848f01e32f00c4bf541878e98ddb702426d7122506982b8317cdd3b126523c0a0e953fd718ac4754538a3d74d26d5964d3e50d4b', + nonce: undefined, s: '7996f3e24812045348cddb71319237288a1927df4501ee480bedca366321963423f9970a1f54728cd6c51ffdaa652dd5522cbf52f0a5b832164b22664cf009cda6be875457e657b10713c0d6613e8337910d6410b0cf27ad8e5f9854af878f9a898621bd30fbb64d5bd4884a4da556679abca69a852664bd493f3e45e6deecc490033d07bbada6ade13a04bf6e373d84a5385caf098fa769777f134eeb63d55155c35135eca7c9125fc17c15c05a73dd6e7054694096674275b18f17fefa395810c7d260db8fcafb7e0f5a0f09d41cbadfe74a65b25ecf2ad83345e4e134b00a9fc6ab895d363d77d19d72037a8bad7c68775dda59a6825acc0414a36086d7e018eafd1c5331ec933175378c25c84eddcc064fc945bb0b5154195660deae36173cdd0cf963fe1cbd2d6d166c6a3d68ff173eda535a843a6cd39cb50ef98406423ead80199ae44525582e305cb9c782ce29fed317e9ba7fef78b1224494fb252c2ac7231a7b783ef6957cf28ca22d406724926627a8e083cc189c56ee80692ef7', s1: '5f46d8ffe2ac222a130c3ed46da7cdfbdf46470b8995fae95292e03b8875c7350d1fb5038d775ea026969ccf7ea2ea4d991ec5edfb63bdcfc375b9ffce262f1b0f2dad51acf9a996879d3028fadc097b432750a31d621a002497f63bf7844b31', s2: '9f47f5acf80c4d2667824b7bac32e78eb49ac2a8b5ffa1b7f6363853e47123f01a64d3116bcac908fe3d2d5d972a9d566d50dde5ca461cfc8e571dce6b7f31ff842f73614f2bf6ab8b107beeb58ed7e9bacbad212580fcdc671d0a55a3da51de6a91a3bf2b5cf6dab966c0d648cb6d15ec54f613f327dbbc8abbec7d732afb06e1de01e285d32e10cd630a50e9b82c4931964e7092314468d0f1f18f83adc8481d94cfb65add609e0be95187df325e9c327cc43b319dc7b21fd4fb649d4ee30a6c9d0a58e48a7d7cc9be1554943f9962314ccb3db02d3c18f49d18927c784cd57fc1cab591fede36d1d8d62715af99aa39e7659a56e5adc1ca51e8c4375b0420faa08619cf22273fefbeb7ea1e41de901ecd0535487b7c694a515c60c386ff90b29a8713db37059947eb6e63851309ef258155897e4986e0fb5b8f02a45ec857e909e03e3772be17571dee303e45ef8619a24c6d5053bb8d2b83e7742f77c64a4cb198fd3c284f9945acfaf5481c2140160ad4a0a42842ae3ba803a1289e46b7b813cd5dbd61a4b82dc6dcc23d5fdfc72877ec204652fd631dfede0b656945b86beeec98808f838ac12792acbc31c5aff759868471c5c06797d528118462f553197f30d679b416174a49e861edf7d1fdb8df7202b241b32356077909d57f18a5', @@ -459,6 +461,7 @@ export const mockAShare = { t: 'b7f71ca4150a2bef48c98110f96ee83c665eb5892316451fabcc23e13bf6148ee47231705ba169fb44094d1603dc3a078ce56f9fc310e87aa28e22970fa0f7a5d9e5a3950399a7b9f8fee107a661055598974c339707aa5deb390165b719a53bb3d13ea6f5102c3afa670b04c80a32a078f6e828be7abba2c5e17a0bc9c38d3ad2027254c5e31f591bdf83f0daa03035a5a7808d909412819d70adcbae21ef4fd866d16fbc46eb59aec6669002e732db880a73eeaeabe8df433903628be89f208ab512825da8f268cfd7fc308141033027ad093bbad0f1d36b9580e76040ed7a31d92f1f6d4f2a841d311ccab01fa0abe04c14e28604a9520b826b703441b21d758ba0970f9e2833592800686ce9d067be034df04ad88304d200b2eef20282b19db02917017767efea961365532cbf00ac7bf7580c76c6f8ffa0cf2ac505dd82199d67f24e5e2e44738cbe7282f284a94e8ae56f9ad333d9b7094a1f8e04b628db29b05f7b656fdd2e098f9fc3f2d9f369c67958ba164ba01134e60790e46c2b', v: '21705248fd73a138ca5c26d090624ebb62fa6d0d7c2e7cfdf402e99057f8b3cc615fe1a7bf82bbe67b2a4dd57ce6df29709c7effb39767f69e5a2b0643b68d2f998dd29f4ee0c3757907278600a9d0b0b0293c176b8a18abd1f1277a5d2aa9d8b628b9a9e5136f92900103c77797edc2c537fb48c8f30b8c9636464727c7d67b859e41f8ed8058acfac4cc2478e876fdf2a3db8d0f79dc6f094108558c2542c94b0a4f54de2583d92710ceab3c4800986525d5173f98352198671ea4de26752c2835240bd9066d364fbdce87f1f976c0c9e65ad76ef95014914e06142bb5025dd2158876ee7be7eb347e798f868f7bc95c47a878c61ba304898bcfdb6c4e098566c1e87e29c66bd49af3a6c565c87fda983355d44017b7a152a153c532d0f2e3e1a980bbfe39090b65b116761e64a01d8e31d5ad4847f806367870eb81322dd08120d28d87bf0a28ecc516952a89a18c40ac5182bc4b909a8d35411a8419300bbfe05a58662c52ecd898f998065c33ae3dce349b1d89632c4c11edb845c4ff4559fcbb1be3ea45e79dff5bb9b9cb06cac9b6cb2cec4ec6ce40b598e25202dcdce0948f7e5b5ec4f819ebfff6a7eeed00d5dcae8475cc316665c35a3ba98591c33f1bcfaf2b7c90082927c957f953f0740ce25dd9dfea5128ba2f952e0ce81812418e4c67a7031b2081b7b062cc94708186bf948ed62d21c9dce7c80151e906d9e0b5e512022654ab2d9fb6df5ac19101ff393aad8474e7954a4f532296cc6586bee367162074e200004e9bda23c16823d1f917747e4e6c1be0d6439ad4ddbdc3bfc6864ee6f5c328e2c25fb48685daeb00652e972e97a0e7d4bb735321d4a73d025c20f60b58b54eaac58a5b2bc824ea28a26c348f15c4e619e81ed39cfdf05f405c7708f952bbf0d1a2b148739319c466ad6defdb6b52eed44d8ba7b09cfdf2564aeb979fe3d73207108a6fe7ef3d8e1c0b19e8ca3715524cce6293ec77c835d1ff4ed08dbf078dac14387639732716832667bc2aa22ebb6a442b8a002d5d86213f66e9e06da41df94506aad97f35a0a562c18c15d876831fbe111bd1979d49', w: '76ff8c76016a532cf8615d2abe9e65e58f08fd309101d3014884d5fe4e1de11b452f7158e57544ba7836d99456992ad9d5067cf12f252462ad3ab5de1be9f5343508e4f217d1fe08b472f780b49eb4c8c92973a7f7c5a4c064caddaae127552284d6dcb44127b2676c765941d2cbf206edc962834db7ca37cef9ddffe16d8c13c2a324eb855caa66339f9081787768fd72235e881190910186fd2a8c92019b8fe7de64c8f141688db045ecef3e890e4a1eb9e3459dc4c5071615b6763560fae69f7b8986ff48061edb76dc16bae8d3c0fcc20f4d86ba94e30ab08a3345c4fdaf18757fcd2f94fecf022ebcfc37b388016c7f0f3a4f2c74f04e73b3a807d4e4bd4c1f27b1274817f5894fe5c5fbe29f699f58c9c71b904fbb5d7cecadd93951fce198ab7143b5a811f3e873f4fb603cf44314af43e75051c65f2168eb57bcc99b4db9e5e70c68191f087186faf923a15df152f0c524133fc6724ec9c08d4c4f9f0694913186c29eb0b540493bfc456e6895a951ca74d326e3fdd4b4980ff2bfb1', + nonce: undefined, s: '2641a2e1ba7bba89492a5059dfa10b84e856f168eebb840e39976e073d1e7434a1987a50ed3b07522b9d7356cb7cce61a91fb31b01015bfb85ab8ed4ffd550d740b9d0dd7ed159bbd864b5ea4188ecc3612374ca460b39f9e41f0887a5e9dd7151c2e13cfe69710b5aaa5a858c51ad34b7718af777a30e90a23017f95caebf70e71b802a75cbecfc833e436e40ca45cc6c96fd13f7c3a062db3a8abd1729948a27901a938f21ab26904b08c665f1533e070a7beed20700e0e10ce02cdc5ffcc796b88207f18be103f57c433644f1845b6df72fdad25109624129b9e0de6986fbe31875f2362bf903824d898ba5f341c606f652ff31b8a4eacb5086cffae7786ca05eb1a1c03c534f685debb24b9f70bd16e5b04810a1bbf52079040a31c721bdfd04e5adeaaf31358b117408e87eb9ce02d57d3a88e2cbc0d413d9304eec8529e0a364d0a80c6b9486b4aca711f1f802f0f49eb7aa369a54a3a1f5188553d550746a2565a56824d60ee6510d3ddfb0727a0959edb4f7e9bdaa310eaf324e3437', s1: '59d1427c3dde3c3c7c838577d126836ce6c6a6be1a71a51dfefde1722ce99a88296bafe4446bb7276a3172558bbfe6fa0c6bb239a7ab8fca204f7fffeca040d94db44b3879010561b152d6e8fff2accdf1828fd9f2e2a7f6ce92c4c25a4800a5', s2: '66c3af5747d21f82380b8c34ff9b8ec062ea4dec980458c2a56902c85de7fb8164ee9287c06ab8a2e85eab2571bd9d10f846f7efb23933d057fd48afdbcc7bbe49a8efc96c679f31d360f6a212ff704bd1087f9d5962a3a558c5a35d1d22944e05c485b0890e8a2ef621bd6d598996b0624f9a22847fdf9497de4ae1330bdeabfdefdbac9a64d9d12a1819527a63d213ca30083de0dc3a482500b79e3613ff2fa4fcb2e70cd18a3a7f66854cebfc0a9458e9c9edfcc4cb73534d1097b8cad934efd5d2be32462ec3a667568bc58c3be1903bae32d1c73b6021c9a8e7c6478c6b6d841a1e0fe674aee64fa5f60afbc77e7c2d4458850d3c91f93d8c83de5c42087d27145fb174627d3d58e3b3cef40fba83047eeafb00c31fc1f5093e6b4c11f9b4df5795f05259b69db2ab6ff7b4e2e7276443c75cbb9c267cba6d3a4835c4c81b53d2a5b7e9aabaa62608a378a92e6845a35c4c3be331442b877a26ba8a95a2e50ad04864d514d6aec46e9c3b386884b5a7563248fa38f13a36a0e4514b939ec369861c9acc4fad45270c743bdf61b170c4172dcfe968a40bb99fe0558cde8bf17ff56046a3e8f105b56d4dab2b26df2ae712d74cdd5266a0de6caef5511df0e5f58e8660438c931cbd1f3e71c7cda227ce22206cd116ab5d30a8c36de955c6', @@ -473,6 +476,7 @@ export const mockAShare = { t: '56fd7cc46302298768823915630fd27325c9e4a3b8cdb37d1779b811e75e92ac47e1858d9657eeee1a98fc9cc2ea53a71c584365402d5fe722d8547dd8233f6c49b62e290d75f5702f377868d99ab5019c4703f570df097a738baa752469f38818eeb174f20db4bbe6ec1f747c12e19d400c95e1368a6be67f03f47ff7287b3e6851b02e34c9ad337473e4f93730eae690951510398bc05a074de0a9a10ad2fce8161d8ed83a97f85743c25a3cd677048841b39c5743e2a6f6646219564f0d43acae1e30c8222937bd62e7c6bedf2eb1cad5ac3bb38b4fce2cb8417b2eb71bed2919135c88fbd0b6455146c2d04b155d8ca6a1e3fddb1e57ffc04197d8a5477c00159c3267ebd5131d592f7fb7a6b856255cec4b08c8430cb086536b4a42068fac0f42b81dee6a5cc19d3942181c2f5689191d89c7f5752dff0f4952bac4c0cf49b64c0e49863d2ae59559445ddf9efeb47692e8be128791e06a354fc5e3ef9010d510566abe2c682bf58641bd4e5a012a908dc643e93dcdfcd0e83b9fa3deb6', v: 'a48b817f870d7d372a0e721b5a991216987b3a4ad33351e5bc353d7ee3615d95435437e72e4890333087fcb75e453154a52a1e442f60760790b4f664fc02bd8a7fdbff6e127aae3306f0a1a029a83e038f1125216ab7da4a74cba4882076921ee306561bea3422148e664665e657b69f8d2ae687c2a69700d1098901e21fcff1476f2f1e0d1da7987d1dcd115c9d032f7dd7334e8dd453d522091720776297bec5717ed1d3a13dde9744c1ab73829d3cd97b068600d73b64a761cb664e33a79dacb1a0672f2928b83baf2910a095641e9f15a15baadc2da8d470c0ea8f70d8e0938280e901a1c69bc5d6dbcc674bacf15daa832d657c8a20c585dfee330a9a3bd802d800ffdaacd9afb37eb264e9442f5a0f794cf6d898f60bd0ca2dc4a390d140a2f391d4af466b50028633697c4e589d736ec17884375d8a04f204bc109a84bdb800b268adb2c7419d4144990aa8e8f6fa9861d887feda7882d6a349f2d750446e32263f42ba6da091af8bcb144c31dadcda7bdf874b5489d9bbcf067e1bd086a41652639ceb242b6a318180a4966191f9c2e341bd23ed5b013b2c84c766c17c129026ab3243b9784ca544bd1797242f26375c8284cb44f9f84440c91ccdd6b1457e1a2d4a36d2968ba2999830e52a149fefa21b8bbb0654d716b037fe2c2eb30a80e346c03f52d60aa535fbd68352f43030e606780bf2593e0ba2774d46bbcd6e5091c98b05266e12b86faf3761be2297a9445debed7a86be9ca96849b7125333ed21deef919cc5fcd80f8a73cfcc0f0f484f225a4c1af0f9fc71b0ec8dd3dee0c81ff250085412061dbf4e2ac5c2478e486d0ff9a2162a51cd7e594ffdd612fe5d9f645f13b83f2dd01a45beb6703f64e2cc02f91b0b8ca005dcd061a6dcc82e34d6efc941edebec2d038562f2cb29ab669e73bca3a0b95bd1150dcf351293fc43cea46b674e54aec32c55e444f9dd842f71c2caf064a744584208dffdfa7cdc63ee592b165b6613e47aa468ba103ee9cb538102d0cb28792db25b5f3c16cac4022f008d4cf2ec141370b5b168757461018e1f2a57594fa55a083a8eee69', w: 'c667265d7adfe0cffdb875c12ff47b8c1f22ca6c786841f18681803d1508a4e88ef800505d4dbf9e68c0177068b144b500cc27aa720a54607ffd94ee140c74f7854d7ae3ead7656f65e10703eab95e72feec21b722b61d68b5b8dbb7a87cf41121c4cdb695986d19090b5acf9de9c9586115d3bfc97a521e8ba0b38178f8239721e8b3dce7c40e7025c6b7763c8de82877bf4edf518610861640213a81266d2bf09eee0cfacfdb19322b7459fa709f06bbf8eee649a762a1bb96d07c8de313ed25c12fb5ec35c258787bfafdf9d778ddf5a922ecc209f8ec1ba958f202e1d12aec9e24f31796f7676e0bb7d6f7894a983af2013654cfa0777b3c3876b77c25fcc20a9f29a30cbd8b37951e5a54cad910037bf6acd7ebbd842b69eea723dc4019a2a6a18ed8f6ae41da8113ed7ad8585e9e0f14adb5747f0628defa528f108e5a513d26162fee10b6a2566914edffb8da49bfe840f03addddfe1a1d99b401aefa16b2a2ad34f51d9b1c2b679526ad059db883006a4d02278af4b6ebc14c1ed269', + nonce: undefined, s: '571db9044932faf70bbdcc40aa8249ee8de6318326b03ddc6d68d88c14915b0f92c2183c135935b34b7cdc416b8661b630f2fa2904cfe820d9e185f33794248bd5e2f5e84cc5955c2051da3289660461885a49eee2a7089dd34674e3c63775b2a43b9bf07b7ec0d0361a1a45f2848335a0ee49e17a91b3a7469f0d66f2d533015a15d2af2f2421f35833fb1f75d73b931213c748af04e3a78d79d5a8a68c292ab81e5baeca583143fe2872259439abe6e35b17f7d993df83b45a173d7b99795ef5021dac177d5a5715404b4827ce4f2c106108573437545374c6c56ee03a8f3eac0bbe5777b21dacb498526f187b2fcfe7471d137a0a147f52f824129eb12d8345ea8e42564b519300e3be93620631f94fcf2d4f5fbdf2c58cb4598cb1513fe65e3c4ffc6da0f268436d7d6d77779f11db9961f574dc5400281fe3bb753567f9afec9d4633be658ccdb6e2115d27d11c1cdcfbcac398c807bc0271b239bae6c290349c35f195dccb6e1b05187cda35f2587085a6f34e9d4512374bf74ee02860', s1: '6dbc87f16539870c77f04466e958046280aa9a046f12aecd0ba5efff2e6b138b6d9268fcd03339de410c8e686b9e5c1d9248801e7cda7c97d1b4c5b850ef0ee108725704a596bef64813d0e838b4145c1193902483139ba6d65acf0df5279e79', s2: '6622088cab669360d1c9a04c1a27255a2a2f855609d90ca9cdbaf789d0d0b62b93253200538c03caf5c6243674dc0a061ac3323eed4e0d0459d1deb9025218766d382daefc205679463fe9817acf311ab57e2c9b302045507f62d70a5281eae40d8c53eac996a30209d0dc4e2a272b4296d28be19854fd54d23a382a4231f6ecd20c130430dd15714f5a953320c53fe6c4580bec50ee75c8f87e415af7a1ba3b27e238743e6d3a05348227b63c151de6b50ee6c2cf6ddf52ed62d6551c5aaf69c6ef620721d8c9d68fae0dfeed07a2e25cc07c9c72149a0a11c60770f23bf9a4b27eb521945fab6eb141019f08252c8be34c94445963ca39a743b071a825dd7943d844d1d6b07f634ea83d1e5ee2e6c09b4a3467536669ca61949eb9e4925af11c43210dff981f6f9d93e6e7b8931da43fcb5559f7311d6508292e485c3cbc3fa8fa990ca189b58b5f021317020748f2a30fcadb918823d890c24cce604592b41b8dab00499ae2ac2f26269105b38a73da3f2764728dc4c4b574a164162ead0e955cc3071a5386d99eea37e781445756fbac6b6993268738a3f1d38693c0e3827e19bb3390db870e60e8d4b7e8706d9f0d357e73da83eb85f0100149e7af45cb6f0fd6bb9682884165e67d0ae7c807d80cd19e75536fbd443f5fc7c5c60896cc', diff --git a/modules/bitgo/test/v2/unit/tss/ecdsa.ts b/modules/bitgo/test/v2/unit/tss/ecdsa.ts index 2b97f21cf6..9403f00b3d 100644 --- a/modules/bitgo/test/v2/unit/tss/ecdsa.ts +++ b/modules/bitgo/test/v2/unit/tss/ecdsa.ts @@ -633,7 +633,7 @@ describe('Ecdsa tss helper functions tests', function () { ECDSAMethods.delimeter }${bitgoKShare.p.join(ECDSAMethods.delimeter)}${ECDSAMethods.delimeter}${bitgoKShare.sigma.join( ECDSAMethods.delimeter - )}`, + )}${ECDSAMethods.delimeter}`, } as SignatureShareRecord; const kshare = ECDSAMethods.convertKShare(bitgoKShare); @@ -701,7 +701,9 @@ describe('Ecdsa tss helper functions tests', function () { mockShare.wProof?.t2 || '' }${ECDSAMethods.delimeter}${mockShare.wProof?.u || ''}${ECDSAMethods.delimeter}${mockShare.wProof?.x || ''}${ ECDSAMethods.delimeter - }${mockShare.sigma!.join(ECDSAMethods.delimeter)}`, + }${mockShare.sigma.join(ECDSAMethods.delimeter)}${ECDSAMethods.delimeter}${ECDSAMethods.delimeter}${ + ECDSAMethods.delimeter + }`, } as SignatureShareRecord; const aShare = ECDSAMethods.convertAShare(mockShare); diff --git a/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/ecdsa.ts b/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/ecdsa.ts index 644bb92edd..7dccb6324a 100644 --- a/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/ecdsa.ts +++ b/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/ecdsa.ts @@ -392,6 +392,7 @@ export default class Ecdsa { z: bigIntToBufferBE(proof.z, 384).toString('hex'), u: bigIntToBufferBE(proof.u, 768).toString('hex'), w: bigIntToBufferBE(proof.w, 384).toString('hex'), + nonce: proof.nonce?.toString('hex'), s: bigIntToBufferBE(proof.s, 384).toString('hex'), s1: bigIntToBufferBE(proof.s1, 96).toString('hex'), s2: bigIntToBufferBE(proof.s2, 480).toString('hex'), @@ -487,6 +488,7 @@ export default class Ecdsa { z: hexToBigInt(receivedKShare.proof.z), u: hexToBigInt(receivedKShare.proof.u), w: hexToBigInt(receivedKShare.proof.w), + nonce: receivedKShare.proof.nonce ? Buffer.from(receivedKShare.proof.nonce, 'hex') : undefined, s: hexToBigInt(receivedKShare.proof.s), s1: hexToBigInt(receivedKShare.proof.s1), s2: hexToBigInt(receivedKShare.proof.s2), @@ -528,6 +530,7 @@ export default class Ecdsa { t: bigIntToBufferBE(proof.t, 384).toString('hex'), v: bigIntToBufferBE(proof.v, 768).toString('hex'), w: bigIntToBufferBE(proof.w, 384).toString('hex'), + nonce: proof.nonce?.toString('hex'), s: bigIntToBufferBE(proof.s, 384).toString('hex'), s1: bigIntToBufferBE(proof.s1, 96).toString('hex'), s2: bigIntToBufferBE(proof.s2, 480).toString('hex'), @@ -568,6 +571,7 @@ export default class Ecdsa { t: bigIntToBufferBE(proof.t, 384).toString('hex'), v: bigIntToBufferBE(proof.v, 768).toString('hex'), w: bigIntToBufferBE(proof.w, 384).toString('hex'), + nonce: proof.nonce?.toString('hex'), s: bigIntToBufferBE(proof.s, 384).toString('hex'), s1: bigIntToBufferBE(proof.s1, 96).toString('hex'), s2: bigIntToBufferBE(proof.s2, 480).toString('hex'), @@ -659,6 +663,7 @@ export default class Ecdsa { t: hexToBigInt(receivedAShare.gammaProof.t), v: hexToBigInt(receivedAShare.gammaProof.v), w: hexToBigInt(receivedAShare.gammaProof.w), + nonce: receivedAShare.gammaProof.nonce ? Buffer.from(receivedAShare.gammaProof.nonce, 'hex') : undefined, s: hexToBigInt(receivedAShare.gammaProof.s), s1: hexToBigInt(receivedAShare.gammaProof.s1), s2: hexToBigInt(receivedAShare.gammaProof.s2), @@ -690,6 +695,7 @@ export default class Ecdsa { t: hexToBigInt(receivedAShare.wProof.t), v: hexToBigInt(receivedAShare.wProof.v), w: hexToBigInt(receivedAShare.wProof.w), + nonce: receivedAShare.wProof.nonce ? Buffer.from(receivedAShare.wProof.nonce, 'hex') : undefined, s: hexToBigInt(receivedAShare.wProof.s), s1: hexToBigInt(receivedAShare.wProof.s1), s2: hexToBigInt(receivedAShare.wProof.s2), @@ -738,6 +744,7 @@ export default class Ecdsa { z: hexToBigInt(receivedAShare.proof.z), u: hexToBigInt(receivedAShare.proof.u), w: hexToBigInt(receivedAShare.proof.w), + nonce: receivedAShare.proof.nonce ? Buffer.from(receivedAShare.proof.nonce, 'hex') : undefined, s: hexToBigInt(receivedAShare.proof.s), s1: hexToBigInt(receivedAShare.proof.s1), s2: hexToBigInt(receivedAShare.proof.s2), @@ -780,6 +787,7 @@ export default class Ecdsa { t: bigIntToBufferBE(proof.t, 384).toString('hex'), v: bigIntToBufferBE(proof.v, 768).toString('hex'), w: bigIntToBufferBE(proof.w, 384).toString('hex'), + nonce: proof.nonce?.toString('hex'), s: bigIntToBufferBE(proof.s, 384).toString('hex'), s1: bigIntToBufferBE(proof.s1, 96).toString('hex'), s2: bigIntToBufferBE(proof.s2, 480).toString('hex'), @@ -820,6 +828,7 @@ export default class Ecdsa { t: bigIntToBufferBE(proof.t, 384).toString('hex'), v: bigIntToBufferBE(proof.v, 768).toString('hex'), w: bigIntToBufferBE(proof.w, 384).toString('hex'), + nonce: proof.nonce?.toString('hex'), s: bigIntToBufferBE(proof.s, 384).toString('hex'), s1: bigIntToBufferBE(proof.s1, 96).toString('hex'), s2: bigIntToBufferBE(proof.s2, 480).toString('hex'), @@ -891,6 +900,7 @@ export default class Ecdsa { t: hexToBigInt(receivedMuShare.gammaProof.t), v: hexToBigInt(receivedMuShare.gammaProof.v), w: hexToBigInt(receivedMuShare.gammaProof.w), + nonce: receivedMuShare.gammaProof.nonce ? Buffer.from(receivedMuShare.gammaProof.nonce, 'hex') : undefined, s: hexToBigInt(receivedMuShare.gammaProof.s), s1: hexToBigInt(receivedMuShare.gammaProof.s1), s2: hexToBigInt(receivedMuShare.gammaProof.s2), @@ -922,6 +932,7 @@ export default class Ecdsa { t: hexToBigInt(receivedMuShare.wProof.t), v: hexToBigInt(receivedMuShare.wProof.v), w: hexToBigInt(receivedMuShare.wProof.w), + nonce: receivedMuShare.wProof.nonce ? Buffer.from(receivedMuShare.wProof.nonce, 'hex') : undefined, s: hexToBigInt(receivedMuShare.wProof.s), s1: hexToBigInt(receivedMuShare.wProof.s1), s2: hexToBigInt(receivedMuShare.wProof.s2), @@ -1030,6 +1041,7 @@ export default class Ecdsa { t: hexToBigInt(aShareToBeSent.gammaProof.t), v: hexToBigInt(aShareToBeSent.gammaProof.v), w: hexToBigInt(aShareToBeSent.gammaProof.w), + nonce: aShareToBeSent.gammaProof.nonce ? Buffer.from(aShareToBeSent.gammaProof.nonce, 'hex') : undefined, s: hexToBigInt(aShareToBeSent.gammaProof.s), s1: hexToBigInt(aShareToBeSent.gammaProof.s1), s2: hexToBigInt(aShareToBeSent.gammaProof.s2), @@ -1061,6 +1073,7 @@ export default class Ecdsa { t: hexToBigInt(aShareToBeSent.wProof.t), v: hexToBigInt(aShareToBeSent.wProof.v), w: hexToBigInt(aShareToBeSent.wProof.w), + nonce: aShareToBeSent.wProof.nonce ? Buffer.from(aShareToBeSent.wProof.nonce, 'hex') : undefined, s: hexToBigInt(aShareToBeSent.wProof.s), s1: hexToBigInt(aShareToBeSent.wProof.s1), s2: hexToBigInt(aShareToBeSent.wProof.s2), @@ -1122,6 +1135,7 @@ export default class Ecdsa { z: hexToBigInt(aShareToBeSent.proof.z), u: hexToBigInt(aShareToBeSent.proof.u), w: hexToBigInt(aShareToBeSent.proof.w), + nonce: aShareToBeSent.proof.nonce ? Buffer.from(aShareToBeSent.proof.nonce, 'hex') : undefined, s: hexToBigInt(aShareToBeSent.proof.s), s1: hexToBigInt(aShareToBeSent.proof.s1), s2: hexToBigInt(aShareToBeSent.proof.s2), @@ -1166,6 +1180,7 @@ export default class Ecdsa { t: bigIntToBufferBE(proof.t, 384).toString('hex'), v: bigIntToBufferBE(proof.v, 768).toString('hex'), w: bigIntToBufferBE(proof.w, 384).toString('hex'), + nonce: proof.nonce?.toString('hex'), s: bigIntToBufferBE(proof.s, 384).toString('hex'), s1: bigIntToBufferBE(proof.s1, 96).toString('hex'), s2: bigIntToBufferBE(proof.s2, 480).toString('hex'), @@ -1210,6 +1225,7 @@ export default class Ecdsa { t: bigIntToBufferBE(proof.t, 384).toString('hex'), v: bigIntToBufferBE(proof.v, 768).toString('hex'), w: bigIntToBufferBE(proof.w, 384).toString('hex'), + nonce: proof.nonce?.toString('hex'), s: bigIntToBufferBE(proof.s, 384).toString('hex'), s1: bigIntToBufferBE(proof.s1, 96).toString('hex'), s2: bigIntToBufferBE(proof.s2, 480).toString('hex'), diff --git a/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/types.ts b/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/types.ts index f30436e990..22ebbaf222 100644 --- a/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/types.ts +++ b/modules/sdk-core/src/account-lib/mpc/tss/ecdsa/types.ts @@ -118,6 +118,7 @@ export type RangeProofShare = { z: string; u: string; w: string; + nonce?: string; s: string; s1: string; s2: string; @@ -144,6 +145,7 @@ export type RangeProofWithCheckShare = { t: string; v: string; w: string; + nonce?: string; s: string; s1: string; s2: string; diff --git a/modules/sdk-core/src/bitgo/tss/ecdsa/ecdsa.ts b/modules/sdk-core/src/bitgo/tss/ecdsa/ecdsa.ts index 1a244191e2..ae80013de7 100644 --- a/modules/sdk-core/src/bitgo/tss/ecdsa/ecdsa.ts +++ b/modules/sdk-core/src/bitgo/tss/ecdsa/ecdsa.ts @@ -480,6 +480,7 @@ export function parseKShare(share: SignatureShareRecord): KShare { z: shares[5], u: shares[6], w: shares[7], + nonce: shares[11 + 2 * EcdsaPaillierProof.m] ? shares[11 + 2 * EcdsaPaillierProof.m] : undefined, s: shares[8], s1: shares[9], s2: shares[10], @@ -515,7 +516,9 @@ export function convertKShare(share: KShare): SignatureShareRecord { share.proof?.w || '' }${delimeter}${share.proof?.s || ''}${delimeter}${share.proof?.s1 || ''}${delimeter}${ share.proof?.s2 || '' - }${delimeter}${(share.p || []).join(delimeter)}${delimeter}${(share.sigma || []).join(delimeter)}`, + }${delimeter}${(share.p || []).join(delimeter)}${delimeter}${(share.sigma || []).join(delimeter)}${delimeter}${ + share.proof?.nonce || '' + }`, }; } @@ -536,6 +539,7 @@ export function parseAShare(share: SignatureShareRecord): AShare { z: shares[7], u: shares[8], w: shares[9], + nonce: shares[37 + EcdsaPaillierProof.m] ? shares[37 + EcdsaPaillierProof.m] : undefined, s: shares[10], s1: shares[11], s2: shares[12], @@ -549,6 +553,7 @@ export function parseAShare(share: SignatureShareRecord): AShare { t: shares[15], v: shares[16], w: shares[17], + nonce: shares[38 + EcdsaPaillierProof.m] ? shares[38 + EcdsaPaillierProof.m] : undefined, s: shares[18], s1: shares[19], s2: shares[20], @@ -566,6 +571,7 @@ export function parseAShare(share: SignatureShareRecord): AShare { t: shares[27], v: shares[28], w: shares[29], + nonce: shares[39 + EcdsaPaillierProof.m] ? shares[39 + EcdsaPaillierProof.m] : undefined, s: shares[30], s1: shares[31], s2: shares[32], @@ -589,7 +595,7 @@ export function parseAShare(share: SignatureShareRecord): AShare { proof, gammaProof, wProof, - sigma: shares.slice(37), + sigma: shares.slice(37, 37 + EcdsaPaillierProof.m), }; } @@ -624,7 +630,9 @@ export function convertAShare(share: AShare): SignatureShareRecord { share.wProof?.s2 || '' }${delimeter}${share.wProof?.t1 || ''}${delimeter}${share.wProof?.t2 || ''}${delimeter}${ share.wProof?.u || '' - }${delimeter}${share.wProof?.x || ''}${delimeter}${(share.sigma || []).join(delimeter)}`, + }${delimeter}${share.wProof?.x || ''}${delimeter}${(share.sigma || []).join(delimeter)}${delimeter}${ + share.proof?.nonce || '' + }${delimeter}${share.gammaProof?.nonce || ''}${delimeter}${share.wProof?.nonce || ''}`, }; } diff --git a/modules/sdk-lib-mpc/src/tss/ecdsa/rangeproof.ts b/modules/sdk-lib-mpc/src/tss/ecdsa/rangeproof.ts index 53883efbfc..26e49b6547 100644 --- a/modules/sdk-lib-mpc/src/tss/ecdsa/rangeproof.ts +++ b/modules/sdk-lib-mpc/src/tss/ecdsa/rangeproof.ts @@ -2,7 +2,7 @@ * Zero Knowledge Range Proofs as described in (Two-party generation of DSA signatures)[1]. * [1]: https://reitermk.github.io/papers/2004/IJIS.pdf */ -import { createHash } from 'crypto'; +import { createHash, randomBytes } from 'crypto'; import { BaseCurve } from '../../curves'; import { PublicKey } from 'paillier-bigint'; import { bitLength, randBetween } from 'bigint-crypto-utils'; @@ -194,6 +194,41 @@ export async function verifyNtildeProof( } return true; } + +function rangeProofChallenge( + curve: BaseCurve, + modulusBytes: number, + pk: PublicKey, + c: bigint, + z: bigint, + u: bigint, + w: bigint +): { nonce: Buffer; e: bigint } { + const q = curve.order(); + const hash = createHash('sha256'); + hash.update('\x07\x00\x00\x00\x00\x00\x00\x00'); + hash.update(bigIntToBufferBE(pk.n, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(pk.g, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(c, 2 * modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(z, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(u, 2 * modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(w, modulusBytes)); + hash.update('$'); + + let nonce: Buffer, e: bigint; + do { + nonce = randomBytes(32); + e = bigIntFromBufferBE(hash.copy().update(nonce).digest()); + } while (e >= q); + + return { nonce, e }; +} + /** * Generate a zero-knowledge range proof that an encrypted value is "small". * @param {BaseCurve} curve An elliptic curve to use for group operations. @@ -226,25 +261,11 @@ export async function prove( const z = (modPow(ntilde.h1, m, ntilde.ntilde) * modPow(ntilde.h2, rho, ntilde.ntilde)) % ntilde.ntilde; const u = (modPow(pk.g, alpha, pk._n2) * modPow(beta, pk.n, pk._n2)) % pk._n2; const w = (modPow(ntilde.h1, alpha, ntilde.ntilde) * modPow(ntilde.h2, gamma, ntilde.ntilde)) % ntilde.ntilde; - const hash = createHash('sha256'); - hash.update('\x06\x00\x00\x00\x00\x00\x00\x00'); - hash.update(bigIntToBufferBE(pk.n, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(pk.g, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(c, 2 * modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(z, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(u, 2 * modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(w, modulusBytes)); - hash.update('$'); - const e = bigIntFromBufferBE(hash.digest()) % q; + const { nonce, e } = rangeProofChallenge(curve, modulusBytes, pk, c, z, u, w); const s = (modPow(r, e, pk.n) * beta) % pk.n; const s1 = e * m + alpha; const s2 = e * rho + gamma; - return { z, u, w, s, s1, s2 }; + return { z, u, w, nonce, s, s1, s2 }; } /** @@ -275,7 +296,11 @@ export function verify( return false; } const hash = createHash('sha256'); - hash.update('\x06\x00\x00\x00\x00\x00\x00\x00'); + if (proof.nonce) { + hash.update('\x07\x00\x00\x00\x00\x00\x00\x00'); + } else { + hash.update('\x06\x00\x00\x00\x00\x00\x00\x00'); + } hash.update(bigIntToBufferBE(pk.n, modulusBytes)); hash.update('$'); hash.update(bigIntToBufferBE(pk.g, modulusBytes)); @@ -288,7 +313,15 @@ export function verify( hash.update('$'); hash.update(bigIntToBufferBE(proof.w, modulusBytes)); hash.update('$'); - const e = bigIntFromBufferBE(hash.digest()) % q; + let e: bigint; + if (proof.nonce) { + e = bigIntFromBufferBE(hash.update(proof.nonce).digest()); + if (e >= q) { + return false; + } + } else { + e = bigIntFromBufferBE(hash.digest()) % q; + } let products: bigint; products = (modPow(pk.g, proof.s1, pk._n2) * modPow(proof.s, pk.n, pk._n2) * modPow(c, -e, pk._n2)) % pk._n2; if (proof.u !== products) { @@ -301,6 +334,55 @@ export function verify( return proof.w === products; } +function rangeProofWithCheckChallenge( + curve: BaseCurve, + modulusBytes: number, + pk: PublicKey, + X: bigint, + c1: bigint, + c2: bigint, + u: bigint, + z: bigint, + zprm: bigint, + t: bigint, + v: bigint, + w: bigint +): { nonce: Buffer; e: bigint } { + const q = curve.order(); + const hash = createHash('sha256'); + hash.update('\x0e\x00\x00\x00\x00\x00\x00\x00'); + hash.update(bigIntToBufferBE(pk.n, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(pk.g, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(X, 33)); + hash.update('$'); + hash.update(bigIntToBufferBE(c1, 2 * modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(c2, 2 * modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(u, 33)); + hash.update('$'); + hash.update(bigIntToBufferBE(z, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(zprm, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(t, modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(v, 2 * modulusBytes)); + hash.update('$'); + hash.update(bigIntToBufferBE(w, modulusBytes)); + hash.update('$'); + + let nonce: Buffer, e: bigint; + do { + nonce = randomBytes(32); + e = bigIntFromBufferBE(hash.copy().update(nonce).digest()); + } while (e >= q); + + return { nonce, e }; +} + /** * Generate a zero-knowledge range proof that a homomorphically manipulated value is "small". * @param {BaseCurve} curve An elliptic curve to use for group operations. @@ -347,37 +429,13 @@ export async function proveWithCheck( const v = (((modPow(c1, alpha, pk._n2) * modPow(pk.g, gamma, pk._n2)) % pk._n2) * modPow(beta, pk.n, pk._n2)) % pk._n2; const w = (modPow(ntilde.h1, gamma, ntilde.ntilde) * modPow(ntilde.h2, tau, ntilde.ntilde)) % ntilde.ntilde; - const hash = createHash('sha256'); - hash.update('\x0d\x00\x00\x00\x00\x00\x00\x00'); - hash.update(bigIntToBufferBE(pk.n, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(pk.g, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(X, 33)); - hash.update('$'); - hash.update(bigIntToBufferBE(c1, 2 * modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(c2, 2 * modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(u, 33)); - hash.update('$'); - hash.update(bigIntToBufferBE(z, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(zprm, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(t, modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(v, 2 * modulusBytes)); - hash.update('$'); - hash.update(bigIntToBufferBE(w, modulusBytes)); - hash.update('$'); - const e = bigIntFromBufferBE(hash.digest()) % q; + const { nonce, e } = rangeProofWithCheckChallenge(curve, modulusBytes, pk, X, c1, c2, u, z, zprm, t, v, w); const s = (modPow(r, e, pk.n) * beta) % pk.n; const s1 = e * x + alpha; const s2 = e * rho + rhoprm; const t1 = e * y + gamma; const t2 = e * sigma + tau; - return { z, zprm, t, v, w, s, s1, s2, t1, t2, u }; + return { z, zprm, t, v, w, nonce, s, s1, s2, t1, t2, u }; } /** @@ -413,7 +471,11 @@ export function verifyWithCheck( return false; } const hash = createHash('sha256'); - hash.update('\x0d\x00\x00\x00\x00\x00\x00\x00'); + if (proof.nonce) { + hash.update('\x0e\x00\x00\x00\x00\x00\x00\x00'); + } else { + hash.update('\x0d\x00\x00\x00\x00\x00\x00\x00'); + } hash.update(bigIntToBufferBE(pk.n, modulusBytes)); hash.update('$'); hash.update(bigIntToBufferBE(pk.g, modulusBytes)); @@ -436,13 +498,21 @@ export function verifyWithCheck( hash.update('$'); hash.update(bigIntToBufferBE(proof.w, modulusBytes)); hash.update('$'); - const e = bigIntFromBufferBE(hash.digest()) % q; + let e: bigint; + if (proof.nonce) { + e = bigIntFromBufferBE(hash.update(proof.nonce).digest()); + if (e >= q) { + return false; + } + } else { + e = bigIntFromBufferBE(hash.digest()) % q; + } const gS1 = curve.basePointMult(curve.scalarReduce(proof.s1)); const xEU = curve.pointAdd(curve.pointMultiply(X, e), proof.u); if (gS1 !== xEU) { return false; } - let left, right; + let left: bigint, right: bigint; const h1ExpS1 = modPow(ntilde.h1, proof.s1, ntilde.ntilde); const h2ExpS2 = modPow(ntilde.h2, proof.s2, ntilde.ntilde); left = (h1ExpS1 * h2ExpS2) % ntilde.ntilde; diff --git a/modules/sdk-lib-mpc/src/tss/ecdsa/types.ts b/modules/sdk-lib-mpc/src/tss/ecdsa/types.ts index da919605fc..5367792dc9 100644 --- a/modules/sdk-lib-mpc/src/tss/ecdsa/types.ts +++ b/modules/sdk-lib-mpc/src/tss/ecdsa/types.ts @@ -207,6 +207,7 @@ export interface RangeProof { z: bigint; u: bigint; w: bigint; + nonce?: Buffer; s: bigint; s1: bigint; s2: bigint; @@ -219,6 +220,7 @@ export interface RangeProofWithCheck { t: bigint; v: bigint; w: bigint; + nonce?: Buffer; s: bigint; s1: bigint; s2: bigint;