refactor(meshlink): split Ed25519 fallback into field and point arithmetic units - #135
Merged
trancee merged 1 commit intoJul 15, 2026
Conversation
…metic units Implements #125 by extracting the RFC 8032/TweetNaCl radix-2^16 field arithmetic and Edwards point arithmetic into dedicated internal classes: - Curve25519FieldArithmetic - Curve25519PointArithmetic (+ Point/PointScratch) Ed25519Fallback now stays focused on signing/verification/key generation, composing the two extracted units while preserving: - exact constant-time vs variable-time path distinctions - byte-for-byte signing/verification behavior - ExpandedPrivateKey WeakHashMap cache semantics keyed by ByteArray identity No algorithmic changes were made: arithmetic code was moved verbatim. Regenerated detekt baseline for androidMain only. This is re-keying from file extraction (MagicNumber/TooManyFunctions/VariableNaming/ UnsafeCallOnNullableType IDs moved from Ed25519Fallback.kt to the new files) plus removal of stale L2capFrameBuffer baseline IDs no longer present in current code. Verification: - allTests: 1239/1239 pass (unchanged) - Ed25519/Wycheproof tests unchanged: Ed25519FallbackTest 6/6, WycheproofRegressionTest 5/5 on both JVM+AndroidHost, AndroidCryptoPolicyConformanceTest 1/1, MeshRuntimeAndroidCryptoTest 1/1 - apiCheck: zero .api diff - detektAll: clean - ktfmtFormat: clean - clean rebuild re-check: rm -rf meshlink/build && allTests+apiCheck+detektAll pass
trancee
deleted the
refactor/split-ed25519-fallback-into-field-point-signing
branch
July 15, 2026 19:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements #125.
Ed25519Fallback.kt(930 lines, a single class mixingfield arithmetic, point arithmetic, comb-table machinery, and the public
signing API) is split into three files:
Curve25519FieldArithmetic.kt(new) —LongArray-based field operations(
add/subtract/multiply/square/invert/power2523/carry, etc.)Curve25519PointArithmetic.kt(new) —Point/PointScratchoperations,comb-table building, both the constant-time
scalarBaseand thedeliberately variable-time
windowedScalarMultiplyPublicpaths (kepttogether since both are "point arithmetic," with their constant-time vs.
variable-time rationale comments traveling with them)
Ed25519Fallback.kt(reduced, 930 → 290 lines) — the publicsign/verify/generateKeyPair/deriveKeyPairAPI, composing the twoextracted classes, retaining the
ExpandedPrivateKeyWeakHashMapcacheunchanged
This is a cryptographic primitive used on real devices (the pure-Kotlin
Ed25519 fallback for platforms/OEM JCA implementations without native
Ed25519 support), so this was held to a materially higher verification bar
than the rest of this refactor series — see below.
Verification (elevated rigor given the crypto stakes)
before any change, then confirmed byte-for-byte identical pass
counts after:
Ed25519FallbackTest6/6,WycheproofRegressionTest5/5(JVM) + 5/5 (Android host),
AndroidCryptoPolicyConformanceTest1/1,MeshRuntimeAndroidCryptoTest1/1 — all unchanged../gradlew :meshlink:allTests— 1239/1239 passing throughout (unchangedtotal count)
./gradlew :meshlink:apiCheck— zero.apidiff (all touched typesinternal)./gradlew :meshlink:detektAll— clean after baseline re-keying (findingtypes and counts unchanged except an expected
+1 TooManyFunctionsfrom the two new classes each independently tripping that rule; verified
via a finding-type/count diff, not just a passing build)
./gradlew :meshlink:ktfmtFormat— clean(
rm -rf meshlink/build) given the correctness stakesAn independent
/code-reviewpass went further: it extracted the fulloriginal file at
mainand did a character-by-character diff of everyone of the 39 original functions against its new location, confirming
byte-for-byte identical arithmetic bodies, identical constants, and that
every constant-time/variable-time rationale comment was preserved verbatim
(not paraphrased, not dropped). No algorithmic change, no correctness bug
found in the original code during the extraction.
Residual notes (not blockers)
constantTimeEqualsnow exists as two small identical private copies(
Ed25519Fallback.kt,Curve25519PointArithmetic.kt) — trivial, flaggedby review as a candidate for a future tiny consolidation, not worth
blocking this PR over.
unrelated
L2capFrameBuffer.ktentries (that file isn't touched by thisdiff) — an unavoidable side effect of baseline regeneration, disclosed
for reviewer awareness.
PureX25519.kt(explicitly out of scope per Split Ed25519Fallback.kt into field-arithmetic / point-arithmetic / signing-API files #125) was not touched.Review
Passed
/code-review(Standards + Spec axes), with the Standards passspecifically instructed to distrust summary claims and verify the moved
arithmetic byte-for-byte given this is a cryptographic primitive. No
blockers on either axis.
Closes #125