mirror of
https://github.com/saymrwulf/betrusted-curve25519-dalek-source.git
synced 2026-09-04 20:24:07 +00:00
Merge branch 'release/0.16.2'
This commit is contained in:
commit
5d1f0a4ca6
9 changed files with 533 additions and 347 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "curve25519-dalek"
|
||||
version = "0.16.1"
|
||||
version = "0.16.2"
|
||||
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
|
||||
"Henry de Valence <hdevalence@hdevalence.ca>"]
|
||||
readme = "README.md"
|
||||
|
|
|
|||
4
Makefile
4
Makefile
|
|
@ -1,8 +1,8 @@
|
|||
FEATURES := nightly yolocrypto
|
||||
|
||||
doc:
|
||||
cargo rustdoc --features "$(FEATURES)" -- --html-in-header rustdoc-include-katex-header.html
|
||||
cargo rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html
|
||||
|
||||
doc-internal:
|
||||
cargo rustdoc --features "$(FEATURES)" -- --html-in-header rustdoc-include-katex-header.html --document-private-items
|
||||
cargo rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html --document-private-items
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
475
docs/ristretto-notes.md
Normal file
475
docs/ristretto-notes.md
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
Below are some notes on Ristretto, which are not an authoritative
|
||||
writeup and which may have errors. See also the [Decaf
|
||||
paper][decaf_paper], the [libdecaf
|
||||
implementation of Ristretto][ristretto_libdecaf], and its [Sage
|
||||
script][ristretto_sage].
|
||||
|
||||
Decaf constructs a prime-order group from a cofactor-\\(4\\) Edwards
|
||||
curve by defining an encoding of a related Jacobi quartic, then
|
||||
transporting the encoding from the Jacobi quartic to the Edwards curve
|
||||
by means of an isogeny. Ristretto uses a different Jacobi quartic and
|
||||
a different isogeny, but is otherwise similar.
|
||||
|
||||
These notes only describe Ristretto, and focus on the cofactor-\\(8\\)
|
||||
case.
|
||||
|
||||
# The Jacobi Quartic
|
||||
|
||||
The Jacobi quartic curve is parameterized by \\(e, A\\), and is of the
|
||||
form $$ \mathcal J\_{e,A} : t\^2 = es\^4 + 2As\^2 + 1, $$ with
|
||||
identity point \\((0,1)\\). For more details on the Jacobi quartic,
|
||||
see the [Decaf paper][decaf_paper] or
|
||||
[_Jacobi Quartic Curves Revisited_][hwcd_jacobi] by Hisil, Wong,
|
||||
Carter, and Dawson).
|
||||
|
||||
When \\(e = a\^2\\) is a square, \\(\mathcal J\_{e,A}\\) has full
|
||||
\\(2\\)-torsion (i.e., \\(\mathcal J[2] \cong \mathbb Z /2 \times
|
||||
\mathbb Z/2\\)), and
|
||||
we can write the \\(\mathcal J[2]\\)-coset of a point \\(P =
|
||||
(s,t)\\) as
|
||||
$$
|
||||
P + \mathcal J[2] = \left\\{
|
||||
(s,t),
|
||||
(-s,-t),
|
||||
(1/as, -t/as\^2),
|
||||
(-1/as, t/as\^2)
|
||||
\right\\}.
|
||||
$$
|
||||
Notice that replacing \\(a\\) by \\(-a\\) just swaps the last two
|
||||
points, so this set does not depend on the choice of \\(a\\). In
|
||||
what follows we require \\(a = \pm 1\\).
|
||||
|
||||
# Encoding \\(\mathcal J / \mathcal J[2]\\)
|
||||
|
||||
To encode points on \\(\mathcal J\\) modulo \\(\mathcal J[2]\\),
|
||||
we need to choose a canonical representative of the above coset.
|
||||
To do this, it's sufficient to make two independent sign choices:
|
||||
the Decaf paper suggests choosing \\((s,t)\\) with \\(s\\)
|
||||
non-negative and finite, and \\(t/s\\) non-negative or infinite.
|
||||
|
||||
The encoding is then the (canonical byte encoding of the)
|
||||
\\(s\\)-value of the canonical representative.
|
||||
|
||||
# The Edwards Curve
|
||||
|
||||
The primary internal model in `curve25519-dalek` for Curve25519 points
|
||||
is the [_Extended Twisted Edwards Coordinates_][hwcd_edwards] of
|
||||
Hisil, Wong, Carter, and Dawson. These correspond to the affine model
|
||||
$$
|
||||
\mathcal E\_{a,d} : ax\^2 + y\^2 = 1 + dx\^2y\^2.
|
||||
$$
|
||||
In projective coordinates, we represent a point as \\((X:Y:Z:T)\\)
|
||||
with
|
||||
$$
|
||||
XY = ZT, \quad aX\^2 + Y\^2 = Z\^2 + dT\^2.
|
||||
$$
|
||||
(For more details on this model, see the
|
||||
[`curve_models`][curve_models] documentation). The case \\(a = 1\\) is
|
||||
the _untwisted_ case; we only consider \\(a = \pm 1\\), and in
|
||||
particular we focus on the twisted Edwards form of Curve25519, which
|
||||
has \\(a = -1, d = -121665/121666\\). When not otherwise specified,
|
||||
we write \\(\mathcal E\\) for \\(\mathcal E\_{a,d}\\).
|
||||
|
||||
When both \\(d\\) and \\(ad\\) are nonsquare (which forces \\(a\\)
|
||||
to be square), the curve is *complete*. In this case the
|
||||
four-torsion subgroup is cyclic, and we
|
||||
can write it explicitly as
|
||||
$$
|
||||
\mathcal E\_{a,d}[4] = \\{ (0,1),\\; (1/\sqrt a, 0),\\; (0, -1),\\; (-1/\sqrt{a}, 0)\\}.
|
||||
$$
|
||||
These are the only points with \\(xy = 0\\); the points with
|
||||
\\( y \neq 0 \\) are \\(2\\)-torsion.
|
||||
|
||||
# The Ristretto Group
|
||||
|
||||
We consider two cases:
|
||||
|
||||
* cofactor \\(4\\), where \\( \\# \mathcal E(\mathbb F_p) = 4\cdot \ell \\);
|
||||
* cofactor \\(8\\) with cyclic \\(8\\)-torsion,
|
||||
where \\( \\# \mathcal E(\mathbb F_p) = 8 \cdot \ell \\)
|
||||
and \\( \mathcal E[8] \cong \mathbb Z / 8 \\).
|
||||
|
||||
In the cofactor \\(4\\) case, we have \\( \[2\](\mathcal E[4]) =
|
||||
\mathcal E[2] \\), so that \\( \mathcal E[2] \subseteq \[2\](\mathcal
|
||||
E) \\), and the group we will construct is
|
||||
$$
|
||||
\frac{\[2\](\mathcal E)}{\mathcal E[2]}
|
||||
$$
|
||||
which has prime order \\( (4\ell/2)/2 = \ell \\).
|
||||
|
||||
In the cofactor \\(8\\) case, since the \\(8\\)-torsion is cyclic, we
|
||||
have \\( \[2\](\mathcal E[8]) = \mathcal E[4] \\), so that \\(\mathcal
|
||||
E[4] \subseteq \[2\](\mathcal E)\\), and the group we will construct
|
||||
is
|
||||
$$
|
||||
\frac{\[2\](\mathcal E)}{\mathcal E[4]}
|
||||
$$
|
||||
which has prime order \\( (8\ell/2)/4 = \ell \\).
|
||||
|
||||
In particular, Curve25519 has \\( \mathcal E(\mathbb
|
||||
F\_p) \cong \mathbb Z / 8 \times \mathbb Z / \ell\\), where \\( \ell
|
||||
= 2\^{252} + \cdots \\) is a large prime, and meets the requirements
|
||||
for the cofactor \\(8\\) case.
|
||||
|
||||
# Torquing points to lift from \\(\mathcal E[4]\\) to \\(\mathcal E[2]\\)
|
||||
|
||||
To bridge the gap between the cofactor \\(4\\) and cofactor \\(8\\)
|
||||
cases, we need a way to canonically select a representative modulo
|
||||
\\(\mathcal E[2] \\), given a representative modulo \\(\mathcal E[4] \\).
|
||||
|
||||
Using the description of \\(\mathcal E[4]\\) above, we can write the
|
||||
\\(\mathcal E[4]\\)-coset of a point \\(P = (x,y)\\) as
|
||||
$$
|
||||
P + \mathcal E\_{a,d}[4] = \\{ (x,y),\\; (y/\sqrt a, -x\sqrt a),\\; (-x, -y),\\; (-y/\sqrt a, x\sqrt a)\\}.
|
||||
$$
|
||||
Notice that if \\(xy \neq 0 \\), then exactly two of these points have
|
||||
\\( xy \\) non-negative, and they differ by the \\(2\\)-torsion point
|
||||
\\( (0,-1) \\).
|
||||
|
||||
This means that we can select a representative modulo
|
||||
\\(\mathcal E[2]\\) by requiring \\(xy\\) nonnegative and \\(y \neq
|
||||
0\\), and we can ensure that this condition holds by conditionally
|
||||
adding a \\(4\\)-torsion point \\(Q_4\\) if \\(xy\\) is negative or
|
||||
\\(y = 0\\).
|
||||
|
||||
The points of exact order \\(4\\) are \\( (\pm 1/\sqrt{a}, 0 )\\);
|
||||
convenient choices for \\( Q_4 \\) are \\((1,0)\\) when \\( a = 1 \\)
|
||||
and \\( (i, 0) \\) when \\( a = -1 \\), although the choice of which
|
||||
\\(4\\)-torsion point to use doesn't matter.
|
||||
|
||||
This procedure gives a canonical lift from \\(\mathcal E / \mathcal
|
||||
E[4]\\) to \\(\mathcal E / \mathcal E[2]\\). Since it involves a
|
||||
conditional rotation, we refer to it as *torquing* the point.
|
||||
|
||||
# The Isogeny
|
||||
|
||||
For \\(a = \pm 1\\), we have a \\(2\\)-isogeny
|
||||
$$
|
||||
\theta\_{a,d} : \mathcal J\_{a\^2, -a(a+d)/(a-d)} \longrightarrow \mathcal E\_{a,d}
|
||||
$$
|
||||
(or simply \\(\theta\\)) defined by
|
||||
$$
|
||||
\theta\_{a,d} : (s,t) \mapsto \left( \frac{1}{\sqrt{ad-1}} \cdot \frac{2s}{t},\quad \frac{1+as\^2}{1-as\^2} \right).
|
||||
$$
|
||||
Its dual is
|
||||
$$
|
||||
\hat{\theta}\_{a,d} : \mathcal E\_{a,d} \longrightarrow \mathcal J\_{a\^2, -a(a+d)/(a-d)},
|
||||
$$
|
||||
defined by
|
||||
$$
|
||||
\hat{\theta}\_{a,d} : (x,y) \mapsto \left( \sqrt{ad-1} \cdot \frac{xy}{1-ax\^2}, \frac{y^2 + ax^2}{1-ax^2} \right)
|
||||
$$
|
||||
|
||||
The kernel of the isogeny is \\( \{(0, \pm 1)\} \\).
|
||||
The image of the isogeny is \\(\[2\](\mathcal E)\\). To see this,
|
||||
first note that because \\( \theta \circ \hat{\theta} = [2] \\), we
|
||||
know that \\( \[2\](\mathcal E) \subseteq \theta(\mathcal J)\\); then, to see that
|
||||
\\(\theta(\mathcal J)\\) is exactly \\(\[2\](\mathcal E)\\),
|
||||
recall that isogenous elliptic curves over a finite field have the
|
||||
same number of points (exercise 5.4 of Silverman), so that
|
||||
$$
|
||||
\\# \theta(\mathcal J) = \frac {\\# \mathcal J} {\\# \ker \theta}
|
||||
= \frac {\\# \mathcal E}{2} = \\# \[2\](\mathcal E).
|
||||
$$
|
||||
|
||||
To determine the image \\(\theta(\mathcal J[2])\\) of the
|
||||
\\(2\\)-torsion, we consider the image of the coset
|
||||
\\(\theta((s,t) + \mathcal J[2])\\).
|
||||
Let \\((x,y) = \theta(s,t)\\); then
|
||||
\\(\theta(-s,-t) = (x,y)\\) and
|
||||
\\(\theta(1/as, -t/as\^2) = (-x, -y)\\),
|
||||
so that \\(\theta(\mathcal J[2]) = \mathcal E[2]\\).
|
||||
|
||||
# Encoding with the Isogeny
|
||||
|
||||
The Decaf paper recalls that, for a group \\( G \\) with normal
|
||||
subgroup \\(G' \leq G\\), a group homomorphism \\( \phi : G
|
||||
\rightarrow H \\) induces a homomorphism
|
||||
$$
|
||||
\bar{\phi} : \frac G {G'} \longrightarrow \frac {\phi(G)}{\phi(G')} \leq \frac {H} {\phi(G')},
|
||||
$$
|
||||
and that the induced homomorphism \\(\bar{\phi}\\) is injective if
|
||||
\\( \ker \phi \leq G' \\). In our context, the kernel of
|
||||
\\(\theta\\) is \\( \\{(0, \pm 1)\\} \leq \mathcal J[2] \\),
|
||||
so \\(\theta\\) gives an isomorphism
|
||||
$$
|
||||
\frac {\mathcal J} {\mathcal J[2]}
|
||||
\cong
|
||||
\frac {\theta(\mathcal J)} {\theta(\mathcal J[2])}
|
||||
\cong
|
||||
\frac {\[2\](\mathcal E)} {\mathcal E[2]}.
|
||||
$$
|
||||
|
||||
We can use the isomorphism to transfer the encoding of \\(\mathcal
|
||||
J / \mathcal J[2] \\) defined above to \\(\[2\](\mathcal E)/\mathcal
|
||||
E[2]\\), by encoding the Edwards point \\((x,y)\\) using the Jacobi
|
||||
quartic encoding of \\(\theta\^{-1}(x,y)\\).
|
||||
|
||||
Since \\(\\# (\[2\](\mathcal E) / \mathcal E[2]) = (\\#\mathcal
|
||||
E)/4\\), if \\(\mathcal E\\) has cofactor \\(4\\), we're done.
|
||||
Otherwise, if \\(\mathcal E\\) has cofactor \\(8\\), as in the
|
||||
Curve25519 case, we use the torquing procedure to lift \\(\mathcal E
|
||||
/ \mathcal E[4]\\) to \\(\mathcal E / \mathcal E[2]\\), and then
|
||||
apply the encoding for \\( \[2\](\mathcal E) / \mathcal E[2] \\).
|
||||
|
||||
# The Ristretto Encoding
|
||||
|
||||
We can write the above encoding/decoding procedure in affine
|
||||
coordinates, before describing optimized formulas to and from
|
||||
projective coordinates.
|
||||
|
||||
## Encoding in Affine Coordinates
|
||||
|
||||
On input \\( (x,y) \in \[2\](\mathcal E)\\), a representative for a
|
||||
coset in \\( \[2\](\mathcal E) / \mathcal E[4] \\):
|
||||
|
||||
1. Check if \\( xy \\) is negative or \\( x = 0 \\); if so, torque
|
||||
the point by setting \\( (x,y) \gets (x,y) + Q_4 \\), where
|
||||
\\(Q_4\\) is a \\(4\\)-torsion point.
|
||||
|
||||
2. Check if \\(x\\) is negative or \\( y = -1 \\); if so, set
|
||||
\\( (x,y) \gets (x,y) + (0,-1) = (-x, -y) \\).
|
||||
|
||||
3. Compute $$ s = +\sqrt {(-a) \frac {1 - y} {1 + y} }, $$ choosing
|
||||
the positive square root.
|
||||
|
||||
The output is then the (canonical) byte-encoding of \\(s\\).
|
||||
|
||||
If \\(\mathcal E\\) has cofactor \\(4\\), we skip the first step,
|
||||
since our input already represents a coset in
|
||||
\\( \[2\](\mathcal E) / \mathcal E[2] \\).
|
||||
|
||||
## Interpreting the Encoding Procedure
|
||||
|
||||
How does this procedure correspond to the description involving
|
||||
\\( \theta \\)?
|
||||
|
||||
The first step lifts from \\( \mathcal E / \mathcal E[4] \\) to
|
||||
\\(\mathcal E / \mathcal E[2]\\). To understand steps 2 and 3,
|
||||
notice that the \\(y\\)-coordinate of \\(\theta(s,t)\\) is
|
||||
$$
|
||||
y = \frac {1 + as\^2}{1 - as\^2},
|
||||
$$
|
||||
so that the \\(s\\)-coordinate of \\(\theta\^{-1}(x,y)\\) has
|
||||
$$
|
||||
s\^2 = (-a)\frac {1-y}{1+y}.
|
||||
$$
|
||||
Since
|
||||
$$
|
||||
x = \frac 1 {\sqrt {ad - 1}} \frac {2s} {t},
|
||||
$$
|
||||
we also have
|
||||
$$
|
||||
\frac s t = x \frac {\sqrt {ad-1}} 2,
|
||||
$$
|
||||
so that the sign of \\(s/t\\) is determined by the sign of \\(x\\).
|
||||
|
||||
Recall that to choose a canonical representative of \\( (s,t) +
|
||||
\mathcal J[2] \\), it's sufficient to make two sign choices: the
|
||||
sign of \\(s\\) and the sign of \\(s/t\\). Step 2 determines the
|
||||
sign of \\(s/t\\), while step 3 computes \\(s\\) and determines its
|
||||
sign (by choosing the positive square root). Finally, the check
|
||||
that \\(y \neq -1\\) prevents division-by-zero when encoding the
|
||||
identity; it falls out of the optimized formulas below.
|
||||
|
||||
## Decoding to Affine Coordinates
|
||||
|
||||
On input `s_bytes`, decoding proceeds as follows:
|
||||
|
||||
1. Decode `s_bytes` to \\(s\\); reject if `s_bytes` is not the
|
||||
canonical encoding of \\(s\\).
|
||||
|
||||
2. Check whether \\(s\\) is negative; if so, reject.
|
||||
|
||||
3. Compute
|
||||
$$
|
||||
y \gets \frac {1 + as\^2}{1 - as\^2}.
|
||||
$$
|
||||
|
||||
4. Compute
|
||||
$$
|
||||
x \gets +\sqrt{ \frac{4s\^2} {ad(1+as\^2)\^2 - (1-as\^2)\^2}},
|
||||
$$
|
||||
choosing the positive square root, or reject if the square root does
|
||||
not exist.
|
||||
|
||||
5. Check whether \\(xy\\) is negative or \\(y = 0\\); if so, reject.
|
||||
|
||||
# Encoding in Extended Coordinates
|
||||
|
||||
The formulas above are given in affine coordinates, but the usual
|
||||
internal representation is extended twisted Edwards coordinates \\(
|
||||
(X:Y:Z:T) \\) with \\( x = X/Z \\), \\(y = Y/Z\\), \\(xy = T/Z \\).
|
||||
|
||||
This section only covers the cofactor-\\(8\\) case, since it is more complicated:
|
||||
selecting the distinguished representative of the coset
|
||||
requires the affine coordinates \\( (x,y) \\), and computing \\( s
|
||||
\\) requires an inverse square root.
|
||||
As inversions are expensive, we'd like to be able to do this
|
||||
whole computation with only one inverse square root, by batching
|
||||
together the inversion and the inverse square root.
|
||||
|
||||
It is not obvious how to do this, since we need the inverse square
|
||||
root of one of two values, depending on what the distinguished
|
||||
representative is, but the choice of representative depends on the
|
||||
affine coordinates. However, an ingenious trick (due to Mike Hamburg)
|
||||
allows recovering either of the inverse square roots we want.
|
||||
|
||||
## Batching the Inversion and Inverse Square Root
|
||||
|
||||
Write \\( (X\_0 : Y\_0 : Z\_0 : T\_0) \\)
|
||||
for the coordinates of the initial representative, and write
|
||||
\\( (X:Y:Z:T) \\) for the coordinates of the distinguished
|
||||
representative of the coset.
|
||||
|
||||
Since \\(y = Y/Z\\), in extended coordinates the formula for \\(s\\) becomes
|
||||
$$
|
||||
s
|
||||
= \sqrt{ (-a) \frac{ 1 - Y/Z}{1+Y/Z}} = \sqrt{\frac{Z - Y}{Z+Y}} \sqrt{-a}
|
||||
= \frac {Z - Y} {\sqrt{Z\^2 - Y\^2}} \sqrt{-a},
|
||||
$$
|
||||
so we need to compute \\( 1 / \sqrt{Z^2 - Y^2} \\).
|
||||
|
||||
The distinguished representative \\( (X:Y:Z:T) \\) is selected by the
|
||||
torquing procedure in step 1, which conditionally adds a
|
||||
\\(4\\)-torsion point \\(Q_4\\). As noted in the torquing section
|
||||
above, \\( Q_4 = (\pm 1/\sqrt{a}, 0) \\), so we obtain
|
||||
$$
|
||||
(X : Y : Z : T ) =
|
||||
\begin{cases}
|
||||
(X\_0 : Y\_0 : Z\_0 : T\_0) \\\\
|
||||
(\pm Y\_0 / \sqrt{a} : \mp X\_0 \sqrt{a} : Z\_0 : -T\_0)
|
||||
\end{cases}
|
||||
.
|
||||
$$
|
||||
This means we want to compute either of
|
||||
$$
|
||||
\frac {1} {\sqrt{Z^2 - Y^2}}
|
||||
=
|
||||
\begin{cases}
|
||||
1 / \sqrt{Z\_0^2 - Y\_0^2} \\\\
|
||||
1 / \sqrt{Z\_0^2 - aX\_0^2}
|
||||
\end{cases}
|
||||
.
|
||||
$$
|
||||
To relate these quantities, recall from the curve equation that
|
||||
$$
|
||||
-dX\^2Y\^2 = Z\^4 - aZ\^2X\^2 - Z\^2Y\^2,
|
||||
$$
|
||||
so
|
||||
$$
|
||||
(a-d)X\^2Y\^2 = Z\^4 - aZ\^2X\^2 - Z\^2Y\^2 + aX\^2Y\^2.
|
||||
$$
|
||||
Factoring the right-hand side gives
|
||||
$$
|
||||
(a-d)X\^2Y\^2 = (Z\^2 - Y\^2)(Z\^2 - aX\^2),
|
||||
$$
|
||||
which relates the two quantities we want to compute:
|
||||
$$
|
||||
\frac 1 {Z^2 - aX^2} = \frac 1 {a - d} \frac {Z^2 - Y^2} {X^2 Y^2}
|
||||
$$
|
||||
so
|
||||
$$
|
||||
\frac 1 {\sqrt{Z^2 - aX^2}} = \frac 1 {\sqrt{a - d}} \sqrt{ \frac {Z^2 - Y^2} {X^2 Y^2} }
|
||||
$$
|
||||
|
||||
## Explicit Encoding Formulas
|
||||
|
||||
Using this trick, we can write the encoding procedure explicitly:
|
||||
|
||||
1. \\(u\_1 \gets (Z\_0 + Y\_0)(Z\_0 - Y\_0)
|
||||
\textcolor{gray}{= Z\_0\^2 - Y\_0\^2}
|
||||
\\)
|
||||
2. \\(u\_2 \gets X\_0 Y\_0 \\)
|
||||
3. \\(I \gets \mathrm{invsqrt}(u\_1 u\_2\^2)
|
||||
\textcolor{gray}{= 1/\sqrt{X\_0\^2 Y\_0\^2 (Z\_0\^2 - Y\_0\^2)}}
|
||||
\\)
|
||||
4. \\(D\_1 \gets u\_1 I
|
||||
\textcolor{gray}{= \sqrt{(Z\_0\^2 - Y\_0\^2)/(X\_0\^2 Y\_0\^2)} }
|
||||
\\)
|
||||
5. \\(D\_2 \gets u\_2 I
|
||||
\textcolor{gray}{= \pm \sqrt{1/(Z\_0\^2 - Y\_0\^2)} }
|
||||
\\)
|
||||
6. \\(Z\_{inv} \gets D\_1 D\_2 T\_0
|
||||
\textcolor{gray}{= (u\_1 u\_2)/(u\_1 u\_2\^2) T\_0 = T\_0 / X\_0 Y\_0 = 1/Z\_0}
|
||||
\\)
|
||||
7. If \\( T\_0 Z\_{inv} \textcolor{gray}{= x\_0 y\_0 }\\) is negative:
|
||||
1. \\( (X, Y) \gets (Y\_0 (\pm 1/\sqrt{a}), X\_0 (\mp \sqrt{a})) \\)
|
||||
2. \\( D \gets D\_1 / \sqrt{a-d}
|
||||
\textcolor{gray}{= 1/\sqrt{Z\_0\^2 - a X\_0\^2} = 1/\sqrt{Z^2 -Y^2} }
|
||||
\\)
|
||||
8. Otherwise:
|
||||
1. \\( (X, Y) \gets (X\_0, Y\_0) \\)
|
||||
2. \\( D \gets D\_2
|
||||
\textcolor{gray}{= \pm \sqrt{1/(Z\_0\^2 - Y\_0\^2)} = \pm 1/\sqrt{Z^2 - Y^2}}
|
||||
\\)
|
||||
9. If \\( X Z\_{inv} \textcolor{gray}{= x} \\) is negative, set \\( Y \gets - Y\\)
|
||||
10. Compute \\( s \gets |\sqrt{-a} (Z - Y) D| \textcolor{gray}{= |\sqrt{-a} (Z - Y) / \sqrt{Z\^2 - Y\^2}| } \\)
|
||||
11. Return the canonical byte encoding of \\( s \\).
|
||||
|
||||
The choice of \\( Q\_4 = (i, 0) \\) when \\( a = -1 \\) is convenient
|
||||
since it simplifies 7.1 to \\( (X,Y) \gets (iY_0, iX_0) \\).
|
||||
|
||||
## Explicit Decoding Formulas
|
||||
|
||||
As with encoding, we want to batch operations to use only a single
|
||||
inverse square root. However, the procedure is much simpler since
|
||||
there's no torquing.
|
||||
|
||||
On input `s_bytes`:
|
||||
|
||||
1. Check that `s_bytes` is the canonical byte-encoding of a field
|
||||
element \\(s\\), otherwise reject.
|
||||
2. Decode `s_bytes` to \\(s\\).
|
||||
3. Check that \\( s \\) is nonnegative, otherwise reject.
|
||||
4. \\( u_1 \gets 1 + as^2 \\)
|
||||
5. \\( u_2 \gets 1 - as^2 \\)
|
||||
6. \\( v \gets (ad)u_1^2 - u_2^2 \textcolor{gray}{= ad(1+as^2)^2 - (1-as^2)^2} \\)
|
||||
7. \\( I \gets \mathrm{invsqrt}( v u_2^2 ) \textcolor{gray}{= 1/\sqrt{v u_2^2} } \\)
|
||||
8. \\( D_x \gets Iu_2 \textcolor{gray}{= 1/\sqrt{v} } \\)
|
||||
9. \\( D_y \gets ID_x v \textcolor{gray}{= I^2 u_2 v = (v u_2) / (v u_2^2) = 1/u_2 } \\)
|
||||
10. \\( x \gets |2sD_x| \textcolor{gray}{= +\sqrt{ 4s^2 / (ad(1+as^2)^2 - (1-as^2)^2 )}}\\)
|
||||
11. \\( y \gets u_1 D_y \textcolor{gray}{= (1+as^2)/(1-as^2) } \\)
|
||||
12. \\( t \gets xy \\)
|
||||
12. Check that \\(t \\) is nonnegative and that \\( y \neq 0 \\), otherwise reject.
|
||||
13. Return \\( P = (x: y: 1: t) \\)
|
||||
|
||||
# Batched Double-and-Encode Using \\( \hat \theta \\)
|
||||
|
||||
The encoding is not batchable, since it requires an inverse square
|
||||
root. However, since \\( \theta \circ \hat \theta = [2] P \\), it's
|
||||
possible to compute the encoding of \\( [2]P \\) by using \\( \hat
|
||||
\theta \\) instead of \\( \theta^{-1} \\). Since \\( \hat \theta \\) only
|
||||
requires inversions, given \\( P\_1, \ldots, P\_n \\), it's possible
|
||||
to compute the encodings of \\( [2]P\_1, \ldots, [2]P\_n \\) in a
|
||||
batch.
|
||||
|
||||
XXX write up details
|
||||
|
||||
# Equality Testing
|
||||
|
||||
Testing equality of two Ristretto points means testing whether they
|
||||
are equal in the quotient group, i.e., whether they lie in the same
|
||||
coset of \\(\mathcal E[4] \\) (for the cofactor-\\(8\\) case) or
|
||||
\\(\mathcal E[2] \\) (for the cofactor-\\(4\\) case).
|
||||
|
||||
Equality testing of points on the Edwards curve requires comparing to
|
||||
affine coordinates, which requires an expensive inversion. However,
|
||||
testing whether two points lie in the same coset can be done in
|
||||
projective coordinates, making it actually *easier* than equality
|
||||
testing in the original non-quotient group.
|
||||
|
||||
XXX write up details
|
||||
|
||||
# Elligator
|
||||
|
||||
XXX write up details
|
||||
|
||||
[ristretto_sage]: https://sourceforge.net/p/ed448goldilocks/code/ci/master/tree/aux/ristretto/ristretto.sage
|
||||
[ristretto_libdecaf]: https://sourceforge.net/p/ed448goldilocks/code/ci/master/tree/
|
||||
[decaf_paper]: https://eprint.iacr.org/2015/673.pdf
|
||||
[hwcd_jacobi]: https://eprint.iacr.org/2009/312.pdf
|
||||
[hwcd_edwards]: https://eprint.iacr.org/2008/522.pdf
|
||||
[edwards_edwards]: https://www.ams.org/journals/bull/2007-44-03/S0273-0979-07-01153-6/S0273-0979-07-01153-6.pdf
|
||||
[twisted_edwards]: https://eprint.iacr.org/2008/013.pdf
|
||||
[curve_models]: ../../curve_models/index.html
|
||||
|
|
@ -26,6 +26,9 @@
|
|||
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
|
||||
#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")]
|
||||
|
||||
//! Note that docs will only build on nightly Rust until
|
||||
//! [RFC 1990 stabilizes](https://github.com/rust-lang/rust/issues/44732).
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// External dependencies:
|
||||
//------------------------------------------------------------------------
|
||||
|
|
|
|||
396
src/ristretto.rs
396
src/ristretto.rs
|
|
@ -19,11 +19,13 @@
|
|||
//! # The Ristretto Group
|
||||
//!
|
||||
//! Ristretto is a modification of Mike Hamburg's Decaf scheme to work
|
||||
//! with Curve25519. The introduction of the Decaf paper, [_Decaf:
|
||||
//! with cofactor-\\(8\\) curves, such as Curve25519.
|
||||
//!
|
||||
//! The introduction of the Decaf paper, [_Decaf:
|
||||
//! Eliminating cofactors through point
|
||||
//! compression_](https://eprint.iacr.org/2015/673.pdf), notes that while
|
||||
//! most cryptographic systems require a group of prime order, most
|
||||
//! concrete implementations using elliptic curve groups fall short --
|
||||
//! concrete implementations using elliptic curve groups fall short –
|
||||
//! they either provide a group of prime order, but with incomplete or
|
||||
//! variable-time addition formulae (for instance, most Weierstrass
|
||||
//! models), or else they provide a fast and safe implementation of a
|
||||
|
|
@ -31,15 +33,27 @@
|
|||
//! small cofactor \\(h\\) (for instance, Edwards curves, which have
|
||||
//! cofactor at least \\(4\\)).
|
||||
//!
|
||||
//! This abstraction mismatch requires ad-hoc protocol modifications to
|
||||
//! ensure security; these modifications require careful analysis and
|
||||
//! are a recurring source of [vulnerabilities][cryptonote] and [design
|
||||
//! This abstraction mismatch is commonly “handled” by pushing the
|
||||
//! complexity upwards, adding ad-hoc protocol modifications. But
|
||||
//! these modifications require careful analysis and are a recurring
|
||||
//! source of [vulnerabilities][cryptonote] and [design
|
||||
//! complications][ed25519_hkd].
|
||||
//!
|
||||
//! Instead, Ristretto uses a quotient group to implement a prime-order
|
||||
//! group using a non-prime-order curve. More details are described in
|
||||
//! the *Implementation* section below. Ristretto points are provided
|
||||
//! in `curve25519-dalek` by the `RistrettoPoint` struct.
|
||||
//! Instead, Decaf (and Ristretto) use a quotient group to implement a
|
||||
//! prime-order group using a non-prime-order curve. This provides
|
||||
//! the correct abstraction for cryptographic systems, while retaining
|
||||
//! the speed and safety benefits of an Edwards curve.
|
||||
//!
|
||||
//! Decaf is named “after the procedure which divides the effect of
|
||||
//! coffee by \\(4\\)”. However, Curve25519 has a cofactor of
|
||||
//! \\(8\\). To eliminate its cofactor, Ristretto restricts further;
|
||||
//! this [additional restriction][ristretto_coffee] gives the
|
||||
//! _Ristretto_ encoding.
|
||||
//!
|
||||
//! More details
|
||||
//! are described in the *Implementation* section below. Ristretto
|
||||
//! points are provided in `curve25519-dalek` by the `RistrettoPoint`
|
||||
//! struct.
|
||||
//!
|
||||
//! ## Encoding and Decoding
|
||||
//!
|
||||
|
|
@ -65,8 +79,10 @@
|
|||
//! ## Scalars
|
||||
//!
|
||||
//! Scalars are represented by the `Scalar` struct. Each scalar has a
|
||||
//! canonical representative mod the group order; see
|
||||
//! `Scalar::from_canonical_bytes()` and `Scalar::is_canonical()`.
|
||||
//! canonical representative mod the group order. To attempt to load
|
||||
//! a supposedly-canonical scalar, use
|
||||
//! `Scalar::from_canonical_bytes()`. To check whether a
|
||||
//! representative is canonical, use `Scalar::is_canonical()`.
|
||||
//!
|
||||
//! ## Scalar Multiplication
|
||||
//!
|
||||
|
|
@ -115,19 +131,10 @@
|
|||
//! a coset is accepted).
|
||||
//!
|
||||
//! Internally, each coset is represented by a curve point; two points
|
||||
//! may represent the same coset in the same way that two points with
|
||||
//! different \\(X,Y,Z\\) coordinates may represent the same point. The
|
||||
//! group operations are carried out using the fast, safe Edwards
|
||||
//! formulas.
|
||||
//!
|
||||
//! The Decaf paper suggests implementing the compression and
|
||||
//! decompression routines using an isogeny from a Jacobi quartic; for
|
||||
//! curves of cofactor \\(4\\), this eliminates the cofactor, and
|
||||
//! explains the name: Decaf is named "after the procedure which divides
|
||||
//! the effect of coffee by \\(4\\)". However, Curve25519 has a
|
||||
//! cofactor of \\(8\\). To eliminate its cofactor, we tweak Decaf to
|
||||
//! restrict further. This [additional restriction][ristretto_coffee]
|
||||
//! gives the _Ristretto_ encoding.
|
||||
//! \\( P, Q \\) may represent the same coset in the same way that two
|
||||
//! points with different \\(X,Y,Z\\) coordinates may represent the
|
||||
//! same point. The group operations are carried out with no overhead
|
||||
//! using Edwards formulas.
|
||||
//!
|
||||
//! Notes on the details of the encoding can be found in the
|
||||
//! [`ristretto::notes`][ristretto_notes] submodule of the internal `curve25519-dalek`
|
||||
|
|
@ -142,327 +149,18 @@
|
|||
//! [ristretto_notes]:
|
||||
//! https://doc-internal.dalek.rs/curve25519_dalek/ristretto/notes/index.html
|
||||
|
||||
|
||||
// Conditionally include the Ristretto notes if:
|
||||
// - we're on nightly (so we can include docs at all)
|
||||
// - we're in stage 2 of the build.
|
||||
// The latter point prevents a really silly and annoying problem,
|
||||
// where the location of ".." is different depending on whether we're
|
||||
// building the crate for real, or whether we're in build.rs
|
||||
// generating the lookup tables (in which case we're relative to the
|
||||
// location of build.rs, not lib.rs, so the markdown file appears
|
||||
// missing).
|
||||
#[cfg_attr(all(feature = "nightly", feature="precomputed_tables"), doc(include = "../docs/ristretto-notes.md"))]
|
||||
mod notes {
|
||||
|
||||
//! Below are some notes on Ristretto, which are *NOT* a full writeup and which may have errors.
|
||||
//!
|
||||
//! # Notes on Ristretto
|
||||
//!
|
||||
//! ## The Jacobi Quartic
|
||||
//!
|
||||
//! The Jacobi quartic is parameterized by \\(e, A\\), and is of the
|
||||
//! form $$ \mathcal J\_{e,A} : t\^2 = es\^4 + 2As\^2 + 1, $$ with
|
||||
//! identity point \\((0,1)\\). For more details on the Jacobi quartic,
|
||||
//! see the [Decaf paper](https://eprint.iacr.org/2015/673.pdf) or
|
||||
//! [_Jacobi Quartic Curves
|
||||
//! Revisited_](https://eprint.iacr.org/2009/312.pdf) by Hisil, Wong,
|
||||
//! Carter, and Dawson).
|
||||
//!
|
||||
//! When \\(e = a\^2\\), \\(\mathcal J\_{e,A}\\) has full
|
||||
//! \\(2\\)-torsion (i.e., \\(\mathcal J[2] \cong \mathbb Z /2 \times
|
||||
//! \mathbb Z/2\\)), and
|
||||
//! we can write the \\(\mathcal J[2]\\)-coset of a point \\(P =
|
||||
//! (s,t)\\) as
|
||||
//! $$
|
||||
//! P + \mathcal J[2] = \left\\{
|
||||
//! (s,t),
|
||||
//! (-s,-t),
|
||||
//! (1/as, -t/as\^2),
|
||||
//! (-1/as, t/as\^2) \right\\}.
|
||||
//! $$
|
||||
//! Notice that replacing \\(a\\) by \\(-a\\) just swaps the last two
|
||||
//! points, so this set does not depend on the choice of \\(a\\). In
|
||||
//! what follows we require \\(a = \pm 1\\).
|
||||
//!
|
||||
//! ## Encoding \\(\mathcal J / \mathcal J[2]\\)
|
||||
//!
|
||||
//! To encode points on \\(\mathcal J\\) modulo \\(\mathcal J[2]\\),
|
||||
//! we need to choose a canonical representative of the above coset.
|
||||
//! To do this, it's sufficient to make two independent sign choices:
|
||||
//! the Decaf paper suggests choosing \\((s,t)\\) with \\(s\\)
|
||||
//! non-negative and finite, and \\(t/s\\) non-negative or infinite.
|
||||
//!
|
||||
//! The encoding is then the (canonical byte encoding of the)
|
||||
//! \\(s\\)-value of the canonical representative.
|
||||
//!
|
||||
//! ## The Edwards Curve
|
||||
//!
|
||||
//! Our primary internal model for Curve25519 points are the [_Extended
|
||||
//! Twisted Edwards Coordinates_](https://eprint.iacr.org/2008/522.pdf)
|
||||
//! of Hisil, Wong, Carter, and Dawson.
|
||||
//! These correspond to the affine model
|
||||
//!
|
||||
//! $$\mathcal E\_{a,d} : ax\^2 + y\^2 = 1 + dx\^2y\^2.$$
|
||||
//!
|
||||
//! In projective coordinates, we represent a point as \\((X:Y:Z:T)\\)
|
||||
//! with $$XY = ZT, \quad aX\^2 + Y\^2 = Z\^2 + dT\^2.$$ (For more
|
||||
//! details on this model, see the documentation for the `edwards`
|
||||
//! module). The case \\(a = 1\\) is the _untwisted_ case; we only
|
||||
//! consider \\(a = \pm 1\\), and in particular we focus on the twisted
|
||||
//! Edwards form of Curve25519, which has \\(a = -1, d =
|
||||
//! -121665/121666\\). When not otherwise specified, we write
|
||||
//! \\(\mathcal E\\) for \\(\mathcal E\_{-1, -121665/121666}\\).
|
||||
//!
|
||||
//! When both \\(d\\) and \\(ad\\) are nonsquare (which forces \\(a\\)
|
||||
//! to be square), the curve is *complete*. In this case the
|
||||
//! four-torsion subgroup is cyclic, and we
|
||||
//! can write it explicitly as
|
||||
//! $$
|
||||
//! \mathcal E\_{a,d}[4] = \\{ (0,1),\; (1/\sqrt a, 0),\; (0, -1),\; (-1/\sqrt{a}, 0)\\}.
|
||||
//! $$
|
||||
//! These are the only points with \\(xy = 0\\); the points with \\( y
|
||||
//! \neq 0 \\) are \\(2\\)-torsion. The \\(\mathcal
|
||||
//! E\_{a,d}[4]\\)-coset of \\(P = (x,y)\\) is then
|
||||
//! $$
|
||||
//! P + \mathcal E\_{a,d}[4] = \\{ (x,y),\; (y/\sqrt a, -x\sqrt a),\; (-x, -y),\; (-y/\sqrt a, x\sqrt a)\\}.
|
||||
//! $$
|
||||
//! Notice that if \\(xy \neq 0 \\), then exactly two of
|
||||
//! these points have \\( xy \\) non-negative, and they differ by the
|
||||
//! \\(2\\)-torsion point \\( (0,-1) \\). This means that we can select
|
||||
//! a representative modulo \\(\mathcal
|
||||
//! E\_{a,d}[2] \\) by requiring \\(xy\\) nonnegative and \\(y \neq
|
||||
//! 0\\), and we can ensure this condition by conditionally adding a
|
||||
//! \\(4\\)-torsion point if \\(xy\\) is negative or \\(y = 0\\).
|
||||
//!
|
||||
//! This procedure gives a canonical lift from \\(\mathcal E / \mathcal
|
||||
//! E[4]\\) to \\(\mathcal E / \mathcal E[2]\\). Since it involves a
|
||||
//! conditional rotation, we refer to it as *torquing* the point.
|
||||
//!
|
||||
//! The structure of the Curve25519 group is \\( \mathcal E(\mathbb
|
||||
//! F\_p) \cong \mathbb Z / 8 \times \mathbb Z / \ell\\), where \\( \ell
|
||||
//! = 2\^{252} + \cdots \\) is a large prime. Because \\(\mathcal E[8]
|
||||
//! \cong \mathbb Z / 8\\), we have \\(\[2\](\mathcal E[8]) = \mathcal
|
||||
//! E[4]\\), \\(\mathcal E[4] \cong \mathbb Z / 4
|
||||
//! \\) and \\( \mathcal E[2] \cong \mathbb Z / 2\\). In particular
|
||||
//! this tells us that the group
|
||||
//! $$
|
||||
//! \frac{\[2\](\mathcal E)}{\mathcal E[4]}
|
||||
//! $$
|
||||
//! is well-defined and has prime order \\( (8\ell / 2) / 4 = \ell \\).
|
||||
//! This is the group we will construct using Ristretto.
|
||||
//!
|
||||
//! ## The Isogeny
|
||||
//!
|
||||
//! For \\(a = \pm 1\\), we have a \\(2\\)-isogeny
|
||||
//! $$
|
||||
//! \theta\_{a,d} : \mathcal J\_{a\^2, -a(a+d)/(a-d)} \longrightarrow \mathcal E\_{a,d}
|
||||
//! $$
|
||||
//! (or simply \\(\theta\\)) defined by
|
||||
//! $$
|
||||
//! \theta\_{a,d} : (s,t) \mapsto \left( \frac{1}{\sqrt{ad-1}} \cdot \frac{2s}{t},\quad \frac{1+as\^2}{1-as\^2} \right).
|
||||
//! $$
|
||||
//!
|
||||
//! XXX Its dual is ... ?
|
||||
//!
|
||||
//! The kernel of the isogeny is \\( \{(0, \pm 1)\} \\).
|
||||
//! The image of the isogeny is \\(\[2\](\mathcal E)\\). To see this,
|
||||
//! first note that because \\( \theta \circ \hat{\theta} = [2] \\), we
|
||||
//! know that \\( \[2\](\mathcal E) \subseteq \theta(\mathcal J)\\); then, to see that
|
||||
//! \\(\theta(\mathcal J)\\) is exactly \\(\[2\](\mathcal E)\\),
|
||||
//! recall that isogenous elliptic curves over a finite field have the
|
||||
//! same number of points (exercise 5.4 of Silverman), so that
|
||||
//! $$
|
||||
//! \\# \theta(\mathcal J) = \frac {\\# \mathcal J} {\\# \ker \theta}
|
||||
//! = \frac {\\# \mathcal E}{2} = \\# \[2\](\mathcal E).
|
||||
//! $$
|
||||
//!
|
||||
//! To determine the image \\(\theta(\mathcal J[2])\\) of the
|
||||
//! \\(2\\)-torsion, we consider the image of the coset \\(\theta((s,t)
|
||||
//! + \mathcal J[2])\\). Let \\((x,y) = \theta(s,t)\\); then
|
||||
//! \\(\theta(-s,-t) = (x,y)\\) and \\(\theta(1/as, -t/as\^2) = (-x,
|
||||
//! -y)\\), so that \\(\theta(\mathcal J[2]) = \mathcal E[2]\\).
|
||||
//!
|
||||
//! The Decaf paper recalls that, for a group \\( G \\) with normal
|
||||
//! subgroup \\(G' \leq G\\), a group homomorphism \\( \phi : G
|
||||
//! \rightarrow H \\) induces a homomorphism
|
||||
//! $$
|
||||
//! \bar{\phi} : \frac G {G'} \longrightarrow \frac {\phi(G)}{\phi(G')} \leq \frac {H} {\phi(G')},
|
||||
//! $$
|
||||
//! and that the induced homomorphism \\(\bar{\phi}\\) is injective if
|
||||
//! \\( \ker \phi \leq G' \\). In our context, the kernel of
|
||||
//! \\(\theta\\) is \\( \\{(0, \pm 1)\\} \leq \mathcal J[2] \\),
|
||||
//! so \\(\theta\\) gives an isomorphism
|
||||
//! $$
|
||||
//! \frac {\mathcal J} {\mathcal J[2]}
|
||||
//! \cong
|
||||
//! \frac {\theta(\mathcal J)} {\theta(\mathcal J[2])}
|
||||
//! \cong
|
||||
//! \frac {\[2\](\mathcal E)} {\mathcal E[2]}.
|
||||
//! $$
|
||||
//!
|
||||
//! We can use the isomorphism to transfer the encoding of \\(\mathcal
|
||||
//! J / \mathcal J[2] \\) defined above to \\(\[2\](\mathcal E)/\mathcal
|
||||
//! E[2]\\), by encoding the Edwards point \\((x,y)\\) using the Jacobi
|
||||
//! quartic encoding of \\(\theta\^{-1}(x,y)\\).
|
||||
//!
|
||||
//! Since \\(\\# (\[2\](\mathcal E) / \mathcal E[2]) = (\\#\mathcal
|
||||
//! E)/4\\), if \\(\mathcal E\\) has cofactor \\(4\\), we're done.
|
||||
//! Otherwise, if \\(\mathcal E\\) has cofactor \\(8\\), as in the
|
||||
//! Curve25519 case, we use the torquing procedure to lift \\(\mathcal E
|
||||
//! / \mathcal E[4]\\) to \\(\mathcal E / \mathcal E[2]\\), and then
|
||||
//! apply the encoding for \\( \[2\](\mathcal E) / \mathcal E[2] \\).
|
||||
//!
|
||||
//! ## The Ristretto Encoding
|
||||
//!
|
||||
//! We can write the above encoding/decoding procedure concretely (in affine
|
||||
//! coordinates) as follows:
|
||||
//!
|
||||
//! ### Encoding
|
||||
//!
|
||||
//! On input \\( (x,y) \in \[2\](\mathcal E)\\), a representative for a
|
||||
//! coset in \\( \[2\](\mathcal E) / \mathcal E[4] \\):
|
||||
//!
|
||||
//! 1. Check if \\( xy \\) is negative or \\( x = 0 \\); if so, torque
|
||||
//! the point by setting \\( (x,y) \gets (x,y) + P_4 \\), where
|
||||
//! \\(P_4\\) is a \\(4\\)-torsion point.
|
||||
//!
|
||||
//! 2. Check if \\(x\\) is negative or \\( y = -1 \\); if so, set
|
||||
//! \\( (x,y) \gets (x,y) + (0,-1) = (-x, -y) \\).
|
||||
//!
|
||||
//! 3. Compute $$ s = +\sqrt {(-a) \frac {1 - y} {1 + y} }, $$ choosing
|
||||
//! the positive square root.
|
||||
//!
|
||||
//! The output is then the (canonical) byte-encoding of \\(s\\).
|
||||
//!
|
||||
//! If \\(\mathcal E\\) has cofactor \\(4\\), we skip the first step,
|
||||
//! since our input already represents a coset in
|
||||
//! \\( \[2\](\mathcal E) / \mathcal E[2] \\).
|
||||
//!
|
||||
//! To see that this corresponds to the encoding procedure above, notice
|
||||
//! that the first step lifts from \\( \mathcal E / \mathcal E[4] \\) to
|
||||
//! \\(\mathcal E / \mathcal E[2]\\). To understand steps 2 and 3,
|
||||
//! notice that the \\(y\\)-coordinate of \\(\theta(s,t)\\) is
|
||||
//! $$
|
||||
//! y = \frac {1 + as\^2}{1 - as\^2},
|
||||
//! $$
|
||||
//! so that the \\(s\\)-coordinate of \\(\theta\^{-1}(x,y)\\) has
|
||||
//! $$
|
||||
//! s\^2 = (-a)\frac {1-y}{1+y}.
|
||||
//! $$
|
||||
//! Since
|
||||
//! $$
|
||||
//! x = \frac 1 {\sqrt {ad - 1}} \frac {2s} {t},
|
||||
//! $$
|
||||
//! we also have
|
||||
//! $$
|
||||
//! \frac s t = x \frac {\sqrt {ad-1}} 2,
|
||||
//! $$
|
||||
//! so that the sign of \\(s/t\\) is determined by the sign of \\(x\\).
|
||||
//!
|
||||
//! Recall that to choose a canonical representative of \\( (s,t) +
|
||||
//! \mathcal J[2] \\), it's sufficient to make two sign choices: the
|
||||
//! sign of \\(s\\) and the sign of \\(s/t\\). Step 2 determines the
|
||||
//! sign of \\(s/t\\), while step 3 computes \\(s\\) and determines its
|
||||
//! sign (by choosing the positive square root). Finally, the check
|
||||
//! that \\(y \neq -1\\) prevents division-by-zero when encoding the
|
||||
//! identity; it falls out of the optimized formulas below.
|
||||
//!
|
||||
//! ### Decoding
|
||||
//!
|
||||
//! On input `s_bytes`, decoding proceeds as follows:
|
||||
//!
|
||||
//! 1. Decode `s_bytes` to \\(s\\); reject if `s_bytes` is not the
|
||||
//! canonical encoding of \\(s\\).
|
||||
//!
|
||||
//! 2. Check whether \\(s\\) is negative; if so, reject.
|
||||
//!
|
||||
//! 3. Compute
|
||||
//! $$
|
||||
//! y \gets \frac {1 + as\^2}{1 - as\^2}.
|
||||
//! $$
|
||||
//!
|
||||
//! 4. Compute
|
||||
//! $$
|
||||
//! x \gets +\sqrt{ \frac{4s\^2} {ad(1+as\^2)\^2 - (1-as\^2)\^2}},
|
||||
//! $$
|
||||
//! choosing the positive square root, or reject if the square root does
|
||||
//! not exist.
|
||||
//!
|
||||
//! 5. Check whether \\(xy\\) is negative or \\(y = 0\\); if so, reject.
|
||||
//!
|
||||
//! ## Encoding in Extended Coordinates
|
||||
//!
|
||||
//! The formulas above are given in affine coordinates, but the usual
|
||||
//! internal representation is extended twisted Edwards coordinates \\(
|
||||
//! (X:Y:Z:T) \\) with \\( x = X/Z \\), \\(y = Y/Z\\), \\(xy = T/Z \\).
|
||||
//! Selecting the distinguished representative of the coset
|
||||
//! requires the affine coordinates \\( (x,y) \\), and computing \\( s
|
||||
//! \\) requires an inverse square root.
|
||||
//! As inversions are expensive, we'd like to be able to do this
|
||||
//! whole computation with only one inverse square root, by batching
|
||||
//! together the inversion and the inverse square root.
|
||||
//!
|
||||
//! However, it is not obvious how to do this, since the inverse square
|
||||
//! root computation depends on the affine coordinates (which select the
|
||||
//! distinguished representative).
|
||||
//!
|
||||
//! In what follows we consider only the case
|
||||
//! \\(a = -1\\); a similar argument applies to the case \\( a = 1\\).
|
||||
//!
|
||||
//! Since \\(y = Y/Z\\), in extended coordinates the formula for \\(s\\) becomes
|
||||
//! $$
|
||||
//! s = \sqrt{ \frac{ 1 - Y/Z}{1+Y/Z}} = \sqrt{\frac{Z - Y}{Z+Y}}
|
||||
//! = \frac {Z - Y} {\sqrt{Z\^2 - Y\^2}}.
|
||||
//! $$
|
||||
//!
|
||||
//! Here \\( (X:Y:Z:T) \\) are the coordinates of the distinguished
|
||||
//! representative of the coset.
|
||||
//! Write \\( (X\_0 : Y\_0 : Z\_0 : T\_0) \\)
|
||||
//! for the coordinates of the initial representative. Then the
|
||||
//! torquing procedure in step 1 replaces \\( (X\_0 : Y\_0 : Z\_0 :
|
||||
//! T\_0) \\) by \\( (iY\_0 : iX\_0 : Z\_0 : -T\_0) \\). This means we
|
||||
//! want to obtain either
|
||||
//! $$
|
||||
//! \frac {1} { \sqrt{Z\_0\^2 - Y\_0\^2}}
|
||||
//! \quad \text{or} \quad
|
||||
//! \frac {1} { \sqrt{Z\_0\^2 + X\_0\^2}}.
|
||||
//! $$
|
||||
//!
|
||||
//! We can relate these using the identity
|
||||
//! $$
|
||||
//! (a-d)X\^2Y\^2 = (Z\^2 - aX\^2)(Z\^2 - Y\^2),
|
||||
//! $$
|
||||
//! which is valid for all curve points. To see this, recall from the curve equation that
|
||||
//! $$
|
||||
//! -dX\^2Y\^2 = Z\^4 - aZ\^2X\^2 - Z\^2Y\^2,
|
||||
//! $$
|
||||
//! so that
|
||||
//! $$
|
||||
//! (a-d)X\^2Y\^2 = Z\^4 - aZ\^2X\^2 - Z\^2Y\^2 + aX\^2Y\^2 = (Z\^2 - Y\^2)(Z\^2 + X\^2).
|
||||
//! $$
|
||||
//!
|
||||
//! The encoding procedure is as follows:
|
||||
//!
|
||||
//! 1. \\(u\_1 \gets (Z\_0 + Y\_0)(Z\_0 - Y\_0) = Z\_0\^2 - Y\_0\^2 \\)
|
||||
//! 2. \\(u\_2 \gets X\_0 Y\_0 \\)
|
||||
//! 3. \\(I \gets \mathrm{invsqrt}(u\_1 u\_2\^2) = 1/\sqrt{X\_0\^2 Y\_0\^2 (Z\_0\^2 - Y\_0\^2)} \\)
|
||||
//! 4. \\(D\_1 \gets u\_1 I = \sqrt{(Z\_0\^2 - Y\_0\^2)/(X\_0\^2 Y\_0\^2)} \\)
|
||||
//! 5. \\(D\_2 \gets u\_2 I = \pm \sqrt{1/(Z\_0\^2 - Y\_0\^2)} \\)
|
||||
//! 6. \\(Z\_{inv} \gets D\_1 D\_2 T\_0 = (u\_1 u\_2)/(u\_1 u\_2\^2) T\_0 = T\_0 / X\_0 Y\_0 = 1/Z\_0 \\)
|
||||
//! 7. If \\( T\_0 Z\_{inv} = x\_0 y\_0 \\) is negative:
|
||||
//! 1. \\( X \gets iY\_0 \\)
|
||||
//! 2. \\( Y \gets iX\_0 \\)
|
||||
//! 3. \\( D \gets D\_1 / \sqrt{a-d} = 1/\sqrt{Z\_0\^2 + X\_0\^2} \\)
|
||||
//! 8. Otherwise:
|
||||
//! 1. \\( X \gets X\_0 \\)
|
||||
//! 2. \\( Y \gets Y\_0 \\)
|
||||
//! 3. \\( D \gets D\_2 = \pm \sqrt{1/(Z\_0\^2 - Y\_0\^2)} \\)
|
||||
//! 9. If \\( X Z\_{inv} = x \\) is negative, set \\( Y \gets - Y\\)
|
||||
//! 10. Compute \\( s \gets (Z - Y) D = (Z - Y) / \sqrt{Z\^2 - Y\^2} \\) and return.
|
||||
//!
|
||||
//! ## Decoding to Extended Coordinates
|
||||
//!
|
||||
//! ## Equality Testing
|
||||
//!
|
||||
//! ## Elligator
|
||||
//!
|
||||
//! ## The Double-Ristretto Encoding
|
||||
//!
|
||||
//! It's possible to do batch encoding of \\( [2]P \\) using the dual
|
||||
//! isogeny \\(\hat{\theta}\\). Defer this for now.
|
||||
//!
|
||||
//! ## ???
|
||||
|
||||
}
|
||||
|
||||
use core::fmt::Debug;
|
||||
|
|
@ -1135,6 +833,16 @@ pub fn multiscalar_mul<I, J>(scalars: I, points: J) -> RistrettoPoint
|
|||
|
||||
/// A precomputed table of multiples of a basepoint, used to accelerate
|
||||
/// scalar multiplication.
|
||||
///
|
||||
/// A precomputed table of multiples of the Ristretto basepoint is
|
||||
/// available in the `constants` module:
|
||||
/// ```
|
||||
/// use curve25519_dalek::constants;
|
||||
/// use curve25519_dalek::scalar::Scalar;
|
||||
///
|
||||
/// let a = Scalar::from_u64(87329482);
|
||||
/// let P = &a * &constants::RISTRETTO_BASEPOINT_TABLE;
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct RistrettoBasepointTable(pub(crate) EdwardsBasepointTable);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue