Skip to content

Commit 4e3d735

Browse files
committed
Additional JavaDoc, relates to github issue #735
1 parent 1867285 commit 4e3d735

4 files changed

Lines changed: 153 additions & 0 deletions

File tree

core/src/main/java/org/bouncycastle/math/ec/rfc7748/X25519.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,47 @@
55
import org.bouncycastle.math.ec.rfc8032.Ed25519;
66
import org.bouncycastle.util.Arrays;
77

8+
/**
9+
* A low-level implementation of X25519 (RFC 7748).
10+
* <p>
11+
* <b>Algorithm map.</b>
12+
* <ul>
13+
* <li>{@link #generatePrivateKey} &mdash; 32 random bytes followed by
14+
* {@link #clampPrivateKey} (RFC 7748 sec. 5 clamping: clear bits
15+
* 254..255 then 0..2, set bit 254).</li>
16+
* <li>{@link #generatePublicKey} / {@link #scalarMultBase} &mdash;
17+
* computed as {@code k * B} on the birationally-equivalent
18+
* {@code edwards25519} curve via
19+
* {@link Ed25519#scalarMultBaseYZ(Friend, byte[], int, int[], int[])}
20+
* (a signed multi-comb in extended Edwards coordinates), then
21+
* converted to the Curve25519 {@code u} coordinate using the RFC
22+
* 7748 sec. 4.1 birational map {@code u = (1 + Y) / (1 - Y)}
23+
* where {@code Y = y / z}.</li>
24+
* <li>{@link #scalarMult} (key agreement) &mdash; Montgomery ladder on
25+
* XZ-only projective coordinates per RFC 7748 sec. 5, with
26+
* per-bit constant-time {@code cswap}; the
27+
* {@code A24 = (A + 2) / 4} curve constant is precomputed from
28+
* {@code A = 486662}. The trailing three doublings cancel the
29+
* cofactor introduced by the lowest cleared scalar bits.</li>
30+
* <li>{@link #calculateAgreement} &mdash; {@link #scalarMult} followed
31+
* by the RFC 7748 sec. 6.1 all-zero rejection.</li>
32+
* </ul>
33+
* <p>
34+
* <b>Side-channel scope.</b> Secret-scalar operations are written to be
35+
* constant-time at the Java level: the Montgomery ladder in
36+
* {@link #scalarMult} performs identical field operations per bit with
37+
* branchless {@code cswap}; {@link #scalarMultBase} routes through the
38+
* Ed25519 signed-comb, which walks all precomputed entries with mask-based
39+
* {@code cmov} rather than a secret-indexed array load and applies
40+
* conditional negation by XOR-with-mask; the final modular inverse uses
41+
* constant-time {@code Mod.modOddInverse}. The all-zero rejection in
42+
* {@link #calculateAgreement} runs an OR-accumulator and only leaks the
43+
* RFC-mandated public rejection criterion. This is sufficient against a
44+
* remote network timing attacker but is not a substitute for a constant-time
45+
* native implementation against a co-located cache-line-resolution
46+
* adversary &mdash; JVM-level timing variance from JIT, GC and cache
47+
* eviction is not addressable in pure Java.
48+
*/
849
public abstract class X25519
950
{
1051
public static class Friend
@@ -165,6 +206,9 @@ public static void scalarMultBase(byte[] k, int kOff, byte[] r, int rOff)
165206

166207
Ed25519.scalarMultBaseYZ(Friend.INSTANCE, k, kOff, y, z);
167208

209+
// Birational map edwards25519 -> Curve25519 (RFC 7748 sec. 4.1):
210+
// u = (1 + Y) / (1 - Y), where Y = y / z.
211+
// Computed projectively: y' := z + y, z' := z - y, then u = y' / z'.
168212
F.apm(z, y, y, z);
169213

170214
F.inv(z, z);

core/src/main/java/org/bouncycastle/math/ec/rfc7748/X448.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,47 @@
55
import org.bouncycastle.math.ec.rfc8032.Ed448;
66
import org.bouncycastle.util.Arrays;
77

8+
/**
9+
* A low-level implementation of X448 (RFC 7748).
10+
* <p>
11+
* <b>Algorithm map.</b>
12+
* <ul>
13+
* <li>{@link #generatePrivateKey} &mdash; 56 random bytes followed by
14+
* {@link #clampPrivateKey} (RFC 7748 sec. 5 clamping: clear bits
15+
* 0..1, set bit 447).</li>
16+
* <li>{@link #generatePublicKey} / {@link #scalarMultBase} &mdash;
17+
* computed as {@code k * B} on the birationally-equivalent
18+
* {@code edwards448} curve via
19+
* {@link Ed448#scalarMultBaseXY(Friend, byte[], int, int[], int[])}
20+
* (a signed multi-comb in projective Edwards coordinates), then
21+
* converted to the Curve448 {@code u} coordinate using the RFC
22+
* 7748 sec. 4.2 / errata 5568 birational map
23+
* {@code u = (y / x)^2}.</li>
24+
* <li>{@link #scalarMult} (key agreement) &mdash; Montgomery ladder on
25+
* XZ-only projective coordinates per RFC 7748 sec. 5, with
26+
* per-bit constant-time {@code cswap}; the
27+
* {@code A24 = (A + 2) / 4} curve constant is precomputed from
28+
* {@code A = 156326}. The trailing two doublings cancel the
29+
* cofactor introduced by the lowest cleared scalar bits.</li>
30+
* <li>{@link #calculateAgreement} &mdash; {@link #scalarMult} followed
31+
* by the RFC 7748 sec. 6.2 all-zero rejection.</li>
32+
* </ul>
33+
* <p>
34+
* <b>Side-channel scope.</b> Secret-scalar operations are written to be
35+
* constant-time at the Java level: the Montgomery ladder in
36+
* {@link #scalarMult} performs identical field operations per bit with
37+
* branchless {@code cswap}; {@link #scalarMultBase} routes through the
38+
* Ed448 signed-comb, which walks all precomputed entries with mask-based
39+
* {@code cmov} rather than a secret-indexed array load and applies
40+
* conditional negation by XOR-with-mask; the final modular inverse uses
41+
* constant-time {@code Mod.modOddInverse}. The all-zero rejection in
42+
* {@link #calculateAgreement} runs an OR-accumulator and only leaks the
43+
* RFC-mandated public rejection criterion. This is sufficient against a
44+
* remote network timing attacker but is not a substitute for a constant-time
45+
* native implementation against a co-located cache-line-resolution
46+
* adversary &mdash; JVM-level timing variance from JIT, GC and cache
47+
* eviction is not addressable in pure Java.
48+
*/
849
public abstract class X448
950
{
1051
public static class Friend
@@ -173,6 +214,9 @@ public static void scalarMultBase(byte[] k, int kOff, byte[] r, int rOff)
173214

174215
Ed448.scalarMultBaseXY(Friend.INSTANCE, k, kOff, x, y);
175216

217+
// Birational map edwards448 -> Curve448 (RFC 7748 sec. 4.2 /
218+
// errata 5568): u = (y / x)^2. The Ed448 comb returns the
219+
// affine Edwards (x, y); invert x and square the ratio.
176220
F.inv(x, x);
177221
F.mul(x, y, x);
178222
F.sqr(x, x);

core/src/main/java/org/bouncycastle/math/ec/rfc8032/Ed25519.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,38 @@
2020
* "extensible coordinates" (for accumulators). Standard
2121
* <a href="https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html">extended coordinates</a> are used
2222
* during precomputations, needing only a single extra point addition formula.
23+
* <p>
24+
* <b>Algorithm map.</b>
25+
* <ul>
26+
* <li>Key generation &mdash; {@code generatePrivateKey} returns a 32-byte seed;
27+
* {@code generatePublicKey} (via {@code scalarMultBaseEncoded}) computes
28+
* {@code A = s * B} where {@code s} is the SHA-512-expanded clamped secret scalar (RFC 8032
29+
* sec. 5.1.5), using the constant-time signed multi-comb {@code scalarMultBase}.</li>
30+
* <li>Signing &mdash; {@code sign} computes {@code R = r * B} (signed multi-comb) where
31+
* {@code r = SHA-512(prefix || M) mod L}, then {@code S = (r + k * s) mod L} (RFC 8032
32+
* sec. 5.1.6). Reduction modulo {@code L} uses {@code Scalar25519.reduce512} (Barrett-style,
33+
* straight-line). No variable-base scalar multiplication is performed.</li>
34+
* <li>Verification &mdash; {@code verify} runs the small-multiple basis-reduction trick of
35+
* <a href="https://ia.cr/2003/116">Antipa-Brown-Menezes-Struik-Vanstone</a> via
36+
* {@code Scalar25519.reduceBasisVar} then evaluates the combined relation with Strauss-Shamir's
37+
* trick in {@code scalarMultStraus128Var}. Both routines are deliberately variable-time and
38+
* operate only on public material (signature, message, public key).</li>
39+
* <li>Coordinates &mdash; the precomputed base-point comb table lives in
40+
* <a href="https://ia.cr/2012/309">half-Niels</a> form; signing-side accumulators use extensible
41+
* (twisted Edwards) coordinates so each step needs only one extra point-addition formula.
42+
* Verification re-uses projective extended coordinates throughout.</li>
43+
* </ul>
44+
* <p>
45+
* <b>Side-channel scope.</b> The signing path (which operates on the secret seed, the derived secret
46+
* scalar, and the secret per-message nonce) is written to be constant-time at the Java level: the comb
47+
* {@code scalarMultBase} walks all precomputed entries via mask-based {@code cmov} rather than a
48+
* secret-indexed array load, conditional sign application uses XOR-with-mask {@code cnegate}, scalar
49+
* recoding via {@code toSignedDigits} uses mask-driven {@code caddTo}, and {@code Scalar25519.reduce512}
50+
* is fully unrolled straight-line arithmetic. This is sufficient against a remote network timing attacker
51+
* but is not a substitute for a constant-time native implementation against a co-located
52+
* cache-line-resolution adversary &mdash; JVM-level timing variance from JIT, GC and cache eviction is not
53+
* addressable in pure Java. Verification routines (those suffixed {@code Var}) are deliberately
54+
* variable-time and operate only on public material.
2355
*/
2456
public abstract class Ed25519
2557
{

core/src/main/java/org/bouncycastle/math/ec/rfc8032/Ed448.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,39 @@
1717
* <a href="https://ia.cr/2012/309">Mike Hamburg, "Fast and compact elliptic-curve cryptography"</a>. Standard
1818
* <a href="https://hyperelliptic.org/EFD/g1p/auto-edwards-projective.html">projective coordinates</a> are
1919
* used for most point arithmetic.
20+
* <p>
21+
* <b>Algorithm map.</b>
22+
* <ul>
23+
* <li>Key generation &mdash; {@code generatePrivateKey} returns a 57-byte seed;
24+
* {@code generatePublicKey} (via {@code scalarMultBaseEncoded}) computes
25+
* {@code A = s * B} where {@code s} is the SHAKE-256-expanded clamped secret scalar
26+
* (RFC 8032 sec. 5.2.5), using the constant-time signed multi-comb {@code scalarMultBase}.</li>
27+
* <li>Signing &mdash; {@code sign} computes {@code R = r * B} (signed multi-comb) where
28+
* {@code r = SHAKE-256(dom4(F, C) || prefix || M, 912 bits) mod L}, then
29+
* {@code S = (r + k * s) mod L} (RFC 8032 sec. 5.2.6). Reduction modulo {@code L} uses
30+
* {@code Scalar448.reduce912} (Barrett-style, straight-line). No variable-base scalar
31+
* multiplication is performed.</li>
32+
* <li>Verification &mdash; {@code verify} runs the small-multiple basis-reduction trick of
33+
* <a href="https://ia.cr/2003/116">Antipa-Brown-Menezes-Struik-Vanstone</a> via
34+
* {@code Scalar448.reduceBasisVar} then evaluates the combined relation with Strauss-Shamir's
35+
* trick in {@code scalarMultStraus128Var}. Both routines are deliberately variable-time and
36+
* operate only on public material (signature, message, public key).</li>
37+
* <li>Coordinates &mdash; the precomputed base-point comb table lives in
38+
* <a href="https://hyperelliptic.org/EFD/g1p/auto-edwards-projective.html">affine</a> form
39+
* (matching {@code PointAffine} in {@code pointLookup}); the signing-side accumulator is
40+
* projective (X : Y : Z). Verification uses projective coordinates throughout.</li>
41+
* </ul>
42+
* <p>
43+
* <b>Side-channel scope.</b> The signing path (which operates on the secret seed, the derived secret
44+
* scalar, and the secret per-message nonce) is written to be constant-time at the Java level: the comb
45+
* {@code scalarMultBase} walks all precomputed entries via mask-based {@code cmov} rather than a
46+
* secret-indexed array load, conditional sign application uses XOR-with-mask {@code cnegate}, scalar
47+
* recoding via {@code toSignedDigits} uses mask-driven {@code caddTo}, and {@code Scalar448.reduce912}
48+
* is fully unrolled straight-line arithmetic. This is sufficient against a remote network timing attacker
49+
* but is not a substitute for a constant-time native implementation against a co-located
50+
* cache-line-resolution adversary &mdash; JVM-level timing variance from JIT, GC and cache eviction is not
51+
* addressable in pure Java. Verification routines (those suffixed {@code Var}) are deliberately
52+
* variable-time and operate only on public material.
2053
*/
2154
public abstract class Ed448
2255
{

0 commit comments

Comments
 (0)