Commit 06e0835f authored by Niels Möller's avatar Niels Möller

Describe point addition and decompression.

parent c87b56a0
......@@ -97,7 +97,7 @@
<t>B generator of the group or subgroup of interest</t>
<t>n B B added to itselt n times.</t>
<t>n B B added to itself n times.</t>
<t>h_i the i'th bit of h</t>
......@@ -153,8 +153,6 @@ x3 = -------------------, y3 = -------------------
the generic EdDSA algorithm is given here.</t>
<t>EdDSA has seven parameters:
<!-- FIXME: Less general, make q a prime, and drop encoding,
fixing little-endian. -->
<list style="numbers">
<t>an integer b >= 10.</t>
<t>a cryptographic hash function H producing 2b-bit outputs.</t>
......@@ -234,6 +232,119 @@ x3 = -------------------, y3 = -------------------
(15112221349535400772501151409588531511454012693041857206046113283949847762202,
46316835694926478169428394003475163141307993866256225615783033603165251855960).
</t>
<section title="Modular arithmetic">
<t>For advise on how to implement arithmetic modulo p = 2^255
- 1 efficiently and securely, see <xref
target="CURVE25519">Curve25519</xref>. For
inversion modulo p, it is recommended to use the identity x^-1
= x^(p-2) (mod p).</t>
<t>For point decoding or "decompression", square roots modulo
p are needed. They can be computed using the Tonelli-Shanks
algorithm, or the special case for p = 5 (mod 8). To find a
square root of a, first compute the candidate root x =
a^((p+3)/8) (mod p). Then there are three cases:
<list>
<t> x^2 = a (mod p). Then x is a square root.</t>
<t> x^2 = -a (mod p). Then 2^((p-1)/4) x is a square root.</t>
<t> a is not a square modulo p.</t>
</list>
</t>
</section>
<section title="Encoding">
<t>All values are coded as octet strings, and integers are
coded using little endian convention. I.e., a 32-octet string
h h[0],...h[31] represents the integer h[0] + 2^8 h[1] + ... +
2^248 h[31].</t>
<t>A curve point (x,y), with coordiantes in the range 0 &lt;=
x,y &lt; p, is coded as follows. First encode the y-coordinate
as a little-endian string of 32 octets. The most significant
bit of the final octet is always zero. To form the encoding of
the point, copy the least significant bit of the x-coordinate
to the most significant bit of the final octet.</t>
</section>
<section title="Decoding">
<t>Decoding a point, given as a 32-octet string, is a little
more complicated.
<list style="numbers">
<t>First interpret the string as an integer in little-endian
representation. Bit 255 of this number is the least
significant bit of the x-coordinate, and denote this value
x_0. The y-coordinate is recovered simply by clearing this
bit. If the resulting value is &gt;= p, decoding fails.</t>
<t>To recover the x coordinate, the curve equation implies x^2
= (y^2 - 1) / (d y^2 + 1) (mod p). Since d is a non-square and
-1 is a square, the numerator, (d y^2 + 1), is always
invertible modulo p. Let u = y^2 - 1 and v = d y^2 + 1. To
compute the square root of (u/v), the first step is to compute
the candidate root x = (u/v)^((p+3)/8). This can be done using
the following trick, to use a single modular powering for both
the inversion of v and the square root:
<figure>
<artwork>
(p+3)/8 3 (p-5)/8
x = (u/v) = u v (u v^7) (mod p)
</artwork>
</figure></t>
<t>Again, there are three cases:
<list>
<t>If v x^2 = u (mod p), x is a square root.</t>
<t>If v x^2 = -u (mod p), set x &lt;-- x 2^((p-1)/4),
which is a square root.</t>
<t>Otherwise, no square root exists modulo p, and decoding
fails.</t>
</list>
</t>
<t>Finally, use the x_0 bit to select the right square root.
If x = 0, and x_0 = 1, decoding fails. Otherwise, if x_0 !=
x mod 2, set x &lt;-- p - x. Return the decoded point
(x,y).</t>
</list>
</t>
</section>
<section title="Point addition">
<t>For point addition, the following method is recommended.
A point (x,y) is represented in extended homogeneous
coordinates (X, Y, Z, T), with x = X/Z, y = Y/Z, x y = T/Z.
</t>
<t>The following formulas for adding two points, (x3,y3) =
(x1,y1)+(x2,y2) are described in <xref
target="Edwards-revisited"/>, section 3.1. They are strongly
unified, i.e., they work for any pair of valid input points.
<!-- FIXME: Also refer to
http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3
? -->
</t>
<figure>
<artwork>
A = (Y1-X1)*(Y2-X2)
B = (Y1+X1)*(Y2+X2)
C = T1*2*d*T2
D = Z1*2*Z2
E = B-A
F = D-C
G = D+C
H = B+A
X3 = E*F
Y3 = G*H
T3 = E*H
Z3 = F*G
</artwork>
</figure>
</section>
<section title="Key Generation">
<t>The secret is 32 octets (256 bits, corresponding to b) of
......@@ -273,46 +384,55 @@ x3 = -------------------, y3 = -------------------
</section>
<section title="Sign">
<t>Hash the secret key, 32-octets, using SHA-512. Let h denote
the resulting digest. Construct the secret scalar a from the
first half of the digest, and the corresponding public key A,
as described in the previous section. Let prefix denote the
second half of the hash digest, h[32],...,h[63].</t>
<t>Compute SHA-512(prefix || M), where M is the message to be
signed. Interpret the 64-octet digest as a little-endian
integer r.</t>
<t>Compute the point rB. For efficiency, do this by first
reducing r modulo q, the group order of B. Let the string R be
the encoding of this point.</t>
<t>Compute SHA512(R || A || M), and interpret the 64-octet
digest as a little-endian integer k.</t>
<t>Compute s = (r + k a) mod q. For efficiency, again reduce k
modulo q first.</t>
<t>Form the signature of the concatenation of R (32 octets) and the
little-endian encoding of s (32 octets, three most significant
bits of the final octets always zero).</t>
<t>The imputs to the signing procedure is the secret key, a
32-octet string, and a message M of arbitrary size.
<list style="numbers">
<t>Hash the secret key, 32-octets, using SHA-512. Let h
denote the resulting digest. Construct the secret scalar a
from the first half of the digest, and the corresponding
public key A, as described in the previous section. Let
prefix denote the second half of the hash digest,
h[32],...,h[63].</t>
<t>Compute SHA-512(prefix || M), where M is the message to
be signed. Interpret the 64-octet digest as a little-endian
integer r.</t>
<t>Compute the point rB. For efficiency, do this by first
reducing r modulo q, the group order of B. Let the string R
be the encoding of this point.</t>
<t>Compute SHA512(R || A || M), and interpret the 64-octet
digest as a little-endian integer k.</t>
<t>Compute s = (r + k a) mod q. For efficiency, again reduce
k modulo q first.</t>
<t>Form the signature of the concatenation of R (32 octets)
and the little-endian encoding of s (32 octets, three most
significant bits of the final octets always zero).</t>
</list>
</t>
</section>
<section title="Verify">
<t>To verify a signature on a message M, first split the
signature into two 32-octet halves. Decode the first half as a
point R, and the second half as an integer s, in the range 0
&lt;= s &lt; q. If the decoding fails, the signature is invalid.
<!-- FIXME: Should have a separate section on point
decompression, including some hints on how to do it
efficiently. -->
<t>
<list style="numbers">
<t>To verify a signature on a message M, first split the
signature into two 32-octet halves. Decode the first half as
a point R, and the second half as an integer s, in the range
0 &lt;= s &lt; q. If the decoding fails, the signature is
invalid.</t>
<t>Compute SHA512(R || A || M), and interpret the 64-octet
digest as a little-endian integer k.</t>
<t>Check the group equation 8s B = 8 R + 8k A. It's
sufficient, but not required, to instead check s B = R + k
A.</t>
</list>
</t>
<t>Compute SHA512(R || A || M), and interpret the 64-octet
digest as a little-endian integer k.</t>
<t>Check the group equation 8s B = 8 R + 8k A. It's
sufficient, but not required, to instead check s B = R + k
A.</t>.
</section>
<section title="Python illustration">
<t>The rest of this section describes how Ed25519 can be
......@@ -724,7 +844,7 @@ d25bf5f0595bbe24655141438e7a100b
the secret key.
</t>
<t> To make an implementation side-channel silent in this way,
the modulo q arithmetic must not use any data-dependent
the modulo p arithmetic must not use any data-dependent
branches, e.g., related to carry propagation. <!--FIXME: Refer
to curve25519 paper.--> Side channel-silent point addition is
straight-forward, thanks to the unified formulas.
......@@ -733,8 +853,8 @@ d25bf5f0595bbe24655141438e7a100b
needs some additional effort to implement in a side-channel
silent manner. One simple approach is to implement a
side-channel silent conditional assignment, and use together
with binary algorithm to examine one bit of the integer at a
time.
with the binary algorithm to examine one bit of the integer at
a time.
</t>
<t>Note that the example implementation in this document does
not attempt to be side-channel silent.</t>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment