Extracting an Inverse Square Root
Implementing Ristretto requires computing (inverse) square roots. Ed25519 implementations compute square roots as part of the Ed25519 decompression functionality, but this is often inlined into the decompression formulas.
This page explains how to extract an inverse square root function
suitable for use with ristretto255
from an implementation of Ed25519.
Computing \(\sqrt{u/v}\) or \(\sqrt{iu/v}\) simultaneously
Let \(p = 2^{255} -19\). On input field elements \(u, v\), set \[ r = (uv^3)(uv^7)^{(p-5)/8}. \]
There are four possibilities when \(u,v\) are nonzero:
- If \(vr^2 = u\), then \( s \gets r \) is a square root of \(u/v\).
- If \(vr^2 = -u\), then \( s \gets ir \) is a square root of \(u/v\).
- If \(vr^2 = iu\), then \( s \gets r \) is a square root of \(iu/v\).
- If \(vr^2 = -iu\), then \( s \gets ir \) is a square root of \(iu/v\).
When \(u = 0\), \(r = 0\) and the first condition \(vr^2 = u\) is satisfied. When \(v = 0\) and \(u \neq 0\), \(r = 0\) and none of the conditions are satisfied. This allows computing the nonnegative square root of either \( \sqrt{u/v} \) or \(\sqrt{iu/v}\) as follows:
- \(r \gets (uv^3)(uv^7)^{(p-5)/8}\).
- \(c \gets vr^2\).
correct_sign_sqrt
\(\gets (c = u)\).flipped_sign_sqrt
\(\gets (c = -u)\).flipped_sign_sqrt_i
\(\gets (c = -iu)\).- \( r \gets ir \) if
flipped_sign_sqrt | flipped_sign_sqrt_i
. - \( r \gets -r \) if \(r\) is negative.
- Return
(correct_sign_sqrt | flipped_sign_sqrt, r)
.
The first part of the return value signals whether \(u/v\) was square, and the second part contains a square root. Specifically, it returns
( true, +sqrt(u/v))
if \(v\) is nonzero and \(u/v\) is square;( true, zero)
if \(u\) is zero;(false, zero)
if \(v\) is zero and \(u\) is nonzero;(false, +sqrt(i*u/v))
if \(u/v\) is nonsquare (so \(iu/v\) is square).
The computation of \(x^{(p-5)/8}\) is already required for Ed25519
decoding, so an Ed25519 implementation can obtain a sqrt_ratio_i
function by refactoring the computation of \(r\) out of the decoding
function and using sqrt_ratio_i
to perform decoding.
If the equality checks in (3), (4), (5) are implemented in constant-time and the conditional assignments in (6), (7) are also implemented in constant-time, then the entire computation can be done in constant time.