mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-14 11:26:09 -05:00
![Pieter Wuille](/assets/img/avatar_default.png)
705ce7ed8c Merge bitcoin-core/secp256k1#1129: ElligatorSwift + integrated x-only DH 0702ecb061 Merge bitcoin-core/secp256k1#1338: Drop no longer needed `#include "../include/secp256k1.h"` 90e360acc2 Add doc/ellswift.md with ElligatorSwift explanation 4f091847c2 Add ellswift testing to CI 1bcea8c57f Add benchmarks for ellswift module 2d1d41acf8 Add ctime tests for ellswift module df633cdeba Add _prefix and _bip324 ellswift_xdh hash functions 9695deb351 Add tests for ellswift module c47917bbd6 Add ellswift module implementing ElligatorSwift 79e5b2a8b8 Add functions to test if X coordinate is valid a597a5a9ce Add benchmark for key generation 30574f22ea Merge bitcoin-core/secp256k1#1349: Normalize ge produced from secp256k1_pubkey_load 45c5ca7675 Merge bitcoin-core/secp256k1#1350: scalar: introduce and use `secp256k1_{read,write}_be64` helpers f1652528be Normalize ge produced from secp256k1_pubkey_load 7067ee54b4 tests: add tests for `secp256k1_{read,write}_be64` 740528caad scalar: use newly introduced `secp256k1_{read,write}_be64` helpers (4x64 impl.) 67214f5f7d Merge bitcoin-core/secp256k1#1339: scalar: refactor: use `secp256k1_{read,write}_be32` helpers cb1a59275c Merge bitcoin-core/secp256k1#1341: docs: correct `pubkey` param descriptions for `secp256k1_keypair_{xonly_,}pub` f3644287b1 docs: correct `pubkey` param descriptions for `secp256k1_keypair_{xonly_,}pub` 887183e7de scalar: use `secp256k1_{read,write}_be32` helpers (4x64 impl.) 52b84238de scalar: use `secp256k1_{read,write}_be32` helpers (8x32 impl.) e449af6872 Drop no longer needed `#include "../include/secp256k1.h"` 60556c9f49 Merge bitcoin-core/secp256k1#1337: ci: Fix error D8037 in `cl.exe` (attempt 2) db29bf220c ci: Remove quirk that runs dummy command after wineserver c7db4942b3 ci: Fix error D8037 in `cl.exe` 7dae115861 Revert "ci: Move wine prefix to /tmp to avoid error D8037 in cl.exe" bf29f8d0a6 Merge bitcoin-core/secp256k1#1334: fix input range comment for `secp256k1_fe_add_int` 605e07e365 fix input range comment for `secp256k1_fe_add_int` debf3e5c08 Merge bitcoin-core/secp256k1#1330: refactor: take use of `secp256k1_scalar_{zero,one}` constants d75dc59b58 Merge bitcoin-core/secp256k1#1333: test: Warn if both `VERIFY` and `COVERAGE` are defined ade5b36701 tests: add checks for scalar constants `secp256k1_scalar_{zero,one}` e83801f5db test: Warn if both `VERIFY` and `COVERAGE` are defined 654246c635 refactor: take use of `secp256k1_scalar_{zero,one}` constants 908e02d596 Merge bitcoin-core/secp256k1#1328: build: Bump MSVC warning level up to W3 1549db0ca5 build: Level up MSVC warnings 20a5da5fb1 Merge bitcoin-core/secp256k1#1310: Refine release process ad84603297 release process: clarify change log updates 6348bc7eee release process: fix process for maintenance release 79fa50b082 release process: mention targeted release schedule 165206789b release process: add sanity checks 09df0bfb23 Merge bitcoin-core/secp256k1#1327: ci: Move wine prefix to /tmp to avoid error D8037 in cl.exe 27504d5c94 ci: Move wine prefix to /tmp to avoid error D8037 in cl.exe d373a7215b Merge bitcoin-core/secp256k1#1316: Do not invoke fe_is_zero on failed set_b32_limit 6433175ffe Do not invoke fe_is_zero on failed set_b32_limit 5f7903c73c Merge bitcoin-core/secp256k1#1318: build: Enable -DVERIFY for precomputation binaries e9e4526a4e Merge bitcoin-core/secp256k1#1317: Make fe_cmov take max of magnitudes 5768b50229 build: Enable -DVERIFY for precomputation binaries 31b4bbee1e Make fe_cmov take max of magnitudes 83186db34a Merge bitcoin-core/secp256k1#1314: release cleanup: bump version after 0.3.2 95448ef2f8 release cleanup: bump version after 0.3.2 acf5c55ae6 Merge bitcoin-core/secp256k1#1312: release: Prepare for 0.3.2 d490ca2046 release: Prepare for 0.3.2 3e3d125b83 Merge bitcoin-core/secp256k1#1309: changelog: Catch up e8295d07ab Merge bitcoin-core/secp256k1#1311: Revert "Remove unused scratch space from API" 697e1ccf4a changelog: Catch up 3ad1027a40 Revert "Remove unused scratch space from API" 76b43f3443 changelog: Add entry for #1303 7d4f86d242 Merge bitcoin-core/secp256k1#1307: Mark more assembly outputs as early clobber b54a0672ef Merge bitcoin-core/secp256k1#1304: build: Rename arm to arm32 and check if it's really supported c6bb29b303 build: Rename `64bit` to `x86_64` 8c9ae37a5a Add release note 03246457a8 autotools: Add `SECP_ARM32_ASM_CHECK` macro ed4ba238e2 cmake: Add `check_arm32_assembly` function 350b4bd6e6 Mark stack variables as early clobber for technical correctness 0c729ba70d Bugfix: mark outputs as early clobber in scalar x86_64 asm 3353d3c753 Merge bitcoin-core/secp256k1#1207: Split fe_set_b32 into reducing and normalizing variants 5b32602295 Split fe_set_b32 into reducing and normalizing variants 006ddc1f42 Merge bitcoin-core/secp256k1#1306: build: Make tests work with external default callbacks 1907f0f166 build: Make tests work with external default callbacks fb3a806365 Merge bitcoin-core/secp256k1#1133: schnorrsig: Add test vectors for variable-length messages cd54ac7c1c schnorrsig: Improve docs of schnorrsig_sign_custom 28687b0312 schnorrsig: Add BIP340 varlen test vectors 97a98bed1e schnorrsig: Refactor test vector code to allow varlen messages ab5a917128 Merge bitcoin-core/secp256k1#1303: ct: Use more volatile 9eb6934f69 Merge bitcoin-core/secp256k1#1305: Remove unused scratch space from API 073d98a076 Merge bitcoin-core/secp256k1#1292: refactor: Make 64-bit shift explicit 17fa21733a ct: Be cautious and use volatile trick in more "conditional" paths 5fb336f9ce ct: Use volatile trick in scalar_cond_negate 712e7f8722 Remove unused scratch space from API 54d34b6c24 Merge bitcoin-core/secp256k1#1300: Avoid normalize conditional on VERIFY c63ec88ebf Merge bitcoin-core/secp256k1#1066: Abstract out and merge all the magnitude/normalized logic 7fc642fa25 Simplify secp256k1_fe_{impl_,}verify 4e176ad5b9 Abstract out verify logic for fe_is_square_var 4371f98346 Abstract out verify logic for fe_add_int 89e324c6b9 Abstract out verify logic for fe_half 283cd80ab4 Abstract out verify logic for fe_get_bounds d5aa2f0358 Abstract out verify logic for fe_inv{,_var} 3167646072 Abstract out verify logic for fe_from_storage 76d31e5047 Abstract out verify logic for fe_to_storage 1e6894bdd7 Abstract out verify logic for fe_cmov be82bd8e03 Improve comments/checks for fe_sqrt 6ab35082ef Abstract out verify logic for fe_sqr 4c25f6efbd Abstract out verify logic for fe_mul e179e651cb Abstract out verify logic for fe_add 7e7ad7ff57 Abstract out verify logic for fe_mul_int 65d82a3445 Abstract out verify logic for fe_negate 144670893e Abstract out verify logic for fe_get_b32 f7a7666aeb Abstract out verify logic for fe_set_b32 ce4d2093e8 Abstract out verify logic for fe_cmp_var 7d7d43c6dd Improve comments/check for fe_equal{,_var} c5e788d672 Abstract out verify logic for fe_is_odd d3f3fe8616 Abstract out verify logic for fe_is_zero c701d9a471 Abstract out verify logic for fe_clear 19a2bfeeea Abstract out verify logic for fe_set_int 864f9db491 Abstract out verify logic for fe_normalizes_to_zero{,_var} 6c31371120 Abstract out verify logic for fe_normalize_var e28b51f522 Abstract out verify logic for fe_normalize_weak b6b6f9cb97 Abstract out verify logic for fe_normalize 7fa5195559 Bugfix: correct SECP256K1_FE_CONST mag/norm fields e5cf4bf3ff build: Rename `arm` to `arm32` b29566c51b Merge magnitude/normalized fields, move/improve comments 97c63b9039 Avoid normalize conditional on VERIFY 341cc19726 Merge bitcoin-core/secp256k1#1299: Infinity handling: ecmult_const(infinity) works, and group verification bbc834467c Avoid secp256k1_ge_set_gej_zinv with uninitialized z 0a2e0b2ae4 Make secp256k1_{fe,ge,gej}_verify work as no-op if non-VERIFY f20266722a Add invariant checking to group elements a18821d5b1 Always initialize output coordinates in secp256k1_ge_set_gej 3086cb90ac Expose secp256k1_fe_verify to other modules a0e696fd4d Make secp256k1_ecmult_const handle infinity 24c768ae09 Merge bitcoin-core/secp256k1#1301: Avoid using bench_verify_data as bench_sign_data; merge them 2e65f1fdbc Avoid using bench_verify_data as bench_sign_data; merge them 1cf15ebd94 Merge bitcoin-core/secp256k1#1296: docs: complete interface description for `secp256k1_schnorrsig_sign_custom` 149c41cee1 docs: complete interface description for `secp256k1_schnorrsig_sign_custom` f30c74866b Merge bitcoin-core/secp256k1#1270: cmake: Fix library ABI versioning d1e48e5474 refactor: Make 64-bit shift explicit b2e29e43d0 ci: Treat all compiler warnings as errors in "Windows (VS 2022)" task 3c81838856 Merge bitcoin-core/secp256k1#1289: cmake: Use full signature of `add_test()` command 755629bc03 cmake: Use full signature of `add_test()` command bef448f9af cmake: Fix library ABI versioning 4b0f711d46 Merge bitcoin-core/secp256k1#1277: autotools: Clean up after adding Wycheproof 222ecaf661 Merge bitcoin-core/secp256k1#1284: cmake: Some improvements using `PROJECT_IS_TOP_LEVEL` variable 71f746c057 cmake: Include `include` directory for subtree builds 024a409484 Merge bitcoin-core/secp256k1#1240: cmake: Improve and document compiler flag checks a8d059f76c cmake, doc: Document compiler flags 6ece1507cb cmake, refactor: Rename `try_add_compile_option` to `try_append_cflags` 19516ed3e9 cmake: Use `add_compile_options()` in `try_add_compile_option()` 4b84f4bf0f Merge bitcoin-core/secp256k1#1239: cmake: Bugfix and other improvements after bumping CMake up to 3.13 596b336ff6 Merge bitcoin-core/secp256k1#1234: cmake: Add dev-mode 6b7e5b717d Merge bitcoin-core/secp256k1#1275: build: Fix C4005 "macro redefinition" MSVC warnings in examples 1c89536718 Merge bitcoin-core/secp256k1#1286: tests: remove extra semicolon in macro c4062d6b5d debug: move helper for printing buffers into util.h 7e977b3c50 autotools: Take VPATH builds into account when generating testvectors 2418d3260a autotools: Create src/wycheproof dir before creating file in it 8764034ed5 autotools: Make all "pregenerated" targets .PHONY e1b9ce8811 autotools: Use same conventions for all pregenerated files 3858bad2c6 tests: remove extra semicolon in macro 1f33bb2b1c Merge bitcoin-core/secp256k1#1205: field: Improve docs +tests of secp256k1_fe_set_b32 162da73e9a tests: Add debug helper for printing buffers e9fd3dff76 field: Improve docs and tests of secp256k1_fe_set_b32 f6bef03c0a Merge bitcoin-core/secp256k1#1283: Get rid of secp256k1_fe_const_b 5431b9decd cmake: Make `SECP256K1_INSTALL` default depend on `PROJECT_IS_TOP_LEVEL` 5ec1333d4f Merge bitcoin-core/secp256k1#1285: bench: Make sys/time.h a system include 68b16a1662 bench: Make sys/time.h a system include 162608cc98 cmake: Emulate `PROJECT_IS_TOP_LEVEL` for CMake<3.21 69e1ec0331 Get rid of secp256k1_fe_const_b ce5ba9e24d gitignore: Add CMakeUserPresets.json 0a446a312f cmake: Add dev-mode CMake preset a6f4bcf6e1 Merge bitcoin-core/secp256k1#1231: Move `SECP256K1_INLINE` macro definition out from `include/secp256k1.h` a273d74b2e cmake: Improve version comparison 6a58b483ef cmake: Use `if(... IN_LIST ...)` command 2445808c02 cmake: Use dedicated `GENERATOR_IS_MULTI_CONFIG` property 9f8703ef17 cmake: Use dedicated `CMAKE_HOST_APPLE` variable 8c2017035a cmake: Use recommended `add_compile_definitions` command 04d4cc071a cmake: Add `DESCRIPTION` and `HOMEPAGE_URL` options to `project` command 8a8b6536ef cmake: Use `SameMinorVersion` compatibility mode 5b0444a3b5 Merge bitcoin-core/secp256k1#1263: cmake: Make installation optional 47ac3d63cd cmake: Make installation optional 2e035af251 Merge bitcoin-core/secp256k1#1273: build: Make `SECP_VALGRIND_CHECK` preserve `CPPFLAGS` 5be353d658 Merge bitcoin-core/secp256k1#1279: tests: lint wycheproof's python script 08f4b1632d autotools: Move code around to tidy Makefile 04bf3f6778 Merge bitcoin-core/secp256k1#1230: Build: allow static or shared but not both 9ce9984f32 Merge bitcoin-core/secp256k1#1265: Remove bits argument from secp256k1_wnaf_const{_xonly} 566faa17d3 Merge bitcoin-core/secp256k1#1267: doc: clarify process for patch releases ef49a11d29 build: allow static or shared but not both 35ada3b954 tests: lint wycheproof's python script 529b54d922 autotools: Move Wycheproof header from EXTRA_DIST to noinst_HEADERS dc0657c762 build: Fix C4005 "macro redefinition" MSVC warnings in examples 1ecb94ebe9 build: Make `SECP_VALGRIND_CHECK` preserve `CPPFLAGS` 1b6fb5593c doc: clarify process for patch releases a575339c02 Remove bits argument from secp256k1_wnaf_const (always 256) 36b0adf1b9 build: remove warning until it's reproducible 8e142ca410 Move `SECP256K1_INLINE` macro definition out from `include/secp256k1.h` 77445898a5 Remove `SECP256K1_INLINE` usage from examples ca92a35d01 field: Simplify code in secp256k1_fe_set_b32 d93f62e369 field: Verify field element even after secp256k1_fe_set_b32 fails git-subtree-dir: src/secp256k1 git-subtree-split: 705ce7ed8c1557a31e1bfc99be06082c5098d9f5
483 lines
27 KiB
Markdown
483 lines
27 KiB
Markdown
# ElligatorSwift for secp256k1 explained
|
||
|
||
In this document we explain how the `ellswift` module implementation is related to the
|
||
construction in the
|
||
["SwiftEC: Shallue–van de Woestijne Indifferentiable Function To Elliptic Curves"](https://eprint.iacr.org/2022/759)
|
||
paper by Jorge Chávez-Saab, Francisco Rodríguez-Henríquez, and Mehdi Tibouchi.
|
||
|
||
* [1. Introduction](#1-introduction)
|
||
* [2. The decoding function](#2-the-decoding-function)
|
||
+ [2.1 Decoding for `secp256k1`](#21-decoding-for-secp256k1)
|
||
* [3. The encoding function](#3-the-encoding-function)
|
||
+ [3.1 Switching to *v, w* coordinates](#31-switching-to-v-w-coordinates)
|
||
+ [3.2 Avoiding computing all inverses](#32-avoiding-computing-all-inverses)
|
||
+ [3.3 Finding the inverse](#33-finding-the-inverse)
|
||
+ [3.4 Dealing with special cases](#34-dealing-with-special-cases)
|
||
+ [3.5 Encoding for `secp256k1`](#35-encoding-for-secp256k1)
|
||
* [4. Encoding and decoding full *(x, y)* coordinates](#4-encoding-and-decoding-full-x-y-coordinates)
|
||
+ [4.1 Full *(x, y)* coordinates for `secp256k1`](#41-full-x-y-coordinates-for-secp256k1)
|
||
|
||
## 1. Introduction
|
||
|
||
The `ellswift` module effectively introduces a new 64-byte public key format, with the property
|
||
that (uniformly random) public keys can be encoded as 64-byte arrays which are computationally
|
||
indistinguishable from uniform byte arrays. The module provides functions to convert public keys
|
||
from and to this format, as well as convenience functions for key generation and ECDH that operate
|
||
directly on ellswift-encoded keys.
|
||
|
||
The encoding consists of the concatenation of two (32-byte big endian) encoded field elements $u$
|
||
and $t.$ Together they encode an x-coordinate on the curve $x$, or (see further) a full point $(x, y)$ on
|
||
the curve.
|
||
|
||
**Decoding** consists of decoding the field elements $u$ and $t$ (values above the field size $p$
|
||
are taken modulo $p$), and then evaluating $F_u(t)$, which for every $u$ and $t$ results in a valid
|
||
x-coordinate on the curve. The functions $F_u$ will be defined in [Section 2](#2-the-decoding-function).
|
||
|
||
**Encoding** a given $x$ coordinate is conceptually done as follows:
|
||
* Loop:
|
||
* Pick a uniformly random field element $u.$
|
||
* Compute the set $L = F_u^{-1}(x)$ of $t$ values for which $F_u(t) = x$, which may have up to *8* elements.
|
||
* With probability $1 - \dfrac{\\#L}{8}$, restart the loop.
|
||
* Select a uniformly random $t \in L$ and return $(u, t).$
|
||
|
||
This is the *ElligatorSwift* algorithm, here given for just x-coordinates. An extension to full
|
||
$(x, y)$ points will be given in [Section 4](#4-encoding-and-decoding-full-x-y-coordinates).
|
||
The algorithm finds a uniformly random $(u, t)$ among (almost all) those
|
||
for which $F_u(t) = x.$ Section 3.2 in the paper proves that the number of such encodings for
|
||
almost all x-coordinates on the curve (all but at most 39) is close to two times the field size
|
||
(specifically, it lies in the range $2q \pm (22\sqrt{q} + O(1))$, where $q$ is the size of the field).
|
||
|
||
## 2. The decoding function
|
||
|
||
First some definitions:
|
||
* $\mathbb{F}$ is the finite field of size $q$, of characteristic 5 or more, and $q \equiv 1 \mod 3.$
|
||
* For `secp256k1`, $q = 2^{256} - 2^{32} - 977$, which satisfies that requirement.
|
||
* Let $E$ be the elliptic curve of points $(x, y) \in \mathbb{F}^2$ for which $y^2 = x^3 + ax + b$, with $a$ and $b$
|
||
public constants, for which $\Delta_E = -16(4a^3 + 27b^2)$ is a square, and at least one of $(-b \pm \sqrt{-3 \Delta_E} / 36)/2$ is a square.
|
||
This implies that the order of $E$ is either odd, or a multiple of *4*.
|
||
If $a=0$, this condition is always fulfilled.
|
||
* For `secp256k1`, $a=0$ and $b=7.$
|
||
* Let the function $g(x) = x^3 + ax + b$, so the $E$ curve equation is also $y^2 = g(x).$
|
||
* Let the function $h(x) = 3x^3 + 4a.$
|
||
* Define $V$ as the set of solutions $(x_1, x_2, x_3, z)$ to $z^2 = g(x_1)g(x_2)g(x_3).$
|
||
* Define $S_u$ as the set of solutions $(X, Y)$ to $X^2 + h(u)Y^2 = -g(u)$ and $Y \neq 0.$
|
||
* $P_u$ is a function from $\mathbb{F}$ to $S_u$ that will be defined below.
|
||
* $\psi_u$ is a function from $S_u$ to $V$ that will be defined below.
|
||
|
||
**Note**: In the paper:
|
||
* $F_u$ corresponds to $F_{0,u}$ there.
|
||
* $P_u(t)$ is called $P$ there.
|
||
* All $S_u$ sets together correspond to $S$ there.
|
||
* All $\psi_u$ functions together (operating on elements of $S$) correspond to $\psi$ there.
|
||
|
||
Note that for $V$, the left hand side of the equation $z^2$ is square, and thus the right
|
||
hand must also be square. As multiplying non-squares results in a square in $\mathbb{F}$,
|
||
out of the three right-hand side factors an even number must be non-squares.
|
||
This implies that exactly *1* or exactly *3* out of
|
||
$\\{g(x_1), g(x_2), g(x_3)\\}$ must be square, and thus that for any $(x_1,x_2,x_3,z) \in V$,
|
||
at least one of $\\{x_1, x_2, x_3\\}$ must be a valid x-coordinate on $E.$ There is one exception
|
||
to this, namely when $z=0$, but even then one of the three values is a valid x-coordinate.
|
||
|
||
**Define** the decoding function $F_u(t)$ as:
|
||
* Let $(x_1, x_2, x_3, z) = \psi_u(P_u(t)).$
|
||
* Return the first element $x$ of $(x_3, x_2, x_1)$ which is a valid x-coordinate on $E$ (i.e., $g(x)$ is square).
|
||
|
||
$P_u(t) = (X(u, t), Y(u, t))$, where:
|
||
|
||
$$
|
||
\begin{array}{lcl}
|
||
X(u, t) & = & \left\\{\begin{array}{ll}
|
||
\dfrac{g(u) - t^2}{2t} & a = 0 \\
|
||
\dfrac{g(u) + h(u)(Y_0(u) + X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0
|
||
\end{array}\right. \\
|
||
Y(u, t) & = & \left\\{\begin{array}{ll}
|
||
\dfrac{X(u, t) + t}{u \sqrt{-3}} = \dfrac{g(u) + t^2}{2tu\sqrt{-3}} & a = 0 \\
|
||
Y_0(u) + t(X(u, t) - X_0(u)) & a \neq 0
|
||
\end{array}\right.
|
||
\end{array}
|
||
$$
|
||
|
||
$P_u(t)$ is defined:
|
||
* For $a=0$, unless:
|
||
* $u = 0$ or $t = 0$ (division by zero)
|
||
* $g(u) = -t^2$ (would give $Y=0$).
|
||
* For $a \neq 0$, unless:
|
||
* $X_0(u) = 0$ or $h(u)t^2 = -1$ (division by zero)
|
||
* $Y_0(u) (1 - h(u)t^2) = 2X_0(u)t$ (would give $Y=0$).
|
||
|
||
The functions $X_0(u)$ and $Y_0(u)$ are defined in Appendix A of the paper, and depend on various properties of $E.$
|
||
|
||
The function $\psi_u$ is the same for all curves: $\psi_u(X, Y) = (x_1, x_2, x_3, z)$, where:
|
||
|
||
$$
|
||
\begin{array}{lcl}
|
||
x_1 & = & \dfrac{X}{2Y} - \dfrac{u}{2} && \\
|
||
x_2 & = & -\dfrac{X}{2Y} - \dfrac{u}{2} && \\
|
||
x_3 & = & u + 4Y^2 && \\
|
||
z & = & \dfrac{g(x_3)}{2Y}(u^2 + ux_1 + x_1^2 + a) = \dfrac{-g(u)g(x_3)}{8Y^3}
|
||
\end{array}
|
||
$$
|
||
|
||
### 2.1 Decoding for `secp256k1`
|
||
|
||
Put together and specialized for $a=0$ curves, decoding $(u, t)$ to an x-coordinate is:
|
||
|
||
**Define** $F_u(t)$ as:
|
||
* Let $X = \dfrac{u^3 + b - t^2}{2t}.$
|
||
* Let $Y = \dfrac{X + t}{u\sqrt{-3}}.$
|
||
* Return the first $x$ in $(u + 4Y^2, \dfrac{-X}{2Y} - \dfrac{u}{2}, \dfrac{X}{2Y} - \dfrac{u}{2})$ for which $g(x)$ is square.
|
||
|
||
To make sure that every input decodes to a valid x-coordinate, we remap the inputs in case
|
||
$P_u$ is not defined (when $u=0$, $t=0$, or $g(u) = -t^2$):
|
||
|
||
**Define** $F_u(t)$ as:
|
||
* Let $u'=u$ if $u \neq 0$; $1$ otherwise (guaranteeing $u' \neq 0$).
|
||
* Let $t'=t$ if $t \neq 0$; $1$ otherwise (guaranteeing $t' \neq 0$).
|
||
* Let $t''=t'$ if $g(u') \neq -t'^2$; $2t'$ otherwise (guaranteeing $t'' \neq 0$ and $g(u') \neq -t''^2$).
|
||
* Let $X = \dfrac{u'^3 + b - t''^2}{2t''}.$
|
||
* Let $Y = \dfrac{X + t''}{u'\sqrt{-3}}.$
|
||
* Return the first $x$ in $(u' + 4Y^2, \dfrac{-X}{2Y} - \dfrac{u'}{2}, \dfrac{X}{2Y} - \dfrac{u'}{2})$ for which $x^3 + b$ is square.
|
||
|
||
The choices here are not strictly necessary. Just returning a fixed constant in any of the undefined cases would suffice,
|
||
but the approach here is simple enough and gives fairly uniform output even in these cases.
|
||
|
||
**Note**: in the paper these conditions result in $\infty$ as output, due to the use of projective coordinates there.
|
||
We wish to avoid the need for callers to deal with this special case.
|
||
|
||
This is implemented in `secp256k1_ellswift_xswiftec_frac_var` (which decodes to an x-coordinate represented as a fraction), and
|
||
in `secp256k1_ellswift_xswiftec_var` (which outputs the actual x-coordinate).
|
||
|
||
## 3. The encoding function
|
||
|
||
To implement $F_u^{-1}(x)$, the function to find the set of inverses $t$ for which $F_u(t) = x$, we have to reverse the process:
|
||
* Find all the $(X, Y) \in S_u$ that could have given rise to $x$, through the $x_1$, $x_2$, or $x_3$ formulas in $\psi_u.$
|
||
* Map those $(X, Y)$ solutions to $t$ values using $P_u^{-1}(X, Y).$
|
||
* For each of the found $t$ values, verify that $F_u(t) = x.$
|
||
* Return the remaining $t$ values.
|
||
|
||
The function $P_u^{-1}$, which finds $t$ given $(X, Y) \in S_u$, is significantly simpler than $P_u:$
|
||
|
||
$$
|
||
P_u^{-1}(X, Y) = \left\\{\begin{array}{ll}
|
||
Yu\sqrt{-3} - X & a = 0 \\
|
||
\dfrac{Y-Y_0(u)}{X-X_0(u)} & a \neq 0 \land X \neq X_0(u) \\
|
||
\dfrac{-X_0(u)}{h(u)Y_0(u)} & a \neq 0 \land X = X_0(u) \land Y = Y_0(u)
|
||
\end{array}\right.
|
||
$$
|
||
|
||
The third step above, verifying that $F_u(t) = x$, is necessary because for the $(X, Y)$ values found through the $x_1$ and $x_2$ expressions,
|
||
it is possible that decoding through $\psi_u(X, Y)$ yields a valid $x_3$ on the curve, which would take precedence over the
|
||
$x_1$ or $x_2$ decoding. These $(X, Y)$ solutions must be rejected.
|
||
|
||
Since we know that exactly one or exactly three out of $\\{x_1, x_2, x_3\\}$ are valid x-coordinates for any $t$,
|
||
the case where either $x_1$ or $x_2$ is valid and in addition also $x_3$ is valid must mean that all three are valid.
|
||
This means that instead of checking whether $x_3$ is on the curve, it is also possible to check whether the other one out of
|
||
$x_1$ and $x_2$ is on the curve. This is significantly simpler, as it turns out.
|
||
|
||
Observe that $\psi_u$ guarantees that $x_1 + x_2 = -u.$ So given either $x = x_1$ or $x = x_2$, the other one of the two can be computed as
|
||
$-u - x.$ Thus, when encoding $x$ through the $x_1$ or $x_2$ expressions, one can simply check whether $g(-u-x)$ is a square,
|
||
and if so, not include the corresponding $t$ values in the returned set. As this does not need $X$, $Y$, or $t$, this condition can be determined
|
||
before those values are computed.
|
||
|
||
It is not possible that an encoding found through the $x_1$ expression decodes to a different valid x-coordinate using $x_2$ (which would
|
||
take precedence), for the same reason: if both $x_1$ and $x_2$ decodings were valid, $x_3$ would be valid as well, and thus take
|
||
precedence over both. Because of this, the $g(-u-x)$ being square test for $x_1$ and $x_2$ is the only test necessary to guarantee the found $t$
|
||
values round-trip back to the input $x$ correctly. This is the reason for choosing the $(x_3, x_2, x_1)$ precedence order in the decoder;
|
||
any order which does not place $x_3$ first requires more complicated round-trip checks in the encoder.
|
||
|
||
### 3.1 Switching to *v, w* coordinates
|
||
|
||
Before working out the formulas for all this, we switch to different variables for $S_u.$ Let $v = (X/Y - u)/2$, and
|
||
$w = 2Y.$ Or in the other direction, $X = w(u/2 + v)$ and $Y = w/2:$
|
||
* $S_u'$ becomes the set of $(v, w)$ for which $w^2 (u^2 + uv + v^2 + a) = -g(u)$ and $w \neq 0.$
|
||
* For $a=0$ curves, $P_u^{-1}$ can be stated for $(v,w)$ as $P_u^{'-1}(v, w) = w\left(\frac{\sqrt{-3}-1}{2}u - v\right).$
|
||
* $\psi_u$ can be stated for $(v, w)$ as $\psi_u'(v, w) = (x_1, x_2, x_3, z)$, where
|
||
|
||
$$
|
||
\begin{array}{lcl}
|
||
x_1 & = & v \\
|
||
x_2 & = & -u - v \\
|
||
x_3 & = & u + w^2 \\
|
||
z & = & \dfrac{g(x_3)}{w}(u^2 + uv + v^2 + a) = \dfrac{-g(u)g(x_3)}{w^3}
|
||
\end{array}
|
||
$$
|
||
|
||
We can now write the expressions for finding $(v, w)$ given $x$ explicitly, by solving each of the $\\{x_1, x_2, x_3\\}$
|
||
expressions for $v$ or $w$, and using the $S_u'$ equation to find the other variable:
|
||
* Assuming $x = x_1$, we find $v = x$ and $w = \pm\sqrt{-g(u)/(u^2 + uv + v^2 + a)}$ (two solutions).
|
||
* Assuming $x = x_2$, we find $v = -u-x$ and $w = \pm\sqrt{-g(u)/(u^2 + uv + v^2 + a)}$ (two solutions).
|
||
* Assuming $x = x_3$, we find $w = \pm\sqrt{x-u}$ and $v = -u/2 \pm \sqrt{-w^2(4g(u) + w^2h(u))}/(2w^2)$ (four solutions).
|
||
|
||
### 3.2 Avoiding computing all inverses
|
||
|
||
The *ElligatorSwift* algorithm as stated in Section 1 requires the computation of $L = F_u^{-1}(x)$ (the
|
||
set of all $t$ such that $(u, t)$ decode to $x$) in full. This is unnecessary.
|
||
|
||
Observe that the procedure of restarting with probability $(1 - \frac{\\#L}{8})$ and otherwise returning a
|
||
uniformly random element from $L$ is actually equivalent to always padding $L$ with $\bot$ values up to length 8,
|
||
picking a uniformly random element from that, restarting whenever $\bot$ is picked:
|
||
|
||
**Define** *ElligatorSwift(x)* as:
|
||
* Loop:
|
||
* Pick a uniformly random field element $u.$
|
||
* Compute the set $L = F_u^{-1}(x).$
|
||
* Let $T$ be the 8-element vector consisting of the elements of $L$, plus $8 - \\#L$ times $\\{\bot\\}.$
|
||
* Select a uniformly random $t \in T.$
|
||
* If $t \neq \bot$, return $(u, t)$; restart loop otherwise.
|
||
|
||
Now notice that the order of elements in $T$ does not matter, as all we do is pick a uniformly
|
||
random element in it, so we do not need to have all $\bot$ values at the end.
|
||
As we have 8 distinct formulas for finding $(v, w)$ (taking the variants due to $\pm$ into account),
|
||
we can associate every index in $T$ with exactly one of those formulas, making sure that:
|
||
* Formulas that yield no solutions (due to division by zero or non-existing square roots) or invalid solutions are made to return $\bot.$
|
||
* For the $x_1$ and $x_2$ cases, if $g(-u-x)$ is a square, $\bot$ is returned instead (the round-trip check).
|
||
* In case multiple formulas would return the same non- $\bot$ result, all but one of those must be turned into $\bot$ to avoid biasing those.
|
||
|
||
The last condition above only occurs with negligible probability for cryptographically-sized curves, but is interesting
|
||
to take into account as it allows exhaustive testing in small groups. See [Section 3.4](#34-dealing-with-special-cases)
|
||
for an analysis of all the negligible cases.
|
||
|
||
If we define $T = (G_{0,u}(x), G_{1,u}(x), \ldots, G_{7,u}(x))$, with each $G_{i,u}$ matching one of the formulas,
|
||
the loop can be simplified to only compute one of the inverses instead of all of them:
|
||
|
||
**Define** *ElligatorSwift(x)* as:
|
||
* Loop:
|
||
* Pick a uniformly random field element $u.$
|
||
* Pick a uniformly random integer $c$ in $[0,8).$
|
||
* Let $t = G_{c,u}(x).$
|
||
* If $t \neq \bot$, return $(u, t)$; restart loop otherwise.
|
||
|
||
This is implemented in `secp256k1_ellswift_xelligatorswift_var`.
|
||
|
||
### 3.3 Finding the inverse
|
||
|
||
To implement $G_{c,u}$, we map $c=0$ to the $x_1$ formula, $c=1$ to the $x_2$ formula, and $c=2$ and $c=3$ to the $x_3$ formula.
|
||
Those are then repeated as $c=4$ through $c=7$ for the other sign of $w$ (noting that in each formula, $w$ is a square root of some expression).
|
||
Ignoring the negligible cases, we get:
|
||
|
||
**Define** $G_{c,u}(x)$ as:
|
||
* If $c \in \\{0, 1, 4, 5\\}$ (for $x_1$ and $x_2$ formulas):
|
||
* If $g(-u-x)$ is square, return $\bot$ (as $x_3$ would be valid and take precedence).
|
||
* If $c \in \\{0, 4\\}$ (the $x_1$ formula) let $v = x$, otherwise let $v = -u-x$ (the $x_2$ formula)
|
||
* Let $s = -g(u)/(u^2 + uv + v^2 + a)$ (using $s = w^2$ in what follows).
|
||
* Otherwise, when $c \in \\{2, 3, 6, 7\\}$ (for $x_3$ formulas):
|
||
* Let $s = x-u.$
|
||
* Let $r = \sqrt{-s(4g(u) + sh(u))}.$
|
||
* Let $v = (r/s - u)/2$ if $c \in \\{3, 7\\}$; $(-r/s - u)/2$ otherwise.
|
||
* Let $w = \sqrt{s}.$
|
||
* Depending on $c:$
|
||
* If $c \in \\{0, 1, 2, 3\\}:$ return $P_u^{'-1}(v, w).$
|
||
* If $c \in \\{4, 5, 6, 7\\}:$ return $P_u^{'-1}(v, -w).$
|
||
|
||
Whenever a square root of a non-square is taken, $\bot$ is returned; for both square roots this happens with roughly
|
||
50% on random inputs. Similarly, when a division by 0 would occur, $\bot$ is returned as well; this will only happen
|
||
with negligible probability. A division by 0 in the first branch in fact cannot occur at all, because $u^2 + uv + v^2 + a = 0$
|
||
implies $g(-u-x) = g(x)$ which would mean the $g(-u-x)$ is square condition has triggered
|
||
and $\bot$ would have been returned already.
|
||
|
||
**Note**: In the paper, the $case$ variable corresponds roughly to the $c$ above, but only takes on 4 possible values (1 to 4).
|
||
The conditional negation of $w$ at the end is done randomly, which is equivalent, but makes testing harder. We choose to
|
||
have the $G_{c,u}$ be deterministic, and capture all choices in $c.$
|
||
|
||
Now observe that the $c \in \\{1, 5\\}$ and $c \in \\{3, 7\\}$ conditions effectively perform the same $v \rightarrow -u-v$
|
||
transformation. Furthermore, that transformation has no effect on $s$ in the first branch
|
||
as $u^2 + ux + x^2 + a = u^2 + u(-u-x) + (-u-x)^2 + a.$ Thus we can extract it out and move it down:
|
||
|
||
**Define** $G_{c,u}(x)$ as:
|
||
* If $c \in \\{0, 1, 4, 5\\}:$
|
||
* If $g(-u-x)$ is square, return $\bot.$
|
||
* Let $s = -g(u)/(u^2 + ux + x^2 + a).$
|
||
* Let $v = x.$
|
||
* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$
|
||
* Let $s = x-u.$
|
||
* Let $r = \sqrt{-s(4g(u) + sh(u))}.$
|
||
* Let $v = (r/s - u)/2.$
|
||
* Let $w = \sqrt{s}.$
|
||
* Depending on $c:$
|
||
* If $c \in \\{0, 2\\}:$ return $P_u^{'-1}(v, w).$
|
||
* If $c \in \\{1, 3\\}:$ return $P_u^{'-1}(-u-v, w).$
|
||
* If $c \in \\{4, 6\\}:$ return $P_u^{'-1}(v, -w).$
|
||
* If $c \in \\{5, 7\\}:$ return $P_u^{'-1}(-u-v, -w).$
|
||
|
||
This shows there will always be exactly 0, 4, or 8 $t$ values for a given $(u, x)$ input.
|
||
There can be 0, 1, or 2 $(v, w)$ pairs before invoking $P_u^{'-1}$, and each results in 4 distinct $t$ values.
|
||
|
||
### 3.4 Dealing with special cases
|
||
|
||
As mentioned before there are a few cases to deal with which only happen in a negligibly small subset of inputs.
|
||
For cryptographically sized fields, if only random inputs are going to be considered, it is unnecessary to deal with these. Still, for completeness
|
||
we analyse them here. They generally fall into two categories: cases in which the encoder would produce $t$ values that
|
||
do not decode back to $x$ (or at least cannot guarantee that they do), and cases in which the encoder might produce the same
|
||
$t$ value for multiple $c$ inputs (thereby biasing that encoding):
|
||
|
||
* In the branch for $x_1$ and $x_2$ (where $c \in \\{0, 1, 4, 5\\}$):
|
||
* When $g(u) = 0$, we would have $s=w=Y=0$, which is not on $S_u.$ This is only possible on even-ordered curves.
|
||
Excluding this also removes the one condition under which the simplified check for $x_3$ on the curve
|
||
fails (namely when $g(x_1)=g(x_2)=0$ but $g(x_3)$ is not square).
|
||
This does exclude some valid encodings: when both $g(u)=0$ and $u^2+ux+x^2+a=0$ (also implying $g(x)=0$),
|
||
the $S_u'$ equation degenerates to $0 = 0$, and many valid $t$ values may exist. Yet, these cannot be targeted uniformly by the
|
||
encoder anyway as there will generally be more than 8.
|
||
* When $g(x) = 0$, the same $t$ would be produced as in the $x_3$ branch (where $c \in \\{2, 3, 6, 7\\}$) which we give precedence
|
||
as it can deal with $g(u)=0$.
|
||
This is again only possible on even-ordered curves.
|
||
* In the branch for $x_3$ (where $c \in \\{2, 3, 6, 7\\}$):
|
||
* When $s=0$, a division by zero would occur.
|
||
* When $v = -u-v$ and $c \in \\{3, 7\\}$, the same $t$ would be returned as in the $c \in \\{2, 6\\}$ cases.
|
||
It is equivalent to checking whether $r=0$.
|
||
This cannot occur in the $x_1$ or $x_2$ branches, as it would trigger the $g(-u-x)$ is square condition.
|
||
A similar concern for $w = -w$ does not exist, as $w=0$ is already impossible in both branches: in the first
|
||
it requires $g(u)=0$ which is already outlawed on even-ordered curves and impossible on others; in the second it would trigger division by zero.
|
||
* Curve-specific special cases also exist that need to be rejected, because they result in $(u,t)$ which is invalid to the decoder, or because of division by zero in the encoder:
|
||
* For $a=0$ curves, when $u=0$ or when $t=0$. The latter can only be reached by the encoder when $g(u)=0$, which requires an even-ordered curve.
|
||
* For $a \neq 0$ curves, when $X_0(u)=0$, when $h(u)t^2 = -1$, or when $2w(u + 2v) = 2X_0(u)$ while also either $w \neq 2Y_0(u)$ or $h(u)=0$.
|
||
|
||
**Define** a version of $G_{c,u}(x)$ which deals with all these cases:
|
||
* If $a=0$ and $u=0$, return $\bot.$
|
||
* If $a \neq 0$ and $X_0(u)=0$, return $\bot.$
|
||
* If $c \in \\{0, 1, 4, 5\\}:$
|
||
* If $g(u) = 0$ or $g(x) = 0$, return $\bot$ (even curves only).
|
||
* If $g(-u-x)$ is square, return $\bot.$
|
||
* Let $s = -g(u)/(u^2 + ux + x^2 + a)$ (cannot cause division by zero).
|
||
* Let $v = x.$
|
||
* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$
|
||
* Let $s = x-u.$
|
||
* Let $r = \sqrt{-s(4g(u) + sh(u))}$; return $\bot$ if not square.
|
||
* If $c \in \\{3, 7\\}$ and $r=0$, return $\bot.$
|
||
* If $s = 0$, return $\bot.$
|
||
* Let $v = (r/s - u)/2.$
|
||
* Let $w = \sqrt{s}$; return $\bot$ if not square.
|
||
* If $a \neq 0$ and $w(u+2v) = 2X_0(u)$ and either $w \neq 2Y_0(u)$ or $h(u) = 0$, return $\bot.$
|
||
* Depending on $c:$
|
||
* If $c \in \\{0, 2\\}$, let $t = P_u^{'-1}(v, w).$
|
||
* If $c \in \\{1, 3\\}$, let $t = P_u^{'-1}(-u-v, w).$
|
||
* If $c \in \\{4, 6\\}$, let $t = P_u^{'-1}(v, -w).$
|
||
* If $c \in \\{5, 7\\}$, let $t = P_u^{'-1}(-u-v, -w).$
|
||
* If $a=0$ and $t=0$, return $\bot$ (even curves only).
|
||
* If $a \neq 0$ and $h(u)t^2 = -1$, return $\bot.$
|
||
* Return $t.$
|
||
|
||
Given any $u$, using this algorithm over all $x$ and $c$ values, every $t$ value will be reached exactly once,
|
||
for an $x$ for which $F_u(t) = x$ holds, except for these cases that will not be reached:
|
||
* All cases where $P_u(t)$ is not defined:
|
||
* For $a=0$ curves, when $u=0$, $t=0$, or $g(u) = -t^2.$
|
||
* For $a \neq 0$ curves, when $h(u)t^2 = -1$, $X_0(u) = 0$, or $Y_0(u) (1 - h(u) t^2) = 2X_0(u)t.$
|
||
* When $g(u)=0$, the potentially many $t$ values that decode to an $x$ satisfying $g(x)=0$ using the $x_2$ formula. These were excluded by the $g(u)=0$ condition in the $c \in \\{0, 1, 4, 5\\}$ branch.
|
||
|
||
These cases form a negligible subset of all $(u, t)$ for cryptographically sized curves.
|
||
|
||
### 3.5 Encoding for `secp256k1`
|
||
|
||
Specialized for odd-ordered $a=0$ curves:
|
||
|
||
**Define** $G_{c,u}(x)$ as:
|
||
* If $u=0$, return $\bot.$
|
||
* If $c \in \\{0, 1, 4, 5\\}:$
|
||
* If $(-u-x)^3 + b$ is square, return $\bot$
|
||
* Let $s = -(u^3 + b)/(u^2 + ux + x^2)$ (cannot cause division by 0).
|
||
* Let $v = x.$
|
||
* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$
|
||
* Let $s = x-u.$
|
||
* Let $r = \sqrt{-s(4(u^3 + b) + 3su^2)}$; return $\bot$ if not square.
|
||
* If $c \in \\{3, 7\\}$ and $r=0$, return $\bot.$
|
||
* If $s = 0$, return $\bot.$
|
||
* Let $v = (r/s - u)/2.$
|
||
* Let $w = \sqrt{s}$; return $\bot$ if not square.
|
||
* Depending on $c:$
|
||
* If $c \in \\{0, 2\\}:$ return $w(\frac{\sqrt{-3}-1}{2}u - v).$
|
||
* If $c \in \\{1, 3\\}:$ return $w(\frac{\sqrt{-3}+1}{2}u + v).$
|
||
* If $c \in \\{4, 6\\}:$ return $w(\frac{-\sqrt{-3}+1}{2}u + v).$
|
||
* If $c \in \\{5, 7\\}:$ return $w(\frac{-\sqrt{-3}-1}{2}u - v).$
|
||
|
||
This is implemented in `secp256k1_ellswift_xswiftec_inv_var`.
|
||
|
||
And the x-only ElligatorSwift encoding algorithm is still:
|
||
|
||
**Define** *ElligatorSwift(x)* as:
|
||
* Loop:
|
||
* Pick a uniformly random field element $u.$
|
||
* Pick a uniformly random integer $c$ in $[0,8).$
|
||
* Let $t = G_{c,u}(x).$
|
||
* If $t \neq \bot$, return $(u, t)$; restart loop otherwise.
|
||
|
||
Note that this logic does not take the remapped $u=0$, $t=0$, and $g(u) = -t^2$ cases into account; it just avoids them.
|
||
While it is not impossible to make the encoder target them, this would increase the maximum number of $t$ values for a given $(u, x)$
|
||
combination beyond 8, and thereby slow down the ElligatorSwift loop proportionally, for a negligible gain in uniformity.
|
||
|
||
## 4. Encoding and decoding full *(x, y)* coordinates
|
||
|
||
So far we have only addressed encoding and decoding x-coordinates, but in some cases an encoding
|
||
for full points with $(x, y)$ coordinates is desirable. It is possible to encode this information
|
||
in $t$ as well.
|
||
|
||
Note that for any $(X, Y) \in S_u$, $(\pm X, \pm Y)$ are all on $S_u.$ Moreover, all of these are
|
||
mapped to the same x-coordinate. Negating $X$ or negating $Y$ just results in $x_1$ and $x_2$
|
||
being swapped, and does not affect $x_3.$ This will not change the outcome x-coordinate as the order
|
||
of $x_1$ and $x_2$ only matters if both were to be valid, and in that case $x_3$ would be used instead.
|
||
|
||
Still, these four $(X, Y)$ combinations all correspond to distinct $t$ values, so we can encode
|
||
the sign of the y-coordinate in the sign of $X$ or the sign of $Y.$ They correspond to the
|
||
four distinct $P_u^{'-1}$ calls in the definition of $G_{u,c}.$
|
||
|
||
**Note**: In the paper, the sign of the y coordinate is encoded in a separately-coded bit.
|
||
|
||
To encode the sign of $y$ in the sign of $Y:$
|
||
|
||
**Define** *Decode(u, t)* for full $(x, y)$ as:
|
||
* Let $(X, Y) = P_u(t).$
|
||
* Let $x$ be the first value in $(u + 4Y^2, \frac{-X}{2Y} - \frac{u}{2}, \frac{X}{2Y} - \frac{u}{2})$ for which $g(x)$ is square.
|
||
* Let $y = \sqrt{g(x)}.$
|
||
* If $sign(y) = sign(Y)$, return $(x, y)$; otherwise return $(x, -y).$
|
||
|
||
And encoding would be done using a $G_{c,u}(x, y)$ function defined as:
|
||
|
||
**Define** $G_{c,u}(x, y)$ as:
|
||
* If $c \in \\{0, 1\\}:$
|
||
* If $g(u) = 0$ or $g(x) = 0$, return $\bot$ (even curves only).
|
||
* If $g(-u-x)$ is square, return $\bot.$
|
||
* Let $s = -g(u)/(u^2 + ux + x^2 + a)$ (cannot cause division by zero).
|
||
* Let $v = x.$
|
||
* Otherwise, when $c \in \\{2, 3\\}:$
|
||
* Let $s = x-u.$
|
||
* Let $r = \sqrt{-s(4g(u) + sh(u))}$; return $\bot$ if not square.
|
||
* If $c = 3$ and $r = 0$, return $\bot.$
|
||
* Let $v = (r/s - u)/2.$
|
||
* Let $w = \sqrt{s}$; return $\bot$ if not square.
|
||
* Let $w' = w$ if $sign(w/2) = sign(y)$; $-w$ otherwise.
|
||
* Depending on $c:$
|
||
* If $c \in \\{0, 2\\}:$ return $P_u^{'-1}(v, w').$
|
||
* If $c \in \\{1, 3\\}:$ return $P_u^{'-1}(-u-v, w').$
|
||
|
||
Note that $c$ now only ranges $[0,4)$, as the sign of $w'$ is decided based on that of $y$, rather than on $c.$
|
||
This change makes some valid encodings unreachable: when $y = 0$ and $sign(Y) \neq sign(0)$.
|
||
|
||
In the above logic, $sign$ can be implemented in several ways, such as parity of the integer representation
|
||
of the input field element (for prime-sized fields) or the quadratic residuosity (for fields where
|
||
$-1$ is not square). The choice does not matter, as long as it only takes on two possible values, and for $x \neq 0$ it holds that $sign(x) \neq sign(-x)$.
|
||
|
||
### 4.1 Full *(x, y)* coordinates for `secp256k1`
|
||
|
||
For $a=0$ curves, there is another option. Note that for those,
|
||
the $P_u(t)$ function translates negations of $t$ to negations of (both) $X$ and $Y.$ Thus, we can use $sign(t)$ to
|
||
encode the y-coordinate directly. Combined with the earlier remapping to guarantee all inputs land on the curve, we get
|
||
as decoder:
|
||
|
||
**Define** *Decode(u, t)* as:
|
||
* Let $u'=u$ if $u \neq 0$; $1$ otherwise.
|
||
* Let $t'=t$ if $t \neq 0$; $1$ otherwise.
|
||
* Let $t''=t'$ if $u'^3 + b + t'^2 \neq 0$; $2t'$ otherwise.
|
||
* Let $X = \dfrac{u'^3 + b - t''^2}{2t''}.$
|
||
* Let $Y = \dfrac{X + t''}{u'\sqrt{-3}}.$
|
||
* Let $x$ be the first element of $(u' + 4Y^2, \frac{-X}{2Y} - \frac{u'}{2}, \frac{X}{2Y} - \frac{u'}{2})$ for which $g(x)$ is square.
|
||
* Let $y = \sqrt{g(x)}.$
|
||
* Return $(x, y)$ if $sign(y) = sign(t)$; $(x, -y)$ otherwise.
|
||
|
||
This is implemented in `secp256k1_ellswift_swiftec_var`. The used $sign(x)$ function is the parity of $x$ when represented as in integer in $[0,q).$
|
||
|
||
The corresponding encoder would invoke the x-only one, but negating the output $t$ if $sign(t) \neq sign(y).$
|
||
|
||
This is implemented in `secp256k1_ellswift_elligatorswift_var`.
|
||
|
||
Note that this is only intended for encoding points where both the x-coordinate and y-coordinate are unpredictable. When encoding x-only points
|
||
where the y-coordinate is implicitly even (or implicitly square, or implicitly in $[0,q/2]$), the encoder in
|
||
[Section 3.5](#35-encoding-for-secp256k1) must be used, or a bias is reintroduced that undoes all the benefit of using ElligatorSwift
|
||
in the first place.
|