1
0
mirror of https://github.com/bitcoin/bips.git synced 2024-11-19 01:40:05 +01:00

BIP324 updates

Includes:
* Simpler (but equivalent) ElligatorSwift encoding function & spec
* Improved test vectors
* Test vector generation code
* Code for converting test vectors for libsecp256k1 code.
* Code for running test vectors against SwiftEC paper authors' code.
* Miscellaneous reference code improvements (style, comments).
This commit is contained in:
Pieter Wuille 2023-01-11 17:39:32 -05:00
parent 2361582f0b
commit cc177ab7bc
10 changed files with 837 additions and 106 deletions

View File

@ -247,19 +247,19 @@ To find encodings of a given X coordinate ''x'', we first need the inverse of ''
* ''XSwiftECInv(x, u, case)'':
** If ''case & 2 = 0'':
*** If ''lift_x(-x - u)'' succeeds, return ''None''.
*** Let ''v = x'' if ''case & 1 = 0''; let ''v = -x - u (mod p)'' otherwise.
*** Let ''v = x''.
*** Let ''s = -(u<sup>3</sup> + 7)/(u<sup>2</sup> + uv + v<sup>2</sup>) (mod p)''.
** If ''case & 2 = 2'':
*** Let ''s = x - u (mod p)''.
*** If ''s = 0'', return ''None''.
*** Let ''r'' be the square root of ''-s(4(u<sup>3</sup> + 7) + 3u<sup>2</sup>s) (mod p).''<ref name="modsqrt">'''How to compute a square root mod ''p''?''' Due to the structure of ''p'', a candidate for the square root of ''a'' mod ''p'' can be computed as ''x = a<sup>(p+1)/4</sup> mod p''. If ''a'' is not a square mod ''p'', this formula returns the square root of ''-a mod p'' instead, so it is necessary to verify that ''x<sup>2</sup> mod p = a''. If that is the case ''-x mod p'' is a solution too, but we define "the" square root to be equal to that expression (the square root will therefore always be a square itself, as ''(p+1)/4'' is even). This algorithm is a specialization of the [https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm Tonelli-Shanks algorithm].</ref> Return ''None'' if it does not exist.
*** If ''case & 1 = 1'':
**** If ''r = 0'', return ''None''.
**** let ''r = -r (mod p)''.
** If ''case & 1 = 1'' and ''r = 0'', return ''None''.
*** Let ''v = (-u + r/s)/2''.
** Let ''w'' be the square root of ''s (mod p)''. Return ''None'' if it does not exist.
** If ''case & 4 = 4'', let ''w = -w (mod p)''.
** Return ''w(u(c - 1)/2 - v)''.
** If ''case & 5 = 0'', return ''-w(u(1 - c)/2 + v)''.
** If ''case & 5 = 1'', return ''w(u(1 + c)/2 + v)''.
** If ''case & 5 = 4'', return ''w(u(1 - c)/2 + v)''.
** If ''case & 5 = 5'', return ''-w(u(1 + c)/2 + v)''.
The overall ''XElligatorSwift'' algorithm, matching the name used in the paper, then uses this inverse to randomly''<ref name="ellswift_helps_parroting">'''Can the ElligatorSwift encoding be used to construct public key encodings that satisfy a certain structure (and not pseudorandom)?''' The algorithm chooses the first 32 bytes (i.e., the value ''u'') and then computes a corresponding ''t'' such that the mapping to the curve point holds. In general, picking ''u'' from a uniformly random distribution provides pseudorandomness. But we can also fix any of the 32 bytes in ''u'', and the algorithm will still find a corresponding ''t''. The fact that it is possible to fix the first 32 bytes, combined with the garbage bytes in the handshake, provides a limited but very simple method of parroting other protocols such as [https://tls13.xargs.org/ TLS 1.3], which can be deployed by one of the peers without explicit support from the other peer. More general methods of parroting, e.g., introduced by defining new protocol or a protocol upgrade, are not precluded.</ref> sample encodings of ''x'':
@ -586,8 +586,8 @@ Peers supporting the v2 transport protocol signal support by advertising the <co
== Test Vectors ==
For development and testing purposes, we provide a collection of test vectors in CSV format, and a naive, highly inefficient, [[bip-0324/reference.py|reference implementation]] of the relevant algorithms. This code is for demonstration purposes only:
* [[bip-0324/xelligatorswift_test_vectors.csv|XElligatorSwift vectors]] give examples of ElligatorSwift-encoded public keys, and the X coordinate they map to.
* [[bip-0324/xswiftec_test_vectors.csv|XSwiftEC vectors]] give examples of ''(u, x)'' pairs, and the various ''t'' values that ''xswiftec_inv'' maps them to.
* [[bip-0324/ellswift_decode_test_vectors.csv|XElligatorSwift decoding vectors]] give examples of ElligatorSwift-encoded public keys, and the X coordinate they map to.
* [[bip-0324/xswiftec_inv_test_vectors.csv|XSwiftECInv vectors]] give examples of ''(u, x)'' pairs, and the various ''t'' values that ''xswiftec_inv'' maps them to.
* [[bip-0324/packet_encoding_test_vectors.csv|Packet encoding vectors]] illustrate the lifecycle of the authenticated encryption scheme proposed in this document.
== Rationale and References ==

View File

@ -0,0 +1,77 @@
ellswift,x,comment
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2)
000000000000000000000000000000000000000000000000000000000000000001d3475bf7655b0fb2d852921035b2ef607f49069b97454e6795251062741771,b5da00b73cd6560520e7c364086e7cd23a34bf60d0e707be9fc34d4cd5fdfa2c,u%p=0;valid_x(x1)
000000000000000000000000000000000000000000000000000000000000000082277c4a71f9d22e66ece523f8fa08741a7c0912c66a69ce68514bfd3515b49f,f482f2e241753ad0fb89150d8491dc1e34ff0b8acfbb442cfe999e2e5e6fd1d2,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
00000000000000000000000000000000000000000000000000000000000000008421cc930e77c9f514b6915c3dbe2a94c6d8f690b5b739864ba6789fb8a55dd0,9f59c40275f5085a006f05dae77eb98c6fd0db1ab4a72ac47eae90a4fc9e57e0,u%p=0;valid_x(x2)
0000000000000000000000000000000000000000000000000000000000000000bde70df51939b94c9c24979fa7dd04ebd9b3572da7802290438af2a681895441,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9fffffd6b,u%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3)
0000000000000000000000000000000000000000000000000000000000000000d19c182d2759cd99824228d94799f8c6557c38a1c0d6779b9d4b729c6f1ccc42,70720db7e238d04121f5b1afd8cc5ad9d18944c6bdc94881f502b7a3af3aecff,u%p=0;valid_x(x3)
0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2);t>=p
0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2664bbd5,50873db31badcc71890e4f67753a65757f97aaa7dd5f1e82b753ace32219064b,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7028de7d,1eea9cc59cfcf2fa151ac6c274eea4110feb4f7b68c5965732e9992e976ef68e,u%p=0;valid_x(x2);t>=p
0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffcbcfb7e7,12303941aedc208880735b1f1795c8e55be520ea93e103357b5d2adb7ed59b8e,u%p=0;valid_x(x1);t>=p
0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffff3113ad9,7eed6b70e7b0767c7d7feac04e57aa2a12fef5e0f48f878fcbb88b3b6b5e0783,u%p=0;valid_x(x3);t>=p
0a2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f8530000000000000000000000000000000000000000000000000000000000000000,532167c11200b08c0e84a354e74dcc40f8b25f4fe686e30869526366278a0688,t%p=0;(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
0a2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f853fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,532167c11200b08c0e84a354e74dcc40f8b25f4fe686e30869526366278a0688,t%p=0;(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
0ffde9ca81d751e9cdaffc1a50779245320b28996dbaf32f822f20117c22fbd6c74d99efceaa550f1ad1c0f43f46e7ff1ee3bd0162b7bf55f2965da9c3450646,74e880b3ffd18fe3cddf7902522551ddf97fa4a35a3cfda8197f947081a57b8f,valid_x(x3)
0ffde9ca81d751e9cdaffc1a50779245320b28996dbaf32f822f20117c22fbd6ffffffffffffffffffffffffffffffffffffffffffffffffffffffff156ca896,377b643fce2271f64e5c8101566107c1be4980745091783804f654781ac9217c,valid_x(x2);t>=p
123658444f32be8f02ea2034afa7ef4bbe8adc918ceb49b12773b625f490b368ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8dc5fe11,ed16d65cf3a9538fcb2c139f1ecbc143ee14827120cbc2659e667256800b8142,(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
146f92464d15d36e35382bd3ca5b0f976c95cb08acdcf2d5b3570617990839d7ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3145e93b,0d5cd840427f941f65193079ab8e2e83024ef2ee7ca558d88879ffd879fb6657,(u'^3+t'^2+7)%p=0;valid_x(x3);t>=p
15fdf5cf09c90759add2272d574d2bb5fe1429f9f3c14c65e3194bf61b82aa73ffffffffffffffffffffffffffffffffffffffffffffffffffffffff04cfd906,16d0e43946aec93f62d57eb8cde68951af136cf4b307938dd1447411e07bffe1,(u'^3+t'^2+7)%p=0;valid_x(x2);t>=p
1f67edf779a8a649d6def60035f2fa22d022dd359079a1a144073d84f19b92d50000000000000000000000000000000000000000000000000000000000000000,025661f9aba9d15c3118456bbe980e3e1b8ba2e047c737a4eb48a040bb566f6c,t%p=0;valid_x(x2)
1f67edf779a8a649d6def60035f2fa22d022dd359079a1a144073d84f19b92d5fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,025661f9aba9d15c3118456bbe980e3e1b8ba2e047c737a4eb48a040bb566f6c,t%p=0;valid_x(x2);t>=p
1fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff507fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,98bec3b2a351fa96cfd191c1778351931b9e9ba9ad1149f6d9eadca80981b801,t%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
4056a34a210eec7892e8820675c860099f857b26aad85470ee6d3cf1304a9dcf375e70374271f20b13c9986ed7d3c17799698cfc435dbed3a9f34b38c823c2b4,868aac2003b29dbcad1a3e803855e078a89d16543ac64392d122417298cec76e,(u'^3-t'^2+7)%p=0;valid_x(x3)
4197ec3723c654cfdd32ab075506648b2ff5070362d01a4fff14b336b78f963fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3ab1e95,ba5a6314502a8952b8f456e085928105f665377a8ce27726a5b0eb7ec1ac0286,(u'^3+t'^2+7)%p=0;valid_x(x1);t>=p
47eb3e208fedcdf8234c9421e9cd9a7ae873bfbdbc393723d1ba1e1e6a8e6b24ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7cd12cb1,d192d52007e541c9807006ed0468df77fd214af0a795fe119359666fdcf08f7c,(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
5eb9696a2336fe2c3c666b02c755db4c0cfd62825c7b589a7b7bb442e141c1d693413f0052d49e64abec6d5831d66c43612830a17df1fe4383db896468100221,ef6e1da6d6c7627e80f7a7234cb08a022c1ee1cf29e4d0f9642ae924cef9eb38,(u'^3+t'^2+7)%p=0;valid_x(x1)
7bf96b7b6da15d3476a2b195934b690a3a3de3e8ab8474856863b0de3af90b0e0000000000000000000000000000000000000000000000000000000000000000,50851dfc9f418c314a437295b24feeea27af3d0cd2308348fda6e21c463e46ff,t%p=0;valid_x(x1)
7bf96b7b6da15d3476a2b195934b690a3a3de3e8ab8474856863b0de3af90b0efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,50851dfc9f418c314a437295b24feeea27af3d0cd2308348fda6e21c463e46ff,t%p=0;valid_x(x1);t>=p
851b1ca94549371c4f1f7187321d39bf51c6b7fb61f7cbf027c9da62021b7a65fc54c96837fb22b362eda63ec52ec83d81bedd160c11b22d965d9f4a6d64d251,3e731051e12d33237eb324f2aa5b16bb868eb49a1aa1fadc19b6e8761b5a5f7b,(u'^3+t'^2+7)%p=0;valid_x(x2)
943c2f775108b737fe65a9531e19f2fc2a197f5603e3a2881d1d83e4008f91250000000000000000000000000000000000000000000000000000000000000000,311c61f0ab2f32b7b1f0223fa72f0a78752b8146e46107f8876dd9c4f92b2942,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
943c2f775108b737fe65a9531e19f2fc2a197f5603e3a2881d1d83e4008f9125fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,311c61f0ab2f32b7b1f0223fa72f0a78752b8146e46107f8876dd9c4f92b2942,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
a0f18492183e61e8063e573606591421b06bc3513631578a73a39c1c3306239f2f32904f0d2a33ecca8a5451705bb537d3bf44e071226025cdbfd249fe0f7ad6,97a09cf1a2eae7c494df3c6f8a9445bfb8c09d60832f9b0b9d5eabe25fbd14b9,valid_x(x1)
a1ed0a0bd79d8a23cfe4ec5fef5ba5cccfd844e4ff5cb4b0f2e71627341f1c5b17c499249e0ac08d5d11ea1c2c8ca7001616559a7994eadec9ca10fb4b8516dc,65a89640744192cdac64b2d21ddf989cdac7500725b645bef8e2200ae39691f2,valid_x(x2)
ba94594a432721aa3580b84c161d0d134bc354b690404d7cd4ec57c16d3fbe98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffea507dd7,5e0d76564aae92cb347e01a62afd389a9aa401c76c8dd227543dc9cd0efe685a,valid_x(x1);t>=p
bcaf7219f2f6fbf55fe5e062dce0e48c18f68103f10b8198e974c184750e1be3932016cbf69c4471bd1f656c6a107f1973de4af7086db897277060e25677f19a,2d97f96cac882dfe73dc44db6ce0f1d31d6241358dd5d74eb3d3b50003d24c2b,valid_x(x3);valid_x(x2);valid_x(x1)
bcaf7219f2f6fbf55fe5e062dce0e48c18f68103f10b8198e974c184750e1be3ffffffffffffffffffffffffffffffffffffffffffffffffffffffff6507d09a,e7008afe6e8cbd5055df120bd748757c686dadb41cce75e4addcc5e02ec02b44,valid_x(x3);valid_x(x2);valid_x(x1);t>=p
c5981bae27fd84401c72a155e5707fbb811b2b620645d1028ea270cbe0ee225d4b62aa4dca6506c1acdbecc0552569b4b21436a5692e25d90d3bc2eb7ce24078,948b40e7181713bc018ec1702d3d054d15746c59a7020730dd13ecf985a010d7,(u'^3+t'^2+7)%p=0;valid_x(x3)
c894ce48bfec433014b931a6ad4226d7dbd8eaa7b6e3faa8d0ef94052bcf8cff336eeb3919e2b4efb746c7f71bbca7e9383230fbbc48ffafe77e8bcc69542471,f1c91acdc2525330f9b53158434a4d43a1c547cff29f15506f5da4eb4fe8fa5a,(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
cbb0deab125754f1fdb2038b0434ed9cb3fb53ab735391129994a535d925f6730000000000000000000000000000000000000000000000000000000000000000,872d81ed8831d9998b67cb7105243edbf86c10edfebb786c110b02d07b2e67cd,t%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
d917b786dac35670c330c9c5ae5971dfb495c8ae523ed97ee2420117b171f41effffffffffffffffffffffffffffffffffffffffffffffffffffffff2001f6f6,e45b71e110b831f2bdad8651994526e58393fde4328b1ec04d59897142584691,valid_x(x3);t>=p
e28bd8f5929b467eb70e04332374ffb7e7180218ad16eaa46b7161aa679eb4260000000000000000000000000000000000000000000000000000000000000000,66b8c980a75c72e598d383a35a62879f844242ad1e73ff12edaa59f4e58632b5,t%p=0;valid_x(x3)
e28bd8f5929b467eb70e04332374ffb7e7180218ad16eaa46b7161aa679eb426fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,66b8c980a75c72e598d383a35a62879f844242ad1e73ff12edaa59f4e58632b5,t%p=0;valid_x(x3);t>=p
e7ee5814c1706bf8a89396a9b032bc014c2cac9c121127dbf6c99278f8bb53d1dfd04dbcda8e352466b6fcd5f2dea3e17d5e133115886eda20db8a12b54de71b,e842c6e3529b234270a5e97744edc34a04d7ba94e44b6d2523c9cf0195730a50,(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
f292e46825f9225ad23dc057c1d91c4f57fcb1386f29ef10481cb1d22518593fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7011c989,3cea2c53b8b0170166ac7da67194694adacc84d56389225e330134dab85a4d55,(u'^3-t'^2+7)%p=0;valid_x(x3);t>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f01d3475bf7655b0fb2d852921035b2ef607f49069b97454e6795251062741771,b5da00b73cd6560520e7c364086e7cd23a34bf60d0e707be9fc34d4cd5fdfa2c,u%p=0;valid_x(x1);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9fffffd6b,u%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f82277c4a71f9d22e66ece523f8fa08741a7c0912c66a69ce68514bfd3515b49f,f482f2e241753ad0fb89150d8491dc1e34ff0b8acfbb442cfe999e2e5e6fd1d2,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8421cc930e77c9f514b6915c3dbe2a94c6d8f690b5b739864ba6789fb8a55dd0,9f59c40275f5085a006f05dae77eb98c6fd0db1ab4a72ac47eae90a4fc9e57e0,u%p=0;valid_x(x2);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fd19c182d2759cd99824228d94799f8c6557c38a1c0d6779b9d4b729c6f1ccc42,70720db7e238d04121f5b1afd8cc5ad9d18944c6bdc94881f502b7a3af3aecff,u%p=0;valid_x(x3);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2);u>=p;t>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffff2664bbd5,50873db31badcc71890e4f67753a65757f97aaa7dd5f1e82b753ace32219064b,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7028de7d,1eea9cc59cfcf2fa151ac6c274eea4110feb4f7b68c5965732e9992e976ef68e,u%p=0;valid_x(x2);u>=p;t>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffcbcfb7e7,12303941aedc208880735b1f1795c8e55be520ea93e103357b5d2adb7ed59b8e,u%p=0;valid_x(x1);u>=p;t>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3113ad9,7eed6b70e7b0767c7d7feac04e57aa2a12fef5e0f48f878fcbb88b3b6b5e0783,u%p=0;valid_x(x3);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff13cea4a70000000000000000000000000000000000000000000000000000000000000000,649984435b62b4a25d40c6133e8d9ab8c53d4b059ee8a154a3be0fcf4e892edb,t%p=0;valid_x(x1);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff13cea4a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,649984435b62b4a25d40c6133e8d9ab8c53d4b059ee8a154a3be0fcf4e892edb,t%p=0;valid_x(x1);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff15028c590063f64d5a7f1c14915cd61eac886ab295bebd91992504cf77edb028bdd6267f,3fde5713f8282eead7d39d4201f44a7c85a5ac8a0681f35e54085c6b69543374,(u'^3+t'^2+7)%p=0;valid_x(x2);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2715de860000000000000000000000000000000000000000000000000000000000000000,3524f77fa3a6eb4389c3cb5d27f1f91462086429cd6c0cb0df43ea8f1e7b3fb4,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2715de86fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,3524f77fa3a6eb4389c3cb5d27f1f91462086429cd6c0cb0df43ea8f1e7b3fb4,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2c2c5709e7156c417717f2feab147141ec3da19fb759575cc6e37b2ea5ac9309f26f0f66,d2469ab3e04acbb21c65a1809f39caafe7a77c13d10f9dd38f391c01dc499c52,(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3a08cc1efffffffffffffffffffffffffffffffffffffffffffffffffffffffff760e9f0,38e2a5ce6a93e795e16d2c398bc99f0369202ce21e8f09d56777b40fc512bccc,valid_x(x3);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e91257d932016cbf69c4471bd1f656c6a107f1973de4af7086db897277060e25677f19a,864b3dc902c376709c10a93ad4bbe29fce0012f3dc8672c6286bba28d7d6d6fc,valid_x(x3);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff795d6c1c322cadf599dbb86481522b3cc55f15a67932db2afa0111d9ed6981bcd124bf44,766dfe4a700d9bee288b903ad58870e3d4fe2f0ef780bcac5c823f320d9a9bef,(u'^3+t'^2+7)%p=0;valid_x(x1);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e426f0392389078c12b1a89e9542f0593bc96b6bfde8224f8654ef5d5cda935a3582194,faec7bc1987b63233fbc5f956edbf37d54404e7461c58ab8631bc68e451a0478,valid_x(x1);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff91192139ffffffffffffffffffffffffffffffffffffffffffffffffffffffff45f0f1eb,ec29a50bae138dbf7d8e24825006bb5fc1a2cc1243ba335bc6116fb9e498ec1f,valid_x(x2);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff98eb9ab76e84499c483b3bf06214abfe065dddf43b8601de596d63b9e45a166a580541fe,1e0ff2dee9b09b136292a9e910f0d6ac3e552a644bba39e64e9dd3e3bbd3d4d4,(u'^3-t'^2+7)%p=0;valid_x(x3);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b77b7f2c74d99efceaa550f1ad1c0f43f46e7ff1ee3bd0162b7bf55f2965da9c3450646,8b7dd5c3edba9ee97b70eff438f22dca9849c8254a2f3345a0a572ffeaae0928,valid_x(x2);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b77b7f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffff156ca896,0881950c8f51d6b9a6387465d5f12609ef1bb25412a08a74cb2dfb200c74bfbf,valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffa2f5cd838816c16c4fe8a1661d606fdb13cf9af04b979a2e159a09409ebc8645d58fde02,2f083207b9fd9b550063c31cd62b8746bd543bdc5bbf10e3a35563e927f440c8,(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb13f75c00000000000000000000000000000000000000000000000000000000000000000,4f51e0be078e0cddab2742156adba7e7a148e73157072fd618cd60942b146bd0,t%p=0;valid_x(x3);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb13f75c0fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,4f51e0be078e0cddab2742156adba7e7a148e73157072fd618cd60942b146bd0,t%p=0;valid_x(x3);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7bc1f8d0000000000000000000000000000000000000000000000000000000000000000,16c2ccb54352ff4bd794f6efd613c72197ab7082da5b563bdf9cb3edaafe74c2,t%p=0;valid_x(x2);u>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7bc1f8dfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,16c2ccb54352ff4bd794f6efd613c72197ab7082da5b563bdf9cb3edaafe74c2,t%p=0;valid_x(x2);u>=p;t>=p
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffef64d162750546ce42b0431361e52d4f5242d8f24f33e6b1f99b591647cbc808f462af51,d41244d11ca4f65240687759f95ca9efbab767ededb38fd18c36e18cd3b6f6a9,(u'^3+t'^2+7)%p=0;valid_x(x3);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0e5be52372dd6e894b2a326fc3605a6e8f3c69c710bf27d630dfe2004988b78eb6eab36,64bf84dd5e03670fdb24c0f5d3c2c365736f51db6c92d95010716ad2d36134c8,valid_x(x3);valid_x(x2);valid_x(x1);u>=p
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefbb982fffffffffffffffffffffffffffffffffffffffffffffffffffffffff6d6db1f,1c92ccdfcf4ac550c28db57cff0c8515cb26936c786584a70114008d6c33a34b,valid_x(x1);u>=p;t>=p
1 ellswift x comment
2 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c u%p=0;t%p=0;valid_x(x2)
3 000000000000000000000000000000000000000000000000000000000000000001d3475bf7655b0fb2d852921035b2ef607f49069b97454e6795251062741771 b5da00b73cd6560520e7c364086e7cd23a34bf60d0e707be9fc34d4cd5fdfa2c u%p=0;valid_x(x1)
4 000000000000000000000000000000000000000000000000000000000000000082277c4a71f9d22e66ece523f8fa08741a7c0912c66a69ce68514bfd3515b49f f482f2e241753ad0fb89150d8491dc1e34ff0b8acfbb442cfe999e2e5e6fd1d2 u%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
5 00000000000000000000000000000000000000000000000000000000000000008421cc930e77c9f514b6915c3dbe2a94c6d8f690b5b739864ba6789fb8a55dd0 9f59c40275f5085a006f05dae77eb98c6fd0db1ab4a72ac47eae90a4fc9e57e0 u%p=0;valid_x(x2)
6 0000000000000000000000000000000000000000000000000000000000000000bde70df51939b94c9c24979fa7dd04ebd9b3572da7802290438af2a681895441 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9fffffd6b u%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3)
7 0000000000000000000000000000000000000000000000000000000000000000d19c182d2759cd99824228d94799f8c6557c38a1c0d6779b9d4b729c6f1ccc42 70720db7e238d04121f5b1afd8cc5ad9d18944c6bdc94881f502b7a3af3aecff u%p=0;valid_x(x3)
8 0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c u%p=0;t%p=0;valid_x(x2);t>=p
9 0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2664bbd5 50873db31badcc71890e4f67753a65757f97aaa7dd5f1e82b753ace32219064b u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
10 0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7028de7d 1eea9cc59cfcf2fa151ac6c274eea4110feb4f7b68c5965732e9992e976ef68e u%p=0;valid_x(x2);t>=p
11 0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffcbcfb7e7 12303941aedc208880735b1f1795c8e55be520ea93e103357b5d2adb7ed59b8e u%p=0;valid_x(x1);t>=p
12 0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffff3113ad9 7eed6b70e7b0767c7d7feac04e57aa2a12fef5e0f48f878fcbb88b3b6b5e0783 u%p=0;valid_x(x3);t>=p
13 0a2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f8530000000000000000000000000000000000000000000000000000000000000000 532167c11200b08c0e84a354e74dcc40f8b25f4fe686e30869526366278a0688 t%p=0;(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
14 0a2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f853fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 532167c11200b08c0e84a354e74dcc40f8b25f4fe686e30869526366278a0688 t%p=0;(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
15 0ffde9ca81d751e9cdaffc1a50779245320b28996dbaf32f822f20117c22fbd6c74d99efceaa550f1ad1c0f43f46e7ff1ee3bd0162b7bf55f2965da9c3450646 74e880b3ffd18fe3cddf7902522551ddf97fa4a35a3cfda8197f947081a57b8f valid_x(x3)
16 0ffde9ca81d751e9cdaffc1a50779245320b28996dbaf32f822f20117c22fbd6ffffffffffffffffffffffffffffffffffffffffffffffffffffffff156ca896 377b643fce2271f64e5c8101566107c1be4980745091783804f654781ac9217c valid_x(x2);t>=p
17 123658444f32be8f02ea2034afa7ef4bbe8adc918ceb49b12773b625f490b368ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8dc5fe11 ed16d65cf3a9538fcb2c139f1ecbc143ee14827120cbc2659e667256800b8142 (u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
18 146f92464d15d36e35382bd3ca5b0f976c95cb08acdcf2d5b3570617990839d7ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3145e93b 0d5cd840427f941f65193079ab8e2e83024ef2ee7ca558d88879ffd879fb6657 (u'^3+t'^2+7)%p=0;valid_x(x3);t>=p
19 15fdf5cf09c90759add2272d574d2bb5fe1429f9f3c14c65e3194bf61b82aa73ffffffffffffffffffffffffffffffffffffffffffffffffffffffff04cfd906 16d0e43946aec93f62d57eb8cde68951af136cf4b307938dd1447411e07bffe1 (u'^3+t'^2+7)%p=0;valid_x(x2);t>=p
20 1f67edf779a8a649d6def60035f2fa22d022dd359079a1a144073d84f19b92d50000000000000000000000000000000000000000000000000000000000000000 025661f9aba9d15c3118456bbe980e3e1b8ba2e047c737a4eb48a040bb566f6c t%p=0;valid_x(x2)
21 1f67edf779a8a649d6def60035f2fa22d022dd359079a1a144073d84f19b92d5fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 025661f9aba9d15c3118456bbe980e3e1b8ba2e047c737a4eb48a040bb566f6c t%p=0;valid_x(x2);t>=p
22 1fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff507fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 98bec3b2a351fa96cfd191c1778351931b9e9ba9ad1149f6d9eadca80981b801 t%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
23 4056a34a210eec7892e8820675c860099f857b26aad85470ee6d3cf1304a9dcf375e70374271f20b13c9986ed7d3c17799698cfc435dbed3a9f34b38c823c2b4 868aac2003b29dbcad1a3e803855e078a89d16543ac64392d122417298cec76e (u'^3-t'^2+7)%p=0;valid_x(x3)
24 4197ec3723c654cfdd32ab075506648b2ff5070362d01a4fff14b336b78f963fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3ab1e95 ba5a6314502a8952b8f456e085928105f665377a8ce27726a5b0eb7ec1ac0286 (u'^3+t'^2+7)%p=0;valid_x(x1);t>=p
25 47eb3e208fedcdf8234c9421e9cd9a7ae873bfbdbc393723d1ba1e1e6a8e6b24ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7cd12cb1 d192d52007e541c9807006ed0468df77fd214af0a795fe119359666fdcf08f7c (u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
26 5eb9696a2336fe2c3c666b02c755db4c0cfd62825c7b589a7b7bb442e141c1d693413f0052d49e64abec6d5831d66c43612830a17df1fe4383db896468100221 ef6e1da6d6c7627e80f7a7234cb08a022c1ee1cf29e4d0f9642ae924cef9eb38 (u'^3+t'^2+7)%p=0;valid_x(x1)
27 7bf96b7b6da15d3476a2b195934b690a3a3de3e8ab8474856863b0de3af90b0e0000000000000000000000000000000000000000000000000000000000000000 50851dfc9f418c314a437295b24feeea27af3d0cd2308348fda6e21c463e46ff t%p=0;valid_x(x1)
28 7bf96b7b6da15d3476a2b195934b690a3a3de3e8ab8474856863b0de3af90b0efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 50851dfc9f418c314a437295b24feeea27af3d0cd2308348fda6e21c463e46ff t%p=0;valid_x(x1);t>=p
29 851b1ca94549371c4f1f7187321d39bf51c6b7fb61f7cbf027c9da62021b7a65fc54c96837fb22b362eda63ec52ec83d81bedd160c11b22d965d9f4a6d64d251 3e731051e12d33237eb324f2aa5b16bb868eb49a1aa1fadc19b6e8761b5a5f7b (u'^3+t'^2+7)%p=0;valid_x(x2)
30 943c2f775108b737fe65a9531e19f2fc2a197f5603e3a2881d1d83e4008f91250000000000000000000000000000000000000000000000000000000000000000 311c61f0ab2f32b7b1f0223fa72f0a78752b8146e46107f8876dd9c4f92b2942 t%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
31 943c2f775108b737fe65a9531e19f2fc2a197f5603e3a2881d1d83e4008f9125fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 311c61f0ab2f32b7b1f0223fa72f0a78752b8146e46107f8876dd9c4f92b2942 t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
32 a0f18492183e61e8063e573606591421b06bc3513631578a73a39c1c3306239f2f32904f0d2a33ecca8a5451705bb537d3bf44e071226025cdbfd249fe0f7ad6 97a09cf1a2eae7c494df3c6f8a9445bfb8c09d60832f9b0b9d5eabe25fbd14b9 valid_x(x1)
33 a1ed0a0bd79d8a23cfe4ec5fef5ba5cccfd844e4ff5cb4b0f2e71627341f1c5b17c499249e0ac08d5d11ea1c2c8ca7001616559a7994eadec9ca10fb4b8516dc 65a89640744192cdac64b2d21ddf989cdac7500725b645bef8e2200ae39691f2 valid_x(x2)
34 ba94594a432721aa3580b84c161d0d134bc354b690404d7cd4ec57c16d3fbe98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffea507dd7 5e0d76564aae92cb347e01a62afd389a9aa401c76c8dd227543dc9cd0efe685a valid_x(x1);t>=p
35 bcaf7219f2f6fbf55fe5e062dce0e48c18f68103f10b8198e974c184750e1be3932016cbf69c4471bd1f656c6a107f1973de4af7086db897277060e25677f19a 2d97f96cac882dfe73dc44db6ce0f1d31d6241358dd5d74eb3d3b50003d24c2b valid_x(x3);valid_x(x2);valid_x(x1)
36 bcaf7219f2f6fbf55fe5e062dce0e48c18f68103f10b8198e974c184750e1be3ffffffffffffffffffffffffffffffffffffffffffffffffffffffff6507d09a e7008afe6e8cbd5055df120bd748757c686dadb41cce75e4addcc5e02ec02b44 valid_x(x3);valid_x(x2);valid_x(x1);t>=p
37 c5981bae27fd84401c72a155e5707fbb811b2b620645d1028ea270cbe0ee225d4b62aa4dca6506c1acdbecc0552569b4b21436a5692e25d90d3bc2eb7ce24078 948b40e7181713bc018ec1702d3d054d15746c59a7020730dd13ecf985a010d7 (u'^3+t'^2+7)%p=0;valid_x(x3)
38 c894ce48bfec433014b931a6ad4226d7dbd8eaa7b6e3faa8d0ef94052bcf8cff336eeb3919e2b4efb746c7f71bbca7e9383230fbbc48ffafe77e8bcc69542471 f1c91acdc2525330f9b53158434a4d43a1c547cff29f15506f5da4eb4fe8fa5a (u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
39 cbb0deab125754f1fdb2038b0434ed9cb3fb53ab735391129994a535d925f6730000000000000000000000000000000000000000000000000000000000000000 872d81ed8831d9998b67cb7105243edbf86c10edfebb786c110b02d07b2e67cd t%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
40 d917b786dac35670c330c9c5ae5971dfb495c8ae523ed97ee2420117b171f41effffffffffffffffffffffffffffffffffffffffffffffffffffffff2001f6f6 e45b71e110b831f2bdad8651994526e58393fde4328b1ec04d59897142584691 valid_x(x3);t>=p
41 e28bd8f5929b467eb70e04332374ffb7e7180218ad16eaa46b7161aa679eb4260000000000000000000000000000000000000000000000000000000000000000 66b8c980a75c72e598d383a35a62879f844242ad1e73ff12edaa59f4e58632b5 t%p=0;valid_x(x3)
42 e28bd8f5929b467eb70e04332374ffb7e7180218ad16eaa46b7161aa679eb426fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 66b8c980a75c72e598d383a35a62879f844242ad1e73ff12edaa59f4e58632b5 t%p=0;valid_x(x3);t>=p
43 e7ee5814c1706bf8a89396a9b032bc014c2cac9c121127dbf6c99278f8bb53d1dfd04dbcda8e352466b6fcd5f2dea3e17d5e133115886eda20db8a12b54de71b e842c6e3529b234270a5e97744edc34a04d7ba94e44b6d2523c9cf0195730a50 (u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
44 f292e46825f9225ad23dc057c1d91c4f57fcb1386f29ef10481cb1d22518593fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7011c989 3cea2c53b8b0170166ac7da67194694adacc84d56389225e330134dab85a4d55 (u'^3-t'^2+7)%p=0;valid_x(x3);t>=p
45 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000 edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c u%p=0;t%p=0;valid_x(x2);u>=p
46 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f01d3475bf7655b0fb2d852921035b2ef607f49069b97454e6795251062741771 b5da00b73cd6560520e7c364086e7cd23a34bf60d0e707be9fc34d4cd5fdfa2c u%p=0;valid_x(x1);u>=p
47 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9fffffd6b u%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);u>=p
48 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f82277c4a71f9d22e66ece523f8fa08741a7c0912c66a69ce68514bfd3515b49f f482f2e241753ad0fb89150d8491dc1e34ff0b8acfbb442cfe999e2e5e6fd1d2 u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
49 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8421cc930e77c9f514b6915c3dbe2a94c6d8f690b5b739864ba6789fb8a55dd0 9f59c40275f5085a006f05dae77eb98c6fd0db1ab4a72ac47eae90a4fc9e57e0 u%p=0;valid_x(x2);u>=p
50 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fd19c182d2759cd99824228d94799f8c6557c38a1c0d6779b9d4b729c6f1ccc42 70720db7e238d04121f5b1afd8cc5ad9d18944c6bdc94881f502b7a3af3aecff u%p=0;valid_x(x3);u>=p
51 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c u%p=0;t%p=0;valid_x(x2);u>=p;t>=p
52 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffff2664bbd5 50873db31badcc71890e4f67753a65757f97aaa7dd5f1e82b753ace32219064b u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
53 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7028de7d 1eea9cc59cfcf2fa151ac6c274eea4110feb4f7b68c5965732e9992e976ef68e u%p=0;valid_x(x2);u>=p;t>=p
54 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffcbcfb7e7 12303941aedc208880735b1f1795c8e55be520ea93e103357b5d2adb7ed59b8e u%p=0;valid_x(x1);u>=p;t>=p
55 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3113ad9 7eed6b70e7b0767c7d7feac04e57aa2a12fef5e0f48f878fcbb88b3b6b5e0783 u%p=0;valid_x(x3);u>=p;t>=p
56 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff13cea4a70000000000000000000000000000000000000000000000000000000000000000 649984435b62b4a25d40c6133e8d9ab8c53d4b059ee8a154a3be0fcf4e892edb t%p=0;valid_x(x1);u>=p
57 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff13cea4a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 649984435b62b4a25d40c6133e8d9ab8c53d4b059ee8a154a3be0fcf4e892edb t%p=0;valid_x(x1);u>=p;t>=p
58 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff15028c590063f64d5a7f1c14915cd61eac886ab295bebd91992504cf77edb028bdd6267f 3fde5713f8282eead7d39d4201f44a7c85a5ac8a0681f35e54085c6b69543374 (u'^3+t'^2+7)%p=0;valid_x(x2);u>=p
59 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2715de860000000000000000000000000000000000000000000000000000000000000000 3524f77fa3a6eb4389c3cb5d27f1f91462086429cd6c0cb0df43ea8f1e7b3fb4 t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
60 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2715de86fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 3524f77fa3a6eb4389c3cb5d27f1f91462086429cd6c0cb0df43ea8f1e7b3fb4 t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
61 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2c2c5709e7156c417717f2feab147141ec3da19fb759575cc6e37b2ea5ac9309f26f0f66 d2469ab3e04acbb21c65a1809f39caafe7a77c13d10f9dd38f391c01dc499c52 (u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
62 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3a08cc1efffffffffffffffffffffffffffffffffffffffffffffffffffffffff760e9f0 38e2a5ce6a93e795e16d2c398bc99f0369202ce21e8f09d56777b40fc512bccc valid_x(x3);u>=p;t>=p
63 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e91257d932016cbf69c4471bd1f656c6a107f1973de4af7086db897277060e25677f19a 864b3dc902c376709c10a93ad4bbe29fce0012f3dc8672c6286bba28d7d6d6fc valid_x(x3);u>=p
64 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff795d6c1c322cadf599dbb86481522b3cc55f15a67932db2afa0111d9ed6981bcd124bf44 766dfe4a700d9bee288b903ad58870e3d4fe2f0ef780bcac5c823f320d9a9bef (u'^3+t'^2+7)%p=0;valid_x(x1);u>=p
65 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e426f0392389078c12b1a89e9542f0593bc96b6bfde8224f8654ef5d5cda935a3582194 faec7bc1987b63233fbc5f956edbf37d54404e7461c58ab8631bc68e451a0478 valid_x(x1);u>=p
66 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff91192139ffffffffffffffffffffffffffffffffffffffffffffffffffffffff45f0f1eb ec29a50bae138dbf7d8e24825006bb5fc1a2cc1243ba335bc6116fb9e498ec1f valid_x(x2);u>=p;t>=p
67 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff98eb9ab76e84499c483b3bf06214abfe065dddf43b8601de596d63b9e45a166a580541fe 1e0ff2dee9b09b136292a9e910f0d6ac3e552a644bba39e64e9dd3e3bbd3d4d4 (u'^3-t'^2+7)%p=0;valid_x(x3);u>=p
68 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b77b7f2c74d99efceaa550f1ad1c0f43f46e7ff1ee3bd0162b7bf55f2965da9c3450646 8b7dd5c3edba9ee97b70eff438f22dca9849c8254a2f3345a0a572ffeaae0928 valid_x(x2);u>=p
69 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b77b7f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffff156ca896 0881950c8f51d6b9a6387465d5f12609ef1bb25412a08a74cb2dfb200c74bfbf valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
70 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffa2f5cd838816c16c4fe8a1661d606fdb13cf9af04b979a2e159a09409ebc8645d58fde02 2f083207b9fd9b550063c31cd62b8746bd543bdc5bbf10e3a35563e927f440c8 (u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
71 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb13f75c00000000000000000000000000000000000000000000000000000000000000000 4f51e0be078e0cddab2742156adba7e7a148e73157072fd618cd60942b146bd0 t%p=0;valid_x(x3);u>=p
72 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb13f75c0fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 4f51e0be078e0cddab2742156adba7e7a148e73157072fd618cd60942b146bd0 t%p=0;valid_x(x3);u>=p;t>=p
73 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7bc1f8d0000000000000000000000000000000000000000000000000000000000000000 16c2ccb54352ff4bd794f6efd613c72197ab7082da5b563bdf9cb3edaafe74c2 t%p=0;valid_x(x2);u>=p
74 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7bc1f8dfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 16c2ccb54352ff4bd794f6efd613c72197ab7082da5b563bdf9cb3edaafe74c2 t%p=0;valid_x(x2);u>=p;t>=p
75 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffef64d162750546ce42b0431361e52d4f5242d8f24f33e6b1f99b591647cbc808f462af51 d41244d11ca4f65240687759f95ca9efbab767ededb38fd18c36e18cd3b6f6a9 (u'^3+t'^2+7)%p=0;valid_x(x3);u>=p
76 fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0e5be52372dd6e894b2a326fc3605a6e8f3c69c710bf27d630dfe2004988b78eb6eab36 64bf84dd5e03670fdb24c0f5d3c2c365736f51db6c92d95010716ad2d36134c8 valid_x(x3);valid_x(x2);valid_x(x1);u>=p
77 fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefbb982fffffffffffffffffffffffffffffffffffffffffffffffffffffffff6d6db1f 1c92ccdfcf4ac550c28db57cff0c8515cb26936c786584a70114008d6c33a34b valid_x(x1);u>=p;t>=p

View File

@ -0,0 +1,418 @@
"""Generate the BIP-0324 test vectors."""
import csv
import hashlib
import os
import sys
from reference import (
FE,
GE,
MINUS_3_SQRT,
hkdf_sha256,
SECP256K1_G,
ellswift_decode,
ellswift_ecdh_xonly,
xswiftec_inv,
xswiftec,
v2_ecdh,
initialize_v2_transport,
v2_enc_packet
)
FILENAME_PACKET_TEST = os.path.join(sys.path[0], 'packet_encoding_test_vectors.csv')
FILENAME_XSWIFTEC_INV_TEST = os.path.join(sys.path[0], 'xswiftec_inv_test_vectors.csv')
FILENAME_ELLSWIFT_DECODE_TEST = os.path.join(sys.path[0], 'ellswift_decode_test_vectors.csv')
def xswiftec_flagged(u, t, simplified=False):
"""A variant of xswiftec which also returns 'flags', describing conditions encountered."""
flags = []
if u == 0:
flags.append("u%p=0")
u = FE(1)
if t == 0:
flags.append("t%p=0")
t = FE(1)
if u**3 + t**2 + 7 == 0:
flags.append("(u'^3+t'^2+7)%p=0")
t = 2 * t
X = (u**3 + 7 - t**2) / (2 * t)
Y = (X + t) / (MINUS_3_SQRT * u)
if X == 0:
if not simplified:
flags.append("(u'^3-t'^2+7)%p=0")
x3 = u + 4 * Y**2
if GE.is_valid_x(x3):
flags.append("valid_x(x3)")
x2 = (-X / Y - u) / 2
if GE.is_valid_x(x2):
flags.append("valid_x(x2)")
x1 = (X / Y - u) / 2
if GE.is_valid_x(x1):
flags.append("valid_x(x1)")
for x in (x3, x2, x1):
if GE.is_valid_x(x):
break
return x, flags
def ellswift_create_deterministic(seed, features):
"""This is a variant of ellswift_create which doesn't use randomness.
features is an integer selecting some properties of the result:
- (f & 3) == 0: only x1 is valid on decoding (see xswiftec{_flagged})
- (f & 3) == 1: only x2 is valid on decoding
- (f & 3) == 2: only x3 is valid on decoding
- (f & 3) == 3: x1,x2,x3 are all valid on decoding
- (f & 4) == 4: u >= p
- (f & 8) == 8: u mod n == 0
Returns privkey, ellswift
"""
cnt = 0
while True:
sec = hkdf_sha256(32, seed, (cnt).to_bytes(4, 'little'), b"sec")
xval = (int.from_bytes(sec, 'big') * SECP256K1_G).x
cnt += 1
if features & 8:
u = 0
if features & 4:
u += FE.SIZE
else:
udat = hkdf_sha256(64, seed, (cnt).to_bytes(4, 'little'), b"u")
if features & 4:
u = FE.SIZE + 1 + int.from_bytes(udat, 'big') % (2**256 - FE.SIZE - 1)
else:
u = 1 + int.from_bytes(udat, 'big') % (FE.SIZE - 1)
case = hkdf_sha256(1, seed, (cnt).to_bytes(4, 'little'), b"case")[0] & 7
coru = FE(u) + ((features & 8) == 8)
t = xswiftec_inv(xval, coru, case)
if t is None:
continue
assert xswiftec(FE(u), t) == xval
x2, flags = xswiftec_flagged(FE(u), t)
assert x2 == xval
have_x1 = "valid_x(x1)" in flags
have_x2 = "valid_x(x2)" in flags
have_x3 = "valid_x(x3)" in flags
if (features & 4) == 0 and not (have_x1 and not have_x2 and not have_x3):
continue
if (features & 4) == 1 and not (not have_x1 and have_x2 and not have_x3):
continue
if (features & 4) == 2 and not (not have_x1 and not have_x2 and have_x3):
continue
if (features & 4) == 3 and not (have_x1 and have_x2 and have_x3):
continue
return sec, u.to_bytes(32, 'big') + t.to_bytes()
def ellswift_decode_flagged(ellswift, simplified=False):
"""Decode a 64-byte ElligatorSwift encoded coordinate, returning byte array + flag string."""
uv = int.from_bytes(ellswift[:32], 'big')
tv = int.from_bytes(ellswift[32:], 'big')
x, flags = xswiftec_flagged(FE(uv), FE(tv))
if not simplified:
if uv >= FE.SIZE:
flags.append("u>=p")
if tv >= FE.SIZE:
flags.append("t>=p")
return int(x).to_bytes(32, 'big'), ";".join(flags)
def random_fe_int(_, seed, i, p):
"""Function to use in tuple_expand, generating a random integer in 0..p-1."""
rng_out = hkdf_sha256(64, seed, i.to_bytes(4, 'little'), b"v%i_fe" % p)
return int.from_bytes(rng_out, 'big') % FE.SIZE
def random_fe_int_high(_, seed, i, p):
"""Function to use in tuple_expand, generating a random integer in p..2^256-1."""
rng_out = hkdf_sha256(64, seed, i.to_bytes(4, 'little'), b"v%i_fe_high" % p)
return FE.SIZE + int.from_bytes(rng_out, 'big') % (2**256 - FE.SIZE)
def fn_of(p_in, fn):
"""Function to use in tuple_expand, to pick one variable in function of another."""
def inner(vs, _seed, _i, p):
assert p != p_in
if isinstance(vs[p_in], int):
return fn(vs[p_in])
return None
return inner
def tuple_expand(out, tuplespec, prio, seed=None, cnt=1):
"""Given a tuple specification, expand it cnt times, and add results to out.
Expansion is defined recursively:
- If any of the spec elements is a list, each element of the list results
in an expansion (by replacing the list with its element).
- If any of the spec elements is a function, that function is invoked with
(spec, seed, expansion count, index in spec) as arguments. If the function
needs to wait for other indices to be expanded, it can return None.
The output consists of (prio, expansion count, SHA256(result), result, seed)
tuples."""
def recurse(vs, seed, i, change_pos=None, change=None):
if change_pos is not None:
vs = list(vs)
vs[change_pos] = change
for p, v in enumerate(vs):
if v is None:
return
if isinstance(v, list):
for ve in v:
recurse(vs, seed, i, p, ve)
return
if callable(v):
res = v(vs, seed, i, p)
if res is not None:
recurse(vs, seed, i, p, res)
return
h = hashlib.sha256()
for v in vs:
h.update(int(v).to_bytes(32, 'big'))
out.append((prio, i, h.digest(), vs, seed))
for i in range(cnt):
recurse(tuplespec, seed, i)
def gen_ellswift_decode_cases(seed, simplified=False):
"""Generate a set of interesting (ellswift, x, flags) ellswift decoding cases."""
inputs = []
# Aggregate for use in tuple_expand, expanding to int in 0..p-1, and one in p..2^256-1.
RANDOM_VAL = [random_fe_int, random_fe_int_high]
# Aggregate for use in tuple_expand, expanding to integers which %p equal 0.
ZERO_VAL = [0, FE.SIZE]
# Helpers for constructing u and t values such that u^3+t^2+7=0 or u^3-t^2+7=0.
T_FOR_SUM_ZERO = fn_of(0, lambda u: (-FE(u)**3 - 7).sqrts())
T_FOR_DIFF_ZERO = fn_of(0, lambda u: (FE(u)**3 + 7).sqrts())
U_FOR_SUM_ZERO = fn_of(1, lambda t: (-FE(t)**2 - 7).cbrts())
U_FOR_DIFF_ZERO = fn_of(1, lambda t: (FE(t)**2 - 7).cbrts())
tuple_expand(inputs, [RANDOM_VAL, RANDOM_VAL], 0, seed + b"random", 64)
tuple_expand(inputs, [RANDOM_VAL, T_FOR_SUM_ZERO], 1, seed + b"t=sqrt(-u^3-7)", 64)
tuple_expand(inputs, [U_FOR_SUM_ZERO, RANDOM_VAL], 1, seed + b"u=cbrt(-t^2-7)", 64)
tuple_expand(inputs, [RANDOM_VAL, T_FOR_DIFF_ZERO], 1, seed + b"t=sqrt(u^3+7)", 64)
tuple_expand(inputs, [U_FOR_DIFF_ZERO, RANDOM_VAL], 1, seed + b"u=cbrt(t^2-7)", 64)
tuple_expand(inputs, [ZERO_VAL, RANDOM_VAL], 2, seed + b"u=0", 64)
tuple_expand(inputs, [RANDOM_VAL, ZERO_VAL], 2, seed + b"t=0", 64)
tuple_expand(inputs, [ZERO_VAL, FE(8).sqrts()], 3, seed + b"u=0;t=sqrt(8)")
tuple_expand(inputs, [FE(-8).cbrts(), ZERO_VAL], 3, seed + b"t=0;u=cbrt(-8)")
tuple_expand(inputs, [FE(-6).cbrts(), ZERO_VAL], 3, seed + b"t=0;u=cbrt(-6)")
tuple_expand(inputs, [ZERO_VAL, ZERO_VAL], 3, seed + b"u=0;t=0")
# Unused.
tuple_expand(inputs, [ZERO_VAL, FE(-8).sqrts()], 4, seed + b"u=0;t=sqrt(-8)")
seen = set()
cases = []
for _prio, _cnt, _hash, vs, _seed in sorted(inputs):
inp = int(vs[0]).to_bytes(32, 'big') + int(vs[1]).to_bytes(32, 'big')
outp, flags = ellswift_decode_flagged(inp, simplified)
if flags not in seen:
cases.append((inp, outp, flags))
seen.add(flags)
return cases
def gen_all_ellswift_decode_vectors(fil):
"""Generate all xelligatorswift decoding test vectors."""
cases = gen_ellswift_decode_cases(b"")
writer = csv.DictWriter(fil, ["ellswift", "x", "comment"])
writer.writeheader()
for val, x, flags in sorted(cases):
writer.writerow({"ellswift": val.hex(), "x": x.hex(), "comment": flags})
def xswiftec_inv_flagged(x, u, case):
"""A variant of xswiftec_inv which also returns flags, describing conditions encountered."""
flags = []
if case & 2 == 0:
if GE.is_valid_x(-x - u):
flags.append("bad[valid_x(-x-u)]")
return None, flags
v = x if case & 1 == 0 else -x - u
if v == 0:
flags.append("info[v=0]")
s = -(u**3 + 7) / (u**2 + u*v + v**2)
assert s != 0 # would imply X=0 on curve
else:
s = x - u
if s == 0:
flags.append("bad[s=0]")
return None, flags
q = (-s * (4 * (u**3 + 7) + 3 * s * u**2))
if q == 0:
flags.append("info[q=0]")
r = q.sqrt()
if r is None:
flags.append("bad[non_square(q)]")
return None, flags
if case & 1:
if r == 0:
flags.append("bad[r=0]")
return None, flags
r = -r
v = (-u + r / s) / 2
if v == 0:
flags.append("info[v=0]")
w = s.sqrt()
assert w != 0
if w is None:
flags.append("bad[non_square(s)]")
return None, flags
if case & 4:
w = -w
Y = w / 2
assert Y != 0
X = 2 * Y * (v + u / 2)
if X == 0:
flags.append("info[X=0]")
flags.append("ok")
return w * (u * (MINUS_3_SQRT - 1) / 2 - v), flags
def xswiftec_inv_combo_flagged(x, u):
"""Compute the aggregate results and flags from xswiftec_inv_flagged for case=0..7."""
ts = []
allflags = []
for case in range(8):
t, flags = xswiftec_inv_flagged(x, u, case)
if t is not None:
assert x == xswiftec(u, t)
ts.append(t)
allflags.append(f"case{case}:{'&'.join(flags)}")
return ts, ";".join(allflags)
def gen_all_xswiftec_inv_vectors(fil):
"""Generate all xswiftec_inv test vectors."""
# Two constants used below. Compute them only once.
C1 = (FE(MINUS_3_SQRT) - 1) / 2
C2 = (-FE(MINUS_3_SQRT) - 1) / 2
# Helper functions that pick x and u with special properties.
TRIGGER_Q_ZERO = fn_of(1, lambda u: (FE(u)**3 + 28) / (FE(-3) * FE(u)**2))
TRIGGER_DIVZERO_A = fn_of(1, lambda u: FE(u) * C1)
TRIGGER_DIVZERO_B = fn_of(1, lambda u: FE(u) * C2)
TRIGGER_V_ZERO = fn_of(1, lambda u: FE(-7) / FE(u)**2)
TRIGGER_X_ZERO = fn_of(0, lambda x: FE(-2) * FE(x))
inputs = []
tuple_expand(inputs, [random_fe_int, random_fe_int], 0, b"uniform", 256)
tuple_expand(inputs, [TRIGGER_Q_ZERO, random_fe_int], 1, b"x=-(u^3+28)/(3*u^2)", 64)
tuple_expand(inputs, [TRIGGER_V_ZERO, random_fe_int], 1, b"x=-7/u^2", 512)
tuple_expand(inputs, [random_fe_int, fn_of(0, lambda x: x)], 2, b"u=x", 64)
tuple_expand(inputs, [random_fe_int, fn_of(0, lambda x: -FE(x))], 2, b"u=-x", 64)
# Unused.
tuple_expand(inputs, [TRIGGER_DIVZERO_A, random_fe_int], 3, b"x=u*(sqrt(-3)-1)/2", 64)
tuple_expand(inputs, [TRIGGER_DIVZERO_B, random_fe_int], 3, b"x=u*(-sqrt(-3)-1)/2", 64)
tuple_expand(inputs, [random_fe_int, TRIGGER_X_ZERO], 3, b"u=-2x", 64)
seen = set()
cases = []
for _prio, _cnt, _hash, vs, _seed in sorted(inputs):
x, u = FE(vs[0]), FE(vs[1])
if u == 0:
continue
if not GE.is_valid_x(x):
continue
ts, flags = xswiftec_inv_combo_flagged(x, u)
if flags not in seen:
cases.append((int(u), int(x), ts, flags))
seen.add(flags)
writer = csv.DictWriter(fil, ["u", "x"] + [f"case{c}_t" for c in range(8)] + ["comment"])
writer.writeheader()
for u, x, ts, flags in sorted(cases):
row = {"u": FE(u), "x": FE(x), "comment": flags}
for c in range(8):
if ts[c] is not None:
row[f"case{c}_t"] = FE(ts[c])
writer.writerow(row)
def gen_packet_encoding_vector(case):
"""Given a dict case with specs, construct a packet_encoding test vector as a CSV line."""
ikm = str(case).encode('utf-8')
in_initiating = case["init"]
in_ignore = int(case["ignore"])
in_priv_ours, in_ellswift_ours = ellswift_create_deterministic(ikm, case["features"])
mid_x_ours = (int.from_bytes(in_priv_ours, 'big') * SECP256K1_G).x.to_bytes()
assert mid_x_ours == ellswift_decode(in_ellswift_ours)
in_ellswift_theirs = case["theirs"]
in_contents = hkdf_sha256(case["contentlen"], ikm, b"contents", b"")
contents = in_contents * case["multiply"]
in_aad = hkdf_sha256(case["aadlen"], ikm, b"aad", b"")
mid_shared_secret = v2_ecdh(in_priv_ours, in_ellswift_theirs, in_ellswift_ours, in_initiating)
peer = initialize_v2_transport(mid_shared_secret, in_initiating)
for _ in range(case["idx"]):
v2_enc_packet(peer, b"")
ciphertext = v2_enc_packet(peer, contents, in_aad, case["ignore"])
long_msg = len(ciphertext) > 128
return {
"in_idx": case['idx'],
"in_priv_ours": in_priv_ours.hex(),
"in_ellswift_ours": in_ellswift_ours.hex(),
"in_ellswift_theirs": in_ellswift_theirs.hex(),
"in_initiating": int(in_initiating),
"in_contents": in_contents.hex(),
"in_multiply": case['multiply'],
"in_aad": in_aad.hex(),
"in_ignore": in_ignore,
"mid_x_ours": mid_x_ours.hex(),
"mid_x_theirs": ellswift_decode(in_ellswift_theirs).hex(),
"mid_x_shared": ellswift_ecdh_xonly(in_ellswift_theirs, in_priv_ours).hex(),
"mid_shared_secret": mid_shared_secret.hex(),
"mid_initiator_l": peer['initiator_L'].hex(),
"mid_initiator_p": peer['initiator_P'].hex(),
"mid_responder_l": peer['responder_L'].hex(),
"mid_responder_p": peer['responder_P'].hex(),
"mid_send_garbage_terminator": peer["send_garbage_terminator"].hex(),
"mid_recv_garbage_terminator": peer["recv_garbage_terminator"].hex(),
"out_session_id": peer["session_id"].hex(),
"out_ciphertext": "" if long_msg else ciphertext.hex(),
"out_ciphertext_endswith": ciphertext[-128:].hex() if long_msg else ""
}
def gen_all_packet_encoding_vectors(fil):
"""Return a list of CSV lines, one for each packet encoding vector."""
ellswift = gen_ellswift_decode_cases(b"simplified_", simplified=True)
ellswift.sort(key=lambda x: hashlib.sha256(b"simplified:" + x[0]).digest())
fields = [
"in_idx", "in_priv_ours", "in_ellswift_ours", "in_ellswift_theirs", "in_initiating",
"in_contents", "in_multiply", "in_aad", "in_ignore", "mid_x_ours", "mid_x_theirs",
"mid_x_shared", "mid_shared_secret", "mid_initiator_l", "mid_initiator_p",
"mid_responder_l", "mid_responder_p", "mid_send_garbage_terminator",
"mid_recv_garbage_terminator", "out_session_id", "out_ciphertext", "out_ciphertext_endswith"
]
writer = csv.DictWriter(fil, fields)
writer.writeheader()
for case in [
{"init": True, "contentlen": 1, "multiply": 1, "aadlen": 0, "ignore": False, "idx": 1,
"theirs": ellswift[0][0], "features": 0},
{"init": False, "contentlen": 17, "multiply": 1, "aadlen": 0, "ignore": False, "idx": 999,
"theirs": ellswift[1][0], "features": 1},
{"init": True, "contentlen": 63, "multiply": 1, "aadlen": 4095, "ignore": False, "idx": 0,
"theirs": ellswift[2][0], "features": 2},
{"init": False, "contentlen": 128, "multiply": 1, "aadlen": 0, "ignore": True, "idx": 223,
"theirs": ellswift[3][0], "features": 3},
{"init": True, "contentlen": 193, "multiply": 1, "aadlen": 0, "ignore": False, "idx": 448,
"theirs": ellswift[4][0], "features": 4},
{"init": False, "contentlen": 41, "multiply": 97561, "aadlen": 0, "ignore": False,
"idx": 673, "theirs": ellswift[5][0], "features": 5},
{"init": True, "contentlen": 241, "multiply": 69615, "aadlen": 0, "ignore": True,
"idx": 1024, "theirs": ellswift[6][0], "features": 6},
]:
writer.writerow(gen_packet_encoding_vector(case))
if __name__ == "__main__":
print(f"Generating {FILENAME_PACKET_TEST}...")
with open(FILENAME_PACKET_TEST, "w", encoding="utf-8") as fil_packet:
gen_all_packet_encoding_vectors(fil_packet)
print(f"Generating {FILENAME_XSWIFTEC_INV_TEST}...")
with open(FILENAME_XSWIFTEC_INV_TEST, "w", encoding="utf-8") as fil_xswiftec_inv:
gen_all_xswiftec_inv_vectors(fil_xswiftec_inv)
print(f"Generating {FILENAME_ELLSWIFT_DECODE_TEST}...")
with open(FILENAME_ELLSWIFT_DECODE_TEST, "w", encoding="utf-8") as fil_ellswift_decode:
gen_all_ellswift_decode_vectors(fil_ellswift_decode)

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,5 @@
"""Reference implementation for the cryptographic aspects of BIP-324"""
import sys
import random
import hashlib
@ -70,7 +72,7 @@ class FE:
self.den = (a.den * b.num) % FE.SIZE
else:
self.num = (a * b.den) % FE.SIZE
self.den = a.num
self.den = b.num
else:
b = b % FE.SIZE
assert b != 0
@ -85,8 +87,7 @@ class FE:
"""Compute the sum of two field elements (second may be int)."""
if isinstance(a, FE):
return FE(self.num * a.den + self.den * a.num, self.den * a.den)
else:
return FE(self.num + self.den * a, self.den)
return FE(self.num + self.den * a, self.den)
def __radd__(self, a):
"""Compute the sum of an integer and a field element."""
@ -96,8 +97,7 @@ class FE:
"""Compute the difference of two field elements (second may be int)."""
if isinstance(a, FE):
return FE(self.num * a.den - self.den * a.num, self.den * a.den)
else:
return FE(self.num - self.den * a, self.den)
return FE(self.num - self.den * a, self.den)
def __rsub__(self, a):
"""Compute the difference between an integer and a field element."""
@ -107,8 +107,7 @@ class FE:
"""Compute the product of two field elements (second may be int)."""
if isinstance(a, FE):
return FE(self.num * a.num, self.den * a.den)
else:
return FE(self.num * a, self.den)
return FE(self.num * a, self.den)
def __rmul__(self, a):
"""Compute the product of an integer with a field element."""
@ -140,15 +139,57 @@ class FE:
def sqrt(self):
"""Compute the square root of a field element.
Due to the fact that our modulus is of the form (p % 4) == 3, the Tonelli-Shanks
algorithm (https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm) is simply
raising the argument to the power (p + 3) / 4."""
Due to the fact that our modulus p is of the form p = 3 (mod 4), the
Tonelli-Shanks algorithm (https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm)
is simply raising the argument to the power (p + 1) / 4.
To see why: p-1 = 0 (mod 2), so 2 divides the order of the multiplicative group,
and thus only half of the non-zero field elements are squares. An element a is
a (nonzero) square when Euler's criterion, a^((p-1)/2) = 1 (mod p), holds. We're
looking for x such that x^2 = a (mod p). Given a^((p-1)/2) = 1 (mod p), that is
equivalent to x^2 = a^(1 + (p-1)/2) (mod p). As (1 + (p-1)/2) is even, this is
equivalent to x = a^((1 + (p-1)/2)/2) (mod p), or x = a^((p+1)/4) (mod p)."""
v = int(self)
s = pow(v, (FE.SIZE + 1) // 4, FE.SIZE)
if s**2 % FE.SIZE == v:
return FE(s)
return None
def sqrts(self):
"""Compute all square roots of a field element, if any."""
s = self.sqrt()
if s is None:
return []
return [FE(s), -FE(s)]
# The cube roots of 1 (mod p).
CBRT1 = [
1,
0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40,
0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee
]
def cbrts(self):
"""Compute all cube roots of a field element, if any.
Due to the fact that our modulus p is of the form p = 7 (mod 9), one cube root
can always be computed by raising to the power (p + 2) / 9. The other roots
(if any) can be found by multiplying with the two non-trivial cube roots of 1.
To see why: p-1 = 0 (mod 3), so 3 divides the order of the multiplicative group,
and thus only 1/3 of the non-zero field elements are cubes. An element a is a
(nonzero) cube when a^((p-1)/3) = 1 (mod p). We're looking for x such that
x^3 = a (mod p). Given a^((p-1)/3) = 1 (mod p), that is equivalent to
x^3 = a^(1 + (p-1)/3) (mod p). As (1 + (p-1)/3) is a multiple of 3, this is
equivalent to x = a^((1 + (p-1)/3)/3) (mod p), or x = a^((p+2)/9) (mod p)."""
v = int(self)
c = pow(v, (FE.SIZE + 2) // 9, FE.SIZE)
if pow(c, 3, FE.SIZE) == v:
return [FE(c * f) for f in FE.CBRT1]
return []
def is_square(self):
"""Determine if this field element has a square root."""
# Compute the Jacobi symbol of (self / p). Since our modulus is prime, this
@ -161,7 +202,7 @@ class FE:
while n & 1 == 0:
n >>= 1
r = k & 7
t ^= (r == 3 or r == 5)
t ^= (r in (3, 5))
n, k = k, n
t ^= (n & k & 3 == 3)
n = n % k
@ -172,8 +213,7 @@ class FE:
"""Check whether two field elements are equal (second may be an int)."""
if isinstance(a, FE):
return (self.num * a.den - self.den * a.num) % FE.SIZE == 0
else:
return (self.num - self.den * a) % FE.SIZE == 0
return (self.num - self.den * a) % FE.SIZE == 0
def to_bytes(self):
"""Convert a field element to 32-byte big endian encoding."""
@ -187,6 +227,16 @@ class FE:
return None
return FE(v)
def __str__(self):
"""Convert this field element to a string."""
return f"{int(self):064x}"
def __repr__(self):
"""Get a string representation of this field element."""
return f"FE(0x{int(self):x})"
assert all(pow(c, 3, FE.SIZE) == 1 for c in FE.CBRT1)
class GE:
"""Objects of this class represent points (group elements) on the secp256k1 curve.
@ -221,12 +271,11 @@ class GE:
x3 = l**2 - self.x - a.x
y3 = l * (self.x - x3) - self.y
return GE(x3, y3)
elif self.y == a.y:
if self.y == a.y:
# Adding point to itself
return self.double()
else:
# Adding point to its negation
return None
# Adding point to its negation
return None
def __radd__(self, a):
"""Add infinity to a point."""
@ -260,13 +309,21 @@ class GE:
"""Determine whether the provided field element is a valid X coordinate."""
return (FE(x)**3 + 7).is_square()
def __str__(self):
"""Convert this group element to a string."""
return f"({self.x},{self.y})"
def __repr__(self):
"""Get a string representation for this group element."""
return f"GE(0x{int(self.x)},0x{int(self.y)})"
SECP256K1_G = GE(
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
### ElligatorSwift
# Precomputed constant square root of -3 modulo p.
# Precomputed constant square root of -3 (mod p).
MINUS_3_SQRT = FE(-3).sqrt()
def xswiftec(u, t):
@ -292,7 +349,7 @@ def xswiftec_inv(x, u, case):
if case & 2 == 0:
if GE.is_valid_x(-x - u):
return None
v = x if case & 1 == 0 else -x - u
v = x
s = -(u**3 + 7) / (u**2 + u*v + v**2)
else:
s = x - u
@ -301,17 +358,16 @@ def xswiftec_inv(x, u, case):
r = (-s * (4 * (u**3 + 7) + 3 * s * u**2)).sqrt()
if r is None:
return None
if case & 1:
if r == 0:
return None
r = -r
if case & 1 and r == 0:
return None
v = (-u + r / s) / 2
w = s.sqrt()
if w is None:
return None
if case & 4:
w = -w
return w * (u * (MINUS_3_SQRT - 1) / 2 - v)
if case & 5 == 0: return -w * (u * (1 - MINUS_3_SQRT) / 2 + v)
if case & 5 == 1: return w * (u * (1 + MINUS_3_SQRT) / 2 + v)
if case & 5 == 4: return w * (u * (1 - MINUS_3_SQRT) / 2 + v)
if case & 5 == 5: return -w * (u * (1 + MINUS_3_SQRT) / 2 + v)
def xelligatorswift(x):
"""Given a field element X on the curve, find (u, t) that encode them."""
@ -328,12 +384,17 @@ def ellswift_create():
u, t = xelligatorswift((priv * SECP256K1_G).x)
return priv.to_bytes(32, 'big'), u.to_bytes() + t.to_bytes()
def ellswift_decode(ellswift):
"""Convert ellswift encoded X coordinate to 32-byte xonly format."""
u = FE(int.from_bytes(ellswift[:32], 'big'))
t = FE(int.from_bytes(ellswift[32:], 'big'))
return xswiftec(u, t).to_bytes()
def ellswift_ecdh_xonly(pubkey_theirs, privkey):
"""Compute X coordinate of shared ECDH point between elswift pubkey and privkey."""
u = FE(int.from_bytes(pubkey_theirs[:32], 'big'))
t = FE(int.from_bytes(pubkey_theirs[32:], 'big'))
d = int.from_bytes(privkey, 'big')
return (d * GE.lift_x(xswiftec(u, t))).x.to_bytes()
pub = ellswift_decode(pubkey_theirs)
return (d * GE.lift_x(FE.from_bytes(pub))).x.to_bytes()
### Poly1305
@ -402,7 +463,7 @@ def chacha20_block(key, nonce, cnt):
for i in range(3):
init[13 + i] = int.from_bytes(nonce[4 * i:4 * (i+1)], 'little')
# Perform 20 rounds.
state = [v for v in init]
state = list(init)
for _ in range(10):
chacha20_doubleround(state)
# Add initial values back into state.
@ -459,6 +520,7 @@ class FSChaCha20Poly1305:
self.packet_counter = 0
def crypt(self, aad, text, is_decrypt):
"""Encrypt or decrypt the specified (plain/cipher)text."""
nonce = ((self.packet_counter % REKEY_INTERVAL).to_bytes(4, 'little') +
(self.packet_counter // REKEY_INTERVAL).to_bytes(8, 'little'))
if is_decrypt:
@ -474,12 +536,14 @@ class FSChaCha20Poly1305:
self.packet_counter += 1
return ret
def decrypt(self, aad, ciphertext):
return self.crypt(aad, ciphertext, True)
def encrypt(self, aad, plaintext):
"""Encrypt the specified plaintext with provided AAD."""
return self.crypt(aad, plaintext, False)
def decrypt(self, aad, ciphertext):
"""Decrypt the specified ciphertext with provided AAD."""
return self.crypt(aad, ciphertext, True)
class FSChaCha20:
"""Rekeying wrapper stream cipher around ChaCha20."""
@ -491,6 +555,7 @@ class FSChaCha20:
self.keystream = b''
def get_keystream_bytes(self, nbytes):
"""Generate nbytes keystream bytes."""
while len(self.keystream) < nbytes:
nonce = ((0).to_bytes(4, 'little') +
(self.chunk_counter // REKEY_INTERVAL).to_bytes(8, 'little'))
@ -501,6 +566,7 @@ class FSChaCha20:
return ret
def crypt(self, chunk):
"""Encrypt or decypt chunk."""
ks = self.get_keystream_bytes(len(chunk))
ret = bytes([ks[i] ^ chunk[i] for i in range(len(chunk))])
if ((self.chunk_counter + 1) % REKEY_INTERVAL) == 0:
@ -509,6 +575,15 @@ class FSChaCha20:
self.chunk_counter += 1
return ret
def encrypt(self, chunk):
"""Encrypt chunk."""
return self.crypt(chunk)
def decrypt(self, chunk):
"""Decrypt chunk."""
return self.crypt(chunk)
### Shared secret computation
def v2_ecdh(priv, ellswift_theirs, ellswift_ours, initiating):
@ -519,10 +594,9 @@ def v2_ecdh(priv, ellswift_theirs, ellswift_ours, initiating):
# Initiating, place our public key encoding first.
return TaggedHash("bip324_ellswift_xonly_ecdh",
ellswift_ours + ellswift_theirs + ecdh_point_x32)
else:
# Responding, place their public key encoding first.
return TaggedHash("bip324_ellswift_xonly_ecdh",
ellswift_theirs + ellswift_ours + ecdh_point_x32)
# Responding, place their public key encoding first.
return TaggedHash("bip324_ellswift_xonly_ecdh",
ellswift_theirs + ellswift_ours + ecdh_point_x32)
### Key derivation
@ -571,5 +645,5 @@ def v2_enc_packet(peer, contents, aad=b'', ignore=False):
header = (ignore << IGNORE_BIT_POS).to_bytes(HEADER_LEN, 'little')
plaintext = header + contents
aead_ciphertext = peer['send_P'].encrypt(aad, plaintext)
enc_plaintext_len = peer['send_L'].crypt(len(contents).to_bytes(LENGTH_FIELD_LEN, 'little'))
enc_plaintext_len = peer['send_L'].encrypt(len(contents).to_bytes(LENGTH_FIELD_LEN, 'little'))
return enc_plaintext_len + aead_ciphertext

View File

@ -1,53 +1,69 @@
"""Run the BIP-324 test vectors."""
import csv
import os
import sys
import reference
with open(os.path.join(sys.path[0], 'packet_encoding_test_vectors.csv'), newline='') as csvfile:
reader = csv.reader(csvfile)
reader.__next__()
FILENAME_PACKET_TEST = os.path.join(sys.path[0], 'packet_encoding_test_vectors.csv')
FILENAME_XSWIFTEC_INV_TEST = os.path.join(sys.path[0], 'xswiftec_inv_test_vectors.csv')
FILENAME_ELLSWIFT_DECODE_TEST = os.path.join(sys.path[0], 'ellswift_decode_test_vectors.csv')
with open(FILENAME_PACKET_TEST, newline='', encoding='utf-8') as csvfile:
print(f"Running {FILENAME_PACKET_TEST} tests...")
reader = csv.DictReader(csvfile)
for row in reader:
in_idx, in_priv_ours, in_ellswift_ours, in_ellswift_theirs, in_initiating, in_content, in_multiply, in_aad, in_ignore, mid_x_ours, mid_x_shared, mid_shared_secret, mid_initiator_l, mid_initiator_p, mid_responder_l, mid_responder_p, mid_send_garbage_terminator, mid_recv_garbage_terminator, mid_session_id, out_ciphertext, out_ciphertext_endswith = row
in_initiating = int(row['in_initiating'])
bytes_priv_ours = bytes.fromhex(row['in_priv_ours'])
int_priv_ours = int.from_bytes(bytes_priv_ours, 'big')
assert row['mid_x_ours'] == (int_priv_ours * reference.SECP256K1_G).x.to_bytes().hex()
bytes_ellswift_ours = bytes.fromhex(row['in_ellswift_ours'])
assert row['mid_x_ours'] == reference.ellswift_decode(bytes_ellswift_ours).hex()
bytes_ellswift_theirs = bytes.fromhex(row['in_ellswift_theirs'])
assert row['mid_x_theirs'] == reference.ellswift_decode(bytes_ellswift_theirs).hex()
x_shared = reference.ellswift_ecdh_xonly(bytes_ellswift_theirs, bytes_priv_ours)
assert row['mid_x_shared'] == x_shared.hex()
shared_secret = reference.v2_ecdh(bytes_priv_ours, bytes_ellswift_theirs,
bytes_ellswift_ours, in_initiating)
assert row['mid_shared_secret'] == shared_secret.hex()
assert mid_x_ours == (int.from_bytes(bytes.fromhex(in_priv_ours), 'big') * reference.SECP256K1_G).x.to_bytes().hex()
assert mid_x_shared == reference.ellswift_ecdh_xonly(bytes.fromhex(in_ellswift_theirs), bytes.fromhex(in_priv_ours)).hex()
assert mid_shared_secret == reference.v2_ecdh(bytes.fromhex(in_priv_ours), bytes.fromhex(in_ellswift_theirs), bytes.fromhex(in_ellswift_ours), int(in_initiating)).hex()
peer = reference.initialize_v2_transport(bytes.fromhex(mid_shared_secret), int(in_initiating))
assert mid_initiator_l == peer['initiator_L'].hex()
assert mid_initiator_p == peer['initiator_P'].hex()
assert mid_responder_l == peer['responder_L'].hex()
assert mid_responder_p == peer['responder_P'].hex()
assert mid_send_garbage_terminator == peer['send_garbage_terminator'].hex()
assert mid_recv_garbage_terminator == peer['recv_garbage_terminator'].hex()
assert mid_session_id == peer['session_id'].hex()
for _ in range(int(in_idx)):
peer = reference.initialize_v2_transport(shared_secret, in_initiating)
assert row['mid_initiator_l'] == peer['initiator_L'].hex()
assert row['mid_initiator_p'] == peer['initiator_P'].hex()
assert row['mid_responder_l'] == peer['responder_L'].hex()
assert row['mid_responder_p'] == peer['responder_P'].hex()
assert row['mid_send_garbage_terminator'] == peer['send_garbage_terminator'].hex()
assert row['mid_recv_garbage_terminator'] == peer['recv_garbage_terminator'].hex()
assert row['out_session_id'] == peer['session_id'].hex()
for _ in range(int(row['in_idx'])):
reference.v2_enc_packet(peer, b"")
ciphertext = reference.v2_enc_packet(peer, bytes.fromhex(in_content) * int(in_multiply), bytes.fromhex(in_aad), int(in_ignore))
if len(out_ciphertext):
assert out_ciphertext == ciphertext.hex()
if len(out_ciphertext_endswith):
assert ciphertext.hex().endswith(out_ciphertext_endswith)
ciphertext = reference.v2_enc_packet(
peer,
bytes.fromhex(row['in_contents']) * int(row['in_multiply']),
bytes.fromhex(row['in_aad']), int(row['in_ignore']))
if len(row['out_ciphertext']):
assert row['out_ciphertext'] == ciphertext.hex()
if len(row['out_ciphertext_endswith']):
assert ciphertext.hex().endswith(row['out_ciphertext_endswith'])
with open(os.path.join(sys.path[0], 'xswiftec_test_vectors.csv'), newline='') as csvfile:
reader = csv.reader(csvfile)
reader.__next__()
with open(FILENAME_XSWIFTEC_INV_TEST, newline='', encoding='utf-8') as csvfile:
print(f"Running {FILENAME_XSWIFTEC_INV_TEST} tests...")
reader = csv.DictReader(csvfile)
for row in reader:
u = reference.FE.from_bytes(bytes.fromhex(row[0]))
x = reference.FE.from_bytes(bytes.fromhex(row[1]))
u = reference.FE.from_bytes(bytes.fromhex(row['u']))
x = reference.FE.from_bytes(bytes.fromhex(row['x']))
for case in range(8):
ret = reference.xswiftec_inv(x, u, case)
if ret is None:
assert row[2 + case] == ""
assert row[f"case{case}_t"] == ""
else:
assert row[2 + case] == ret.to_bytes().hex()
assert row[f"case{case}_t"] == ret.to_bytes().hex()
assert reference.xswiftec(u, ret) == x
with open(os.path.join(sys.path[0], 'xelligatorswift_test_vectors.csv'), newline='') as csvfile:
reader = csv.reader(csvfile)
reader.__next__()
with open(FILENAME_ELLSWIFT_DECODE_TEST, newline='', encoding='utf-8') as csvfile:
print(f"Running {FILENAME_ELLSWIFT_DECODE_TEST} tests...")
reader = csv.DictReader(csvfile)
for row in reader:
ellswift = bytes.fromhex(row[0])
x = bytes.fromhex(row[1])
assert reference.ellswift_ecdh_xonly(ellswift, (1).to_bytes(32, 'big')) == x
ellswift = bytes.fromhex(row['ellswift'])
assert reference.ellswift_decode(ellswift).hex() == row['x']

View File

@ -0,0 +1,52 @@
"""Convert the BIP-324 test vectors to secp256k1 code."""
import csv
import reference
import os
import sys
FILENAME_XSWIFTEC_INV_TEST = os.path.join(sys.path[0], 'xswiftec_inv_test_vectors.csv')
FILENAME_ELLSWIFT_DECODE_TEST = os.path.join(sys.path[0], 'ellswift_decode_test_vectors.csv')
def format_int(v):
"""Format 0 as "0", but other integers as 0x%08x."""
if v == 0:
return "0"
return f"0x{v:08x}"
def format_fe(fe):
"""Format a field element constant as SECP256K1_FE_CONST code."""
vals = [(int(fe) >> (32 * (7 - i))) & 0xffffffff for i in range(8)]
strs = ", ".join(format_int(v) for v in vals)
return f"SECP256K1_FE_CONST({strs})"
def output_xswiftec_inv_cases():
"""Generate lines corresponding to the xswiftec_inv test cases."""
with open(FILENAME_XSWIFTEC_INV_TEST, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
print("xswiftec_inv cases:")
for row in reader:
u = int.from_bytes(bytes.fromhex(row['u']), 'big')
x = int.from_bytes(bytes.fromhex(row['x']), 'big')
pat = sum(1<<c for c in range(8) if row[f"case{c}_t"])
tstrs = []
for c in range(8):
tstrs.append(format_fe(int.from_bytes(bytes.fromhex(row[f"case{c}_t"]), 'big')))
print(f" {{0x{pat:02x}, {format_fe(u)}, {format_fe(x)}, {{{', '.join(tstrs)}}}}},")
print()
def output_ellswift_decode_cases():
"""Generate lines corresponding to the ellswift_decode test cases."""
with open(FILENAME_ELLSWIFT_DECODE_TEST, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
print("ellswift_decode cases:")
for row in reader:
enc = bytes.fromhex(row['ellswift'])
tval = int.from_bytes(enc[32:], 'big') % reference.FE.SIZE
x = int.from_bytes(bytes.fromhex(row['x']), 'big')
encstr = ", ".join(f"0x{b:02x}" for b in enc)
print(f" {{{{{encstr}}}, {format_fe(x)}, {tval & 1}}},")
print()
output_xswiftec_inv_cases()
output_ellswift_decode_cases()

View File

@ -0,0 +1,78 @@
"""Compare ellswift decoding in the BIP-324 test vectors against the SwiftEC reference code.
Instructions:
* Clone the SwiftEC repository, and enter the directory:
git clone https://github.com/Jchavezsaab/SwiftEC
git checkout 5320a25035d91addde29d14164cce684b56a12ed
cd SwiftEC
* Generate parameters for the secp256k1 curve:
sage --python generate_parameters.py -p secp256k1
* Copy over this file and the CSV test vectors:
cp PATH_TO_BIPS_REPO/bips/bip-0324/{*.csv,test_sage_decoding.py} .
* Run the tests:
sage --python test_sage_decoding.py -p secp256k1
No output = good.
"""
import sys
import csv
from config import F
from Xencoding_0 import Xdecode
FILENAME_PACKET_TEST = 'packet_encoding_test_vectors.csv'
FILENAME_XSWIFTEC_INV_TEST = 'xswiftec_inv_test_vectors.csv'
FILENAME_ELLSWIFT_DECODE_TEST = 'ellswift_decode_test_vectors.csv'
def ellswift_decode_sage(ellswift):
"""Given a 64-byte ellswift encoded public key, get the 32-byte X coordinate."""
u = F(int.from_bytes(ellswift[:32], 'big'))
t = F(int.from_bytes(ellswift[32:], 'big'))
# Reimplement the input correction step.
if u == F(0):
u = F(1)
if t == F(0):
t = F(1)
if u**3 + t**2 + 7 == F(0):
t = F(2) * t
# Invoke reference code
x, z = Xdecode(u, t)
# Convert to bytes.
return int(x / z).to_bytes(32, 'big')
with open(FILENAME_PACKET_TEST, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
bytes_ellswift_ours = bytes.fromhex(row['in_ellswift_ours'])
bytes_ellswift_theirs = bytes.fromhex(row['in_ellswift_theirs'])
assert row['mid_x_ours'] == ellswift_decode_sage(bytes_ellswift_ours).hex()
assert row['mid_x_theirs'] == ellswift_decode_sage(bytes_ellswift_theirs).hex()
with open(FILENAME_XSWIFTEC_INV_TEST, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
udat = bytes.fromhex(row['u'])
xdat = bytes.fromhex(row['x'])
for case in range(8):
tdat = bytes.fromhex(row[f"case{case}_t"])
if tdat:
assert ellswift_decode_sage(udat + tdat) == xdat
with open(FILENAME_ELLSWIFT_DECODE_TEST, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
ellswift = bytes.fromhex(row['ellswift'])
assert ellswift_decode_sage(ellswift).hex() == row['x']

View File

@ -1,17 +0,0 @@
ellswift,x
26b25d457597a7b0463f9620f666dd10aa2c4373a505967c7c8d70922a2d6eceffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2dabde1,240b740607e14d8cb767f53c9dacf5becde98abe73ffa36f096971215280dc58
5a3e80a37915b1601c363acd1601df7ef257d5d32c664004a2ec0484a4f60628ffffffffffffffffffffffffffffffffffffffffffffffffffffffff15d5f3cd,4deaeb3cfbd2abbc9d57fdd83d825a05c45d773d96e247bda136e154769c1f8b
6641161dc1faf1293662e9d81dc994fed6a720d6e0e1ab5702c6a866254a9076ffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f44671f,32f5e32639066d09d5184e36cfca82b9f16076666edb2597bf6c8ca0f9423799
bf5e8ffa51a9e748985800c1d3d7f1a2a6ae7435136593ca8d9637e3f87c699c76cc5805dab9b4eacefdb477f498020fd82bccdbc9c6a2d9ce10586ac85512b4,5579653da55ae6af8c92b0ab623bfede27756fdba141124c72aec43bc5b746e5
df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d,e838221abd40251a45646c40f62550e0acb8ab1ab292df7a9d4f28d72316bd3a
f0caf11f8aea622a396127c3e7e67a6a854dccb736fcdc1270fc071592083e6da839c820778a009421bb1d1eee17cdea622828bd0d065d5b4adb6c0033570a37,bfae8740fc4926b0387803a8db03fa8b9d8b53ec30713a8227bf421b23b11571
f1473fa4fb09147ba9d07832c92ccc0bcd651b696ff463931964066a4c849d12ffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7ac238b,de26c723c76ec977f4cf79b3ba3e27800041930000ee7a74337d0e64fe164937
fd50cee538a3798d17dde484f9d935860a88fe8dd6cd2341254ab5d558b0b67f5c5ec4b2af7c601e0f4b8d3893192292759a5c3b0a760c0589e5337bfb4e8a2d,0969798ab212485d36a0f007f744a17bffbc4fa9c3e73afcb4e7a27fb3580de9
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3d60a4a9252c0b6b080fa045acfcd1437f693f3be2be2ac8223ea525d492fa19ab028942,c163b493f047704ba83e241472ebb2a05f95ef47c6bf5feedd8da33504866d68
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f51ebdbafa7518106309c22d325df6d2663249d158d2f36f1976269d6d4104d9198a108,37d7c5665514f85fe6e4cca488e8abdfc6bc4b3e87ff01ac08eb2504180296e9
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff72a7e655ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1dd15ad9,34818ed876cbbb6710eb832627de9eb7c468846f26bfc336303601593bbb706d
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff92e6fb5cf32ceb01b42ea21ecdacc88a0e59dfbf72692b68d76924ba59f0a81f373d2cee,438c40e9cc47e577f56932b9bea91433acc7be309c017ff8f45a46046ed5aa9f
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffba7d0816157655bf7c7eaf74e26c4fb12043675dcce7580ea49d60317a546c3df2e14f9f,11d52804cc52a73185697681ebb8713dfe4204864fb9989b28e5a3696907710c
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4b84378fffffffffffffffffffffffffffffffffffffffffffffffffffffffff69a56d1,523e0758ee088690c9b95c604ef4d143e4fd3f2d1ac9084e3086750a9686f9bc
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffdac35742ffffffffffffffffffffffffffffffffffffffffffffffffffffffff99d5d507,db7f9b113af6796d460dfc12bef75f947fa1e0102686cf58de6ad5c0af752f82
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeee1f01fffffffffffffffffffffffffffffffffffffffffffffffffffffffff43363e8,c0c123902ec734bde1c6410a93e5d0033e0540120d5be9f555476b842fd2d245
1 ellswift x
2 26b25d457597a7b0463f9620f666dd10aa2c4373a505967c7c8d70922a2d6eceffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2dabde1 240b740607e14d8cb767f53c9dacf5becde98abe73ffa36f096971215280dc58
3 5a3e80a37915b1601c363acd1601df7ef257d5d32c664004a2ec0484a4f60628ffffffffffffffffffffffffffffffffffffffffffffffffffffffff15d5f3cd 4deaeb3cfbd2abbc9d57fdd83d825a05c45d773d96e247bda136e154769c1f8b
4 6641161dc1faf1293662e9d81dc994fed6a720d6e0e1ab5702c6a866254a9076ffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f44671f 32f5e32639066d09d5184e36cfca82b9f16076666edb2597bf6c8ca0f9423799
5 bf5e8ffa51a9e748985800c1d3d7f1a2a6ae7435136593ca8d9637e3f87c699c76cc5805dab9b4eacefdb477f498020fd82bccdbc9c6a2d9ce10586ac85512b4 5579653da55ae6af8c92b0ab623bfede27756fdba141124c72aec43bc5b746e5
6 df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d e838221abd40251a45646c40f62550e0acb8ab1ab292df7a9d4f28d72316bd3a
7 f0caf11f8aea622a396127c3e7e67a6a854dccb736fcdc1270fc071592083e6da839c820778a009421bb1d1eee17cdea622828bd0d065d5b4adb6c0033570a37 bfae8740fc4926b0387803a8db03fa8b9d8b53ec30713a8227bf421b23b11571
8 f1473fa4fb09147ba9d07832c92ccc0bcd651b696ff463931964066a4c849d12ffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7ac238b de26c723c76ec977f4cf79b3ba3e27800041930000ee7a74337d0e64fe164937
9 fd50cee538a3798d17dde484f9d935860a88fe8dd6cd2341254ab5d558b0b67f5c5ec4b2af7c601e0f4b8d3893192292759a5c3b0a760c0589e5337bfb4e8a2d 0969798ab212485d36a0f007f744a17bffbc4fa9c3e73afcb4e7a27fb3580de9
10 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3d60a4a9252c0b6b080fa045acfcd1437f693f3be2be2ac8223ea525d492fa19ab028942 c163b493f047704ba83e241472ebb2a05f95ef47c6bf5feedd8da33504866d68
11 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f51ebdbafa7518106309c22d325df6d2663249d158d2f36f1976269d6d4104d9198a108 37d7c5665514f85fe6e4cca488e8abdfc6bc4b3e87ff01ac08eb2504180296e9
12 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff72a7e655ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1dd15ad9 34818ed876cbbb6710eb832627de9eb7c468846f26bfc336303601593bbb706d
13 ffffffffffffffffffffffffffffffffffffffffffffffffffffffff92e6fb5cf32ceb01b42ea21ecdacc88a0e59dfbf72692b68d76924ba59f0a81f373d2cee 438c40e9cc47e577f56932b9bea91433acc7be309c017ff8f45a46046ed5aa9f
14 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffba7d0816157655bf7c7eaf74e26c4fb12043675dcce7580ea49d60317a546c3df2e14f9f 11d52804cc52a73185697681ebb8713dfe4204864fb9989b28e5a3696907710c
15 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4b84378fffffffffffffffffffffffffffffffffffffffffffffffffffffffff69a56d1 523e0758ee088690c9b95c604ef4d143e4fd3f2d1ac9084e3086750a9686f9bc
16 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffdac35742ffffffffffffffffffffffffffffffffffffffffffffffffffffffff99d5d507 db7f9b113af6796d460dfc12bef75f947fa1e0102686cf58de6ad5c0af752f82
17 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeee1f01fffffffffffffffffffffffffffffffffffffffffffffffffffffffff43363e8 c0c123902ec734bde1c6410a93e5d0033e0540120d5be9f555476b842fd2d245

View File

@ -0,0 +1,33 @@
u,x,case0_t,case1_t,case2_t,case3_t,case4_t,case5_t,case6_t,case7_t,comment
05ff6bdad900fc3261bc7fe34e2fb0f569f06e091ae437d3a52e9da0cbfb9590,80cdf63774ec7022c89a5a8558e373a279170285e0ab27412dbce510bdfe23fc,,,45654798ece071ba79286d04f7f3eb1c3f1d17dd883610f2ad2efd82a287466b,0aeaa886f6b76c7158452418cbf5033adc5747e9e9b5d3b2303db96936528557,,,ba9ab867131f8e4586d792fb080c14e3c0e2e82277c9ef0d52d1027c5d78b5c4,f51557790948938ea7badbe7340afcc523a8b816164a2c4dcfc24695c9ad76d8,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[v=0]&ok;case3:ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[v=0]&ok;case7:ok
1737a85f4c8d146cec96e3ffdca76d9903dcf3bd53061868d478c78c63c2aa9e,39e48dd150d2f429be088dfd5b61882e7e8407483702ae9a5ab35927b15f85ea,1be8cc0b04be0c681d0c6a68f733f82c6c896e0c8a262fcd392918e303a7abf4,605b5814bf9b8cb066667c9e5480d22dc5b6c92f14b4af3ee0a9eb83b03685e3,,,e41733f4fb41f397e2f3959708cc07d3937691f375d9d032c6d6e71bfc58503b,9fa4a7eb4064734f99998361ab7f2dd23a4936d0eb4b50c11f56147b4fc9764c,,,case0:ok;case1:ok;case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:ok;case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
1aaa1ccebf9c724191033df366b36f691c4d902c228033ff4516d122b2564f68,c75541259d3ba98f207eaa30c69634d187d0b6da594e719e420f4898638fc5b0,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(q)];case7:bad[non_square(q)]
2323a1d079b0fd72fc8bb62ec34230a815cb0596c2bfac998bd6b84260f5dc26,239342dfb675500a34a196310b8d87d54f49dcac9da50c1743ceab41a7b249ff,f63580b8aa49c4846de56e39e1b3e73f171e881eba8c66f614e67e5c975dfc07,b6307b332e699f1cf77841d90af25365404deb7fed5edb3090db49e642a156b6,,,09ca7f4755b63b7b921a91c61e4c18c0e8e177e145739909eb1981a268a20028,49cf84ccd19660e30887be26f50dac9abfb2148012a124cf6f24b618bd5ea579,,,case0:ok;case1:ok;case2:bad[non_square(q)];case3:bad[non_square(q)];case4:ok;case5:ok;case6:bad[non_square(q)];case7:bad[non_square(q)]
2dc90e640cb646ae9164c0b5a9ef0169febe34dc4437d6e46acb0e27e219d1e8,d236f19bf349b9516e9b3f4a5610fe960141cb23bbc8291b9534f1d71de62a47,e69df7d9c026c36600ebdf588072675847c0c431c8eb730682533e964b6252c9,4f18bbdf7c2d6c5f818c18802fa35cd069eaa79fff74e4fc837c80d93fece2f8,,,196208263fd93c99ff1420a77f8d98a7b83f3bce37148cf97dacc168b49da966,b0e7442083d293a07e73e77fd05ca32f96155860008b1b037c837f25c0131937,,,case0:ok;case1:info[v=0]&ok;case2:bad[non_square(q)];case3:bad[non_square(q)];case4:ok;case5:info[v=0]&ok;case6:bad[non_square(q)];case7:bad[non_square(q)]
3edd7b3980e2f2f34d1409a207069f881fda5f96f08027ac4465b63dc278d672,053a98de4a27b1961155822b3a3121f03b2a14458bd80eb4a560c4c7a85c149c,,,b3dae4b7dcf858e4c6968057cef2b156465431526538199cf52dc1b2d62fda30,4aa77dd55d6b6d3cfa10cc9d0fe42f79232e4575661049ae36779c1d0c666d88,,,4c251b482307a71b39697fa8310d4ea9b9abcead9ac7e6630ad23e4c29d021ff,b558822aa29492c305ef3362f01bd086dcd1ba8a99efb651c98863e1f3998ea7,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:ok;case3:ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:ok;case7:ok
4295737efcb1da6fb1d96b9ca7dcd1e320024b37a736c4948b62598173069f70,fa7ffe4f25f88362831c087afe2e8a9b0713e2cac1ddca6a383205a266f14307,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(s)];case7:bad[non_square(s)]
587c1a0cee91939e7f784d23b963004a3bf44f5d4e32a0081995ba20b0fca59e,2ea988530715e8d10363907ff25124524d471ba2454d5ce3be3f04194dfd3a3c,cfd5a094aa0b9b8891b76c6ab9438f66aa1c095a65f9f70135e8171292245e74,a89057d7c6563f0d6efa19ae84412b8a7b47e791a191ecdfdf2af84fd97bc339,475d0ae9ef46920df07b34117be5a0817de1023e3cc32689e9be145b406b0aef,a0759178ad80232454f827ef05ea3e72ad8d75418e6d4cc1cd4f5306c5e7c453,302a5f6b55f464776e48939546bc709955e3f6a59a0608feca17e8ec6ddb9dbb,576fa82839a9c0f29105e6517bbed47584b8186e5e6e132020d507af268438f6,b8a2f51610b96df20f84cbee841a5f7e821efdc1c33cd9761641eba3bf94f140,5f8a6e87527fdcdbab07d810fa15c18d52728abe7192b33e32b0acf83a1837dc,case0:ok;case1:ok;case2:ok;case3:ok;case4:ok;case5:ok;case6:ok;case7:ok
5fa88b3365a635cbbcee003cce9ef51dd1a310de277e441abccdb7be1e4ba249,79461ff62bfcbcac4249ba84dd040f2cec3c63f725204dc7f464c16bf0ff3170,,,6bb700e1f4d7e236e8d193ff4a76c1b3bcd4e2b25acac3d51c8dac653fe909a0,f4c73410633da7f63a4f1d55aec6dd32c4c6d89ee74075edb5515ed90da9e683,,,9448ff1e0b281dc9172e6c00b5893e4c432b1d4da5353c2ae3725399c016f28f,0b38cbef9cc25809c5b0e2aa513922cd3b39276118bf8a124aaea125f25615ac,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:ok;case3:info[v=0]&ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:ok;case7:info[v=0]&ok
6fb31c7531f03130b42b155b952779efbb46087dd9807d241a48eac63c3d96d6,56f81be753e8d4ae4940ea6f46f6ec9fda66a6f96cc95f506cb2b57490e94260,,,59059774795bdb7a837fbe1140a5fa59984f48af8df95d57dd6d1c05437dcec1,22a644db79376ad4e7b3a009e58b3f13137c54fdf911122cc93667c47077d784,,,a6fa688b86a424857c8041eebf5a05a667b0b7507206a2a82292e3f9bc822d6e,dd59bb2486c8952b184c5ff61a74c0ecec83ab0206eeedd336c9983a8f8824ab,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:ok;case3:info[v=0]&ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:ok;case7:info[v=0]&ok
704cd226e71cb6826a590e80dac90f2d2f5830f0fdf135a3eae3965bff25ff12,138e0afa68936ee670bd2b8db53aedbb7bea2a8597388b24d0518edd22ad66ec,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(q)];case7:bad[non_square(q)]
725e914792cb8c8949e7e1168b7cdd8a8094c91c6ec2202ccd53a6a18771edeb,8da16eb86d347376b6181ee9748322757f6b36e3913ddfd332ac595d788e0e44,dd357786b9f6873330391aa5625809654e43116e82a5a5d82ffd1d6624101fc4,a0b7efca01814594c59c9aae8e49700186ca5d95e88bcc80399044d9c2d8613d,,,22ca8879460978cccfc6e55a9da7f69ab1bcee917d5a5a27d002e298dbefdc6b,5f481035fe7eba6b3a63655171b68ffe7935a26a1774337fc66fbb253d279af2,,,case0:ok;case1:info[v=0]&ok;case2:bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:info[v=0]&ok;case6:bad[non_square(s)];case7:bad[non_square(s)]
78fe6b717f2ea4a32708d79c151bf503a5312a18c0963437e865cc6ed3f6ae97,8701948e80d15b5cd8f72863eae40afc5aced5e73f69cbc8179a33902c094d98,,,,,,,,,case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:bad[non_square(q)];case7:bad[non_square(q)]
7c37bb9c5061dc07413f11acd5a34006e64c5c457fdb9a438f217255a961f50d,5c1a76b44568eb59d6789a7442d9ed7cdc6226b7752b4ff8eaf8e1a95736e507,,,b94d30cd7dbff60b64620c17ca0fafaa40b3d1f52d077a60a2e0cafd145086c2,,,,46b2cf32824009f49b9df3e835f05055bf4c2e0ad2f8859f5d1f3501ebaf756d,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
82388888967f82a6b444438a7d44838e13c0d478b9ca060da95a41fb94303de6,29e9654170628fec8b4972898b113cf98807f4609274f4f3140d0674157c90a0,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
91298f5770af7a27f0a47188d24c3b7bf98ab2990d84b0b898507e3c561d6472,144f4ccbd9a74698a88cbf6fd00ad886d339d29ea19448f2c572cac0a07d5562,e6a0ffa3807f09dadbe71e0f4be4725f2832e76cad8dc1d943ce839375eff248,837b8e68d4917544764ad0903cb11f8615d2823cefbb06d89049dbabc69befda,,,195f005c7f80f6252418e1f0b41b8da0d7cd189352723e26bc317c6b8a1009e7,7c8471972b6e8abb89b52f6fc34ee079ea2d7dc31044f9276fb6245339640c55,,,case0:ok;case1:ok;case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:ok;case5:ok;case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
b682f3d03bbb5dee4f54b5ebfba931b4f52f6a191e5c2f483c73c66e9ace97e1,904717bf0bc0cb7873fcdc38aa97f19e3a62630972acff92b24cc6dda197cb96,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(s)];case7:bad[non_square(s)]
c17ec69e665f0fb0dbab48d9c2f94d12ec8a9d7eacb58084833091801eb0b80b,147756e66d96e31c426d3cc85ed0c4cfbef6341dd8b285585aa574ea0204b55e,6f4aea431a0043bdd03134d6d9159119ce034b88c32e50e8e36c4ee45eac7ae9,fd5be16d4ffa2690126c67c3ef7cb9d29b74d397c78b06b3605fda34dc9696a6,5e9c60792a2f000e45c6250f296f875e174efc0e9703e628706103a9dd2d82c7,,90b515bce5ffbc422fcecb2926ea6ee631fcb4773cd1af171c93b11aa1538146,02a41e92b005d96fed93983c1083462d648b2c683874f94c9fa025ca23696589,a1639f86d5d0fff1ba39daf0d69078a1e8b103f168fc19d78f9efc5522d27968,,case0:ok;case1:ok;case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:ok;case5:ok;case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
c25172fc3f29b6fc4a1155b8575233155486b27464b74b8b260b499a3f53cb14,1ea9cbdb35cf6e0329aa31b0bb0a702a65123ed008655a93b7dcd5280e52e1ab,,,7422edc7843136af0053bb8854448a8299994f9ddcefd3a9a92d45462c59298a,78c7774a266f8b97ea23d05d064f033c77319f923f6b78bce4e20bf05fa5398d,,,8bdd12387bcec950ffac4477abbb757d6666b06223102c5656d2bab8d3a6d2a5,873888b5d990746815dc2fa2f9b0fcc388ce606dc09487431b1df40ea05ac2a2,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:ok;case3:ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:ok;case7:ok
cab6626f832a4b1280ba7add2fc5322ff011caededf7ff4db6735d5026dc0367,2b2bef0852c6f7c95d72ac99a23802b875029cd573b248d1f1b3fc8033788eb6,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
d8621b4ffc85b9ed56e99d8dd1dd24aedcecb14763b861a17112dc771a104fd2,812cabe972a22aa67c7da0c94d8a936296eb9949d70c37cb2b2487574cb3ce58,fbc5febc6fdbc9ae3eb88a93b982196e8b6275a6d5a73c17387e000c711bd0e3,8724c96bd4e5527f2dd195a51c468d2d211ba2fac7cbe0b4b3434253409fb42d,,,043a014390243651c147756c467de691749d8a592a58c3e8c781fff28ee42b4c,78db36942b1aad80d22e6a5ae3b972d2dee45d0538341f4b4cbcbdabbf604802,,,case0:ok;case1:ok;case2:bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:ok;case6:bad[non_square(s)];case7:bad[non_square(s)]
da463164c6f4bf7129ee5f0ec00f65a675a8adf1bd931b39b64806afdcda9a22,25b9ce9b390b408ed611a0f13ff09a598a57520e426ce4c649b7f94f2325620d,,,,,,,,,case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:bad[non_square(s)];case7:bad[non_square(s)]
dafc971e4a3a7b6dcfb42a08d9692d82ad9e7838523fcbda1d4827e14481ae2d,250368e1b5c58492304bd5f72696d27d526187c7adc03425e2b7d81dbb7e4e02,,,370c28f1be665efacde6aa436bf86fe21e6e314c1e53dd040e6c73a46b4c8c49,cd8acee98ffe56531a84d7eb3e48fa4034206ce825ace907d0edf0eaeb5e9ca2,,,c8f3d70e4199a105321955bc9407901de191ceb3e1ac22fbf1938c5a94b36fe6,327531167001a9ace57b2814c1b705bfcbdf9317da5316f82f120f1414a15f8d,case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:ok;case3:ok;case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:ok;case7:ok
e0294c8bc1a36b4166ee92bfa70a5c34976fa9829405efea8f9cd54dcb29b99e,ae9690d13b8d20a0fbbf37bed8474f67a04e142f56efd78770a76b359165d8a1,,,dcd45d935613916af167b029058ba3a700d37150b9df34728cb05412c16d4182,,,,232ba26ca9ec6e950e984fd6fa745c58ff2c8eaf4620cb8d734fabec3e92baad,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
e148441cd7b92b8b0e4fa3bd68712cfd0d709ad198cace611493c10e97f5394e,164a639794d74c53afc4d3294e79cdb3cd25f99f6df45c000f758aba54d699c0,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
e4b00ec97aadcca97644d3b0c8a931b14ce7bcf7bc8779546d6e35aa5937381c,94e9588d41647b3fcc772dc8d83c67ce3be003538517c834103d2cd49d62ef4d,c88d25f41407376bb2c03a7fffeb3ec7811cc43491a0c3aac0378cdc78357bee,51c02636ce00c2345ecd89adb6089fe4d5e18ac924e3145e6669501cd37a00d4,205b3512db40521cb200952e67b46f67e09e7839e0de44004138329ebd9138c5,58aab390ab6fb55c1d1b80897a207ce94a78fa5b4aa61a33398bcae9adb20d3e,3772da0bebf8c8944d3fc5800014c1387ee33bcb6e5f3c553fc8732287ca8041,ae3fd9c931ff3dcba132765249f7601b2a1e7536db1ceba19996afe22c85fb5b,dfa4caed24bfade34dff6ad1984b90981f6187c61f21bbffbec7cd60426ec36a,a7554c6f54904aa3e2e47f7685df8316b58705a4b559e5ccc6743515524deef1,case0:ok;case1:ok;case2:ok;case3:info[v=0]&ok;case4:ok;case5:ok;case6:ok;case7:info[v=0]&ok
e5bbb9ef360d0a501618f0067d36dceb75f5be9a620232aa9fd5139d0863fde5,e5bbb9ef360d0a501618f0067d36dceb75f5be9a620232aa9fd5139d0863fde5,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[s=0];case3:bad[s=0];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[s=0];case7:bad[s=0]
e6bcb5c3d63467d490bfa54fbbc6092a7248c25e11b248dc2964a6e15edb1457,19434a3c29cb982b6f405ab04439f6d58db73da1ee4db723d69b591da124e7d8,67119877832ab8f459a821656d8261f544a553b89ae4f25c52a97134b70f3426,ffee02f5e649c07f0560eff1867ec7b32d0e595e9b1c0ea6e2a4fc70c97cd71f,b5e0c189eb5b4bacd025b7444d74178be8d5246cfa4a9a207964a057ee969992,5746e4591bf7f4c3044609ea372e908603975d279fdef8349f0b08d32f07619d,98ee67887cd5470ba657de9a927d9e0abb5aac47651b0da3ad568eca48f0c809,0011fd0a19b63f80fa9f100e7981384cd2f1a6a164e3f1591d5b038e36832510,4a1f3e7614a4b4532fda48bbb28be874172adb9305b565df869b5fa71169629d,a8b91ba6e4080b3cfbb9f615c8d16f79fc68a2d8602107cb60f4f72bd0f89a92,case0:ok;case1:info[v=0]&ok;case2:ok;case3:ok;case4:ok;case5:info[v=0]&ok;case6:ok;case7:ok
f28fba64af766845eb2f4302456e2b9f8d80affe57e7aae42738d7cddb1c2ce6,f28fba64af766845eb2f4302456e2b9f8d80affe57e7aae42738d7cddb1c2ce6,4f867ad8bb3d840409d26b67307e62100153273f72fa4b7484becfa14ebe7408,5bbc4f59e452cc5f22a99144b10ce8989a89a995ec3cea1c91ae10e8f721bb5d,,,b079852744c27bfbf62d9498cf819deffeacd8c08d05b48b7b41305db1418827,a443b0a61bad33a0dd566ebb4ef317676576566a13c315e36e51ef1608de40d2,,,case0:ok;case1:ok;case2:bad[s=0];case3:bad[s=0];case4:ok;case5:ok;case6:bad[s=0];case7:bad[s=0]
f455605bc85bf48e3a908c31023faf98381504c6c6d3aeb9ede55f8dd528924d,d31fbcd5cdb798f6c00db6692f8fe8967fa9c79dd10958f4a194f01374905e99,,,0c00c5715b56fe632d814ad8a77f8e66628ea47a6116834f8c1218f3a03cbd50,df88e44fac84fa52df4d59f48819f18f6a8cd4151d162afaf773166f57c7ff46,,,f3ff3a8ea4a9019cd27eb527588071999d715b859ee97cb073ede70b5fc33edf,20771bb0537b05ad20b2a60b77e60e7095732beae2e9d505088ce98fa837fce9,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[v=0]&ok;case3:ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[v=0]&ok;case7:ok
f58cd4d9830bad322699035e8246007d4be27e19b6f53621317b4f309b3daa9d,78ec2b3dc0948de560148bbc7c6dc9633ad5df70a5a5750cbed721804f082a3b,6c4c580b76c7594043569f9dae16dc2801c16a1fbe12860881b75f8ef929bce5,94231355e7385c5f25ca436aa64191471aea4393d6e86ab7a35fe2afacaefd0d,dff2a1951ada6db574df834048149da3397a75b829abf58c7e69db1b41ac0989,a52b66d3c907035548028bf804711bf422aba95f1a666fc86f4648e05f29caae,93b3a7f48938a6bfbca9606251e923d7fe3e95e041ed79f77e48a07006d63f4a,6bdcecaa18c7a3a0da35bc9559be6eb8e515bc6c291795485ca01d4f5350ff22,200d5e6ae525924a8b207cbfb7eb625cc6858a47d6540a73819624e3be53f2a6,5ad4992c36f8fcaab7fd7407fb8ee40bdd5456a0e599903790b9b71ea0d63181,case0:ok;case1:ok;case2:info[v=0]&ok;case3:ok;case4:ok;case5:ok;case6:info[v=0]&ok;case7:ok
fd7d912a40f182a3588800d69ebfb5048766da206fd7ebc8d2436c81cbef6421,8d37c862054debe731694536ff46b273ec122b35a9bf1445ac3c4ff9f262c952,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
1 u x case0_t case1_t case2_t case3_t case4_t case5_t case6_t case7_t comment
2 05ff6bdad900fc3261bc7fe34e2fb0f569f06e091ae437d3a52e9da0cbfb9590 80cdf63774ec7022c89a5a8558e373a279170285e0ab27412dbce510bdfe23fc 45654798ece071ba79286d04f7f3eb1c3f1d17dd883610f2ad2efd82a287466b 0aeaa886f6b76c7158452418cbf5033adc5747e9e9b5d3b2303db96936528557 ba9ab867131f8e4586d792fb080c14e3c0e2e82277c9ef0d52d1027c5d78b5c4 f51557790948938ea7badbe7340afcc523a8b816164a2c4dcfc24695c9ad76d8 case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[v=0]&ok;case3:ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[v=0]&ok;case7:ok
3 1737a85f4c8d146cec96e3ffdca76d9903dcf3bd53061868d478c78c63c2aa9e 39e48dd150d2f429be088dfd5b61882e7e8407483702ae9a5ab35927b15f85ea 1be8cc0b04be0c681d0c6a68f733f82c6c896e0c8a262fcd392918e303a7abf4 605b5814bf9b8cb066667c9e5480d22dc5b6c92f14b4af3ee0a9eb83b03685e3 e41733f4fb41f397e2f3959708cc07d3937691f375d9d032c6d6e71bfc58503b 9fa4a7eb4064734f99998361ab7f2dd23a4936d0eb4b50c11f56147b4fc9764c case0:ok;case1:ok;case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:ok;case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
4 1aaa1ccebf9c724191033df366b36f691c4d902c228033ff4516d122b2564f68 c75541259d3ba98f207eaa30c69634d187d0b6da594e719e420f4898638fc5b0 case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(q)];case7:bad[non_square(q)]
5 2323a1d079b0fd72fc8bb62ec34230a815cb0596c2bfac998bd6b84260f5dc26 239342dfb675500a34a196310b8d87d54f49dcac9da50c1743ceab41a7b249ff f63580b8aa49c4846de56e39e1b3e73f171e881eba8c66f614e67e5c975dfc07 b6307b332e699f1cf77841d90af25365404deb7fed5edb3090db49e642a156b6 09ca7f4755b63b7b921a91c61e4c18c0e8e177e145739909eb1981a268a20028 49cf84ccd19660e30887be26f50dac9abfb2148012a124cf6f24b618bd5ea579 case0:ok;case1:ok;case2:bad[non_square(q)];case3:bad[non_square(q)];case4:ok;case5:ok;case6:bad[non_square(q)];case7:bad[non_square(q)]
6 2dc90e640cb646ae9164c0b5a9ef0169febe34dc4437d6e46acb0e27e219d1e8 d236f19bf349b9516e9b3f4a5610fe960141cb23bbc8291b9534f1d71de62a47 e69df7d9c026c36600ebdf588072675847c0c431c8eb730682533e964b6252c9 4f18bbdf7c2d6c5f818c18802fa35cd069eaa79fff74e4fc837c80d93fece2f8 196208263fd93c99ff1420a77f8d98a7b83f3bce37148cf97dacc168b49da966 b0e7442083d293a07e73e77fd05ca32f96155860008b1b037c837f25c0131937 case0:ok;case1:info[v=0]&ok;case2:bad[non_square(q)];case3:bad[non_square(q)];case4:ok;case5:info[v=0]&ok;case6:bad[non_square(q)];case7:bad[non_square(q)]
7 3edd7b3980e2f2f34d1409a207069f881fda5f96f08027ac4465b63dc278d672 053a98de4a27b1961155822b3a3121f03b2a14458bd80eb4a560c4c7a85c149c b3dae4b7dcf858e4c6968057cef2b156465431526538199cf52dc1b2d62fda30 4aa77dd55d6b6d3cfa10cc9d0fe42f79232e4575661049ae36779c1d0c666d88 4c251b482307a71b39697fa8310d4ea9b9abcead9ac7e6630ad23e4c29d021ff b558822aa29492c305ef3362f01bd086dcd1ba8a99efb651c98863e1f3998ea7 case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:ok;case3:ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:ok;case7:ok
8 4295737efcb1da6fb1d96b9ca7dcd1e320024b37a736c4948b62598173069f70 fa7ffe4f25f88362831c087afe2e8a9b0713e2cac1ddca6a383205a266f14307 case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(s)];case7:bad[non_square(s)]
9 587c1a0cee91939e7f784d23b963004a3bf44f5d4e32a0081995ba20b0fca59e 2ea988530715e8d10363907ff25124524d471ba2454d5ce3be3f04194dfd3a3c cfd5a094aa0b9b8891b76c6ab9438f66aa1c095a65f9f70135e8171292245e74 a89057d7c6563f0d6efa19ae84412b8a7b47e791a191ecdfdf2af84fd97bc339 475d0ae9ef46920df07b34117be5a0817de1023e3cc32689e9be145b406b0aef a0759178ad80232454f827ef05ea3e72ad8d75418e6d4cc1cd4f5306c5e7c453 302a5f6b55f464776e48939546bc709955e3f6a59a0608feca17e8ec6ddb9dbb 576fa82839a9c0f29105e6517bbed47584b8186e5e6e132020d507af268438f6 b8a2f51610b96df20f84cbee841a5f7e821efdc1c33cd9761641eba3bf94f140 5f8a6e87527fdcdbab07d810fa15c18d52728abe7192b33e32b0acf83a1837dc case0:ok;case1:ok;case2:ok;case3:ok;case4:ok;case5:ok;case6:ok;case7:ok
10 5fa88b3365a635cbbcee003cce9ef51dd1a310de277e441abccdb7be1e4ba249 79461ff62bfcbcac4249ba84dd040f2cec3c63f725204dc7f464c16bf0ff3170 6bb700e1f4d7e236e8d193ff4a76c1b3bcd4e2b25acac3d51c8dac653fe909a0 f4c73410633da7f63a4f1d55aec6dd32c4c6d89ee74075edb5515ed90da9e683 9448ff1e0b281dc9172e6c00b5893e4c432b1d4da5353c2ae3725399c016f28f 0b38cbef9cc25809c5b0e2aa513922cd3b39276118bf8a124aaea125f25615ac case0:bad[non_square(s)];case1:bad[non_square(s)];case2:ok;case3:info[v=0]&ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:ok;case7:info[v=0]&ok
11 6fb31c7531f03130b42b155b952779efbb46087dd9807d241a48eac63c3d96d6 56f81be753e8d4ae4940ea6f46f6ec9fda66a6f96cc95f506cb2b57490e94260 59059774795bdb7a837fbe1140a5fa59984f48af8df95d57dd6d1c05437dcec1 22a644db79376ad4e7b3a009e58b3f13137c54fdf911122cc93667c47077d784 a6fa688b86a424857c8041eebf5a05a667b0b7507206a2a82292e3f9bc822d6e dd59bb2486c8952b184c5ff61a74c0ecec83ab0206eeedd336c9983a8f8824ab case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:ok;case3:info[v=0]&ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:ok;case7:info[v=0]&ok
12 704cd226e71cb6826a590e80dac90f2d2f5830f0fdf135a3eae3965bff25ff12 138e0afa68936ee670bd2b8db53aedbb7bea2a8597388b24d0518edd22ad66ec case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(q)];case7:bad[non_square(q)]
13 725e914792cb8c8949e7e1168b7cdd8a8094c91c6ec2202ccd53a6a18771edeb 8da16eb86d347376b6181ee9748322757f6b36e3913ddfd332ac595d788e0e44 dd357786b9f6873330391aa5625809654e43116e82a5a5d82ffd1d6624101fc4 a0b7efca01814594c59c9aae8e49700186ca5d95e88bcc80399044d9c2d8613d 22ca8879460978cccfc6e55a9da7f69ab1bcee917d5a5a27d002e298dbefdc6b 5f481035fe7eba6b3a63655171b68ffe7935a26a1774337fc66fbb253d279af2 case0:ok;case1:info[v=0]&ok;case2:bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:info[v=0]&ok;case6:bad[non_square(s)];case7:bad[non_square(s)]
14 78fe6b717f2ea4a32708d79c151bf503a5312a18c0963437e865cc6ed3f6ae97 8701948e80d15b5cd8f72863eae40afc5aced5e73f69cbc8179a33902c094d98 case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:bad[non_square(q)];case7:bad[non_square(q)]
15 7c37bb9c5061dc07413f11acd5a34006e64c5c457fdb9a438f217255a961f50d 5c1a76b44568eb59d6789a7442d9ed7cdc6226b7752b4ff8eaf8e1a95736e507 b94d30cd7dbff60b64620c17ca0fafaa40b3d1f52d077a60a2e0cafd145086c2 46b2cf32824009f49b9df3e835f05055bf4c2e0ad2f8859f5d1f3501ebaf756d case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
16 82388888967f82a6b444438a7d44838e13c0d478b9ca060da95a41fb94303de6 29e9654170628fec8b4972898b113cf98807f4609274f4f3140d0674157c90a0 case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
17 91298f5770af7a27f0a47188d24c3b7bf98ab2990d84b0b898507e3c561d6472 144f4ccbd9a74698a88cbf6fd00ad886d339d29ea19448f2c572cac0a07d5562 e6a0ffa3807f09dadbe71e0f4be4725f2832e76cad8dc1d943ce839375eff248 837b8e68d4917544764ad0903cb11f8615d2823cefbb06d89049dbabc69befda 195f005c7f80f6252418e1f0b41b8da0d7cd189352723e26bc317c6b8a1009e7 7c8471972b6e8abb89b52f6fc34ee079ea2d7dc31044f9276fb6245339640c55 case0:ok;case1:ok;case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:ok;case5:ok;case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
18 b682f3d03bbb5dee4f54b5ebfba931b4f52f6a191e5c2f483c73c66e9ace97e1 904717bf0bc0cb7873fcdc38aa97f19e3a62630972acff92b24cc6dda197cb96 case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(s)];case7:bad[non_square(s)]
19 c17ec69e665f0fb0dbab48d9c2f94d12ec8a9d7eacb58084833091801eb0b80b 147756e66d96e31c426d3cc85ed0c4cfbef6341dd8b285585aa574ea0204b55e 6f4aea431a0043bdd03134d6d9159119ce034b88c32e50e8e36c4ee45eac7ae9 fd5be16d4ffa2690126c67c3ef7cb9d29b74d397c78b06b3605fda34dc9696a6 5e9c60792a2f000e45c6250f296f875e174efc0e9703e628706103a9dd2d82c7 90b515bce5ffbc422fcecb2926ea6ee631fcb4773cd1af171c93b11aa1538146 02a41e92b005d96fed93983c1083462d648b2c683874f94c9fa025ca23696589 a1639f86d5d0fff1ba39daf0d69078a1e8b103f168fc19d78f9efc5522d27968 case0:ok;case1:ok;case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:ok;case5:ok;case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
20 c25172fc3f29b6fc4a1155b8575233155486b27464b74b8b260b499a3f53cb14 1ea9cbdb35cf6e0329aa31b0bb0a702a65123ed008655a93b7dcd5280e52e1ab 7422edc7843136af0053bb8854448a8299994f9ddcefd3a9a92d45462c59298a 78c7774a266f8b97ea23d05d064f033c77319f923f6b78bce4e20bf05fa5398d 8bdd12387bcec950ffac4477abbb757d6666b06223102c5656d2bab8d3a6d2a5 873888b5d990746815dc2fa2f9b0fcc388ce606dc09487431b1df40ea05ac2a2 case0:bad[non_square(s)];case1:bad[non_square(s)];case2:ok;case3:ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:ok;case7:ok
21 cab6626f832a4b1280ba7add2fc5322ff011caededf7ff4db6735d5026dc0367 2b2bef0852c6f7c95d72ac99a23802b875029cd573b248d1f1b3fc8033788eb6 case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
22 d8621b4ffc85b9ed56e99d8dd1dd24aedcecb14763b861a17112dc771a104fd2 812cabe972a22aa67c7da0c94d8a936296eb9949d70c37cb2b2487574cb3ce58 fbc5febc6fdbc9ae3eb88a93b982196e8b6275a6d5a73c17387e000c711bd0e3 8724c96bd4e5527f2dd195a51c468d2d211ba2fac7cbe0b4b3434253409fb42d 043a014390243651c147756c467de691749d8a592a58c3e8c781fff28ee42b4c 78db36942b1aad80d22e6a5ae3b972d2dee45d0538341f4b4cbcbdabbf604802 case0:ok;case1:ok;case2:bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:ok;case6:bad[non_square(s)];case7:bad[non_square(s)]
23 da463164c6f4bf7129ee5f0ec00f65a675a8adf1bd931b39b64806afdcda9a22 25b9ce9b390b408ed611a0f13ff09a598a57520e426ce4c649b7f94f2325620d case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:bad[non_square(s)];case7:bad[non_square(s)]
24 dafc971e4a3a7b6dcfb42a08d9692d82ad9e7838523fcbda1d4827e14481ae2d 250368e1b5c58492304bd5f72696d27d526187c7adc03425e2b7d81dbb7e4e02 370c28f1be665efacde6aa436bf86fe21e6e314c1e53dd040e6c73a46b4c8c49 cd8acee98ffe56531a84d7eb3e48fa4034206ce825ace907d0edf0eaeb5e9ca2 c8f3d70e4199a105321955bc9407901de191ceb3e1ac22fbf1938c5a94b36fe6 327531167001a9ace57b2814c1b705bfcbdf9317da5316f82f120f1414a15f8d case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:ok;case3:ok;case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:ok;case7:ok
25 e0294c8bc1a36b4166ee92bfa70a5c34976fa9829405efea8f9cd54dcb29b99e ae9690d13b8d20a0fbbf37bed8474f67a04e142f56efd78770a76b359165d8a1 dcd45d935613916af167b029058ba3a700d37150b9df34728cb05412c16d4182 232ba26ca9ec6e950e984fd6fa745c58ff2c8eaf4620cb8d734fabec3e92baad case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
26 e148441cd7b92b8b0e4fa3bd68712cfd0d709ad198cace611493c10e97f5394e 164a639794d74c53afc4d3294e79cdb3cd25f99f6df45c000f758aba54d699c0 case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
27 e4b00ec97aadcca97644d3b0c8a931b14ce7bcf7bc8779546d6e35aa5937381c 94e9588d41647b3fcc772dc8d83c67ce3be003538517c834103d2cd49d62ef4d c88d25f41407376bb2c03a7fffeb3ec7811cc43491a0c3aac0378cdc78357bee 51c02636ce00c2345ecd89adb6089fe4d5e18ac924e3145e6669501cd37a00d4 205b3512db40521cb200952e67b46f67e09e7839e0de44004138329ebd9138c5 58aab390ab6fb55c1d1b80897a207ce94a78fa5b4aa61a33398bcae9adb20d3e 3772da0bebf8c8944d3fc5800014c1387ee33bcb6e5f3c553fc8732287ca8041 ae3fd9c931ff3dcba132765249f7601b2a1e7536db1ceba19996afe22c85fb5b dfa4caed24bfade34dff6ad1984b90981f6187c61f21bbffbec7cd60426ec36a a7554c6f54904aa3e2e47f7685df8316b58705a4b559e5ccc6743515524deef1 case0:ok;case1:ok;case2:ok;case3:info[v=0]&ok;case4:ok;case5:ok;case6:ok;case7:info[v=0]&ok
28 e5bbb9ef360d0a501618f0067d36dceb75f5be9a620232aa9fd5139d0863fde5 e5bbb9ef360d0a501618f0067d36dceb75f5be9a620232aa9fd5139d0863fde5 case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[s=0];case3:bad[s=0];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[s=0];case7:bad[s=0]
29 e6bcb5c3d63467d490bfa54fbbc6092a7248c25e11b248dc2964a6e15edb1457 19434a3c29cb982b6f405ab04439f6d58db73da1ee4db723d69b591da124e7d8 67119877832ab8f459a821656d8261f544a553b89ae4f25c52a97134b70f3426 ffee02f5e649c07f0560eff1867ec7b32d0e595e9b1c0ea6e2a4fc70c97cd71f b5e0c189eb5b4bacd025b7444d74178be8d5246cfa4a9a207964a057ee969992 5746e4591bf7f4c3044609ea372e908603975d279fdef8349f0b08d32f07619d 98ee67887cd5470ba657de9a927d9e0abb5aac47651b0da3ad568eca48f0c809 0011fd0a19b63f80fa9f100e7981384cd2f1a6a164e3f1591d5b038e36832510 4a1f3e7614a4b4532fda48bbb28be874172adb9305b565df869b5fa71169629d a8b91ba6e4080b3cfbb9f615c8d16f79fc68a2d8602107cb60f4f72bd0f89a92 case0:ok;case1:info[v=0]&ok;case2:ok;case3:ok;case4:ok;case5:info[v=0]&ok;case6:ok;case7:ok
30 f28fba64af766845eb2f4302456e2b9f8d80affe57e7aae42738d7cddb1c2ce6 f28fba64af766845eb2f4302456e2b9f8d80affe57e7aae42738d7cddb1c2ce6 4f867ad8bb3d840409d26b67307e62100153273f72fa4b7484becfa14ebe7408 5bbc4f59e452cc5f22a99144b10ce8989a89a995ec3cea1c91ae10e8f721bb5d b079852744c27bfbf62d9498cf819deffeacd8c08d05b48b7b41305db1418827 a443b0a61bad33a0dd566ebb4ef317676576566a13c315e36e51ef1608de40d2 case0:ok;case1:ok;case2:bad[s=0];case3:bad[s=0];case4:ok;case5:ok;case6:bad[s=0];case7:bad[s=0]
31 f455605bc85bf48e3a908c31023faf98381504c6c6d3aeb9ede55f8dd528924d d31fbcd5cdb798f6c00db6692f8fe8967fa9c79dd10958f4a194f01374905e99 0c00c5715b56fe632d814ad8a77f8e66628ea47a6116834f8c1218f3a03cbd50 df88e44fac84fa52df4d59f48819f18f6a8cd4151d162afaf773166f57c7ff46 f3ff3a8ea4a9019cd27eb527588071999d715b859ee97cb073ede70b5fc33edf 20771bb0537b05ad20b2a60b77e60e7095732beae2e9d505088ce98fa837fce9 case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[v=0]&ok;case3:ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[v=0]&ok;case7:ok
32 f58cd4d9830bad322699035e8246007d4be27e19b6f53621317b4f309b3daa9d 78ec2b3dc0948de560148bbc7c6dc9633ad5df70a5a5750cbed721804f082a3b 6c4c580b76c7594043569f9dae16dc2801c16a1fbe12860881b75f8ef929bce5 94231355e7385c5f25ca436aa64191471aea4393d6e86ab7a35fe2afacaefd0d dff2a1951ada6db574df834048149da3397a75b829abf58c7e69db1b41ac0989 a52b66d3c907035548028bf804711bf422aba95f1a666fc86f4648e05f29caae 93b3a7f48938a6bfbca9606251e923d7fe3e95e041ed79f77e48a07006d63f4a 6bdcecaa18c7a3a0da35bc9559be6eb8e515bc6c291795485ca01d4f5350ff22 200d5e6ae525924a8b207cbfb7eb625cc6858a47d6540a73819624e3be53f2a6 5ad4992c36f8fcaab7fd7407fb8ee40bdd5456a0e599903790b9b71ea0d63181 case0:ok;case1:ok;case2:info[v=0]&ok;case3:ok;case4:ok;case5:ok;case6:info[v=0]&ok;case7:ok
33 fd7d912a40f182a3588800d69ebfb5048766da206fd7ebc8d2436c81cbef6421 8d37c862054debe731694536ff46b273ec122b35a9bf1445ac3c4ff9f262c952 case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]