Skip to content

Commit 7377a7e

Browse files
authoredJan 8, 2025··
opt(ecc): jacobian doubling improvement (#510)
1 parent 5d66b52 commit 7377a7e

File tree

2 files changed

+37
-44
lines changed

2 files changed

+37
-44
lines changed
 

‎constantine/math/elliptic/ec_shortweierstrass_jacobian.md

+5
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,8 @@ we could use this formula instead:
222222
| Y₃ = R*(V-X₃)-2*S₁*J | Y₃ = M*(S-X₃)-8*YY² | | |
223223
| Z₃ = ((Z₁+Z₂)²-Z₁Z₁-Z₂Z₂)*H | Z₃ = (Y₁+Z₁)² - YY - ZZ | | |
224224
```
225+
226+
## References
227+
228+
- https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
229+
- Bos, Costello, Longa, Naehrig, 2014: https://eprint.iacr.org/2014/130.pdf

‎constantine/math/elliptic/ec_shortweierstrass_jacobian.nim

+32-44
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,36 @@ func mixedSum*[F; G: static Subgroup](
561561

562562
r = o
563563

564+
func dbl_1998_cmo_rescaled_a0_impl[F; G: static Subgroup](r: var EC_ShortW_Jac[F, G], P: EC_ShortW_Jac[F, G]) {.inline.} =
565+
static: doAssert F.Name.getCoefA() == 0
566+
# "dbl-1998-cmo" doubling formula - https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-1998-cmo
567+
# rescaled by 1/2, 1/4, 1/8 (inspiration from Bos et al https://eprint.iacr.org/2014/130.pdf)
568+
# See [./ec_shortweierstrass_jacobian.md](./ec_shortweierstrass_jacobian.md)
569+
#
570+
# Cost: 3M + 4S + 3add + 1*2 + 1*3 + 1half
571+
#
572+
# YY = Y₁²
573+
# M = 3X₁²/2
574+
# S = X₁*YY
575+
# X₃ = M²-2*S
576+
# Y₃ = M*(S-X₃)-YY²
577+
# Z₃ = Y₁*Z₁
578+
var Y {.noInit.}, M {.noInit.}, S {.noInit.}: F
579+
Y.square(P.y)
580+
M.square(P.x)
581+
M *= 3
582+
M.div2()
583+
S.prod(P.x, Y)
584+
Y.square()
585+
586+
r.z.prod(P.z, P.y) # Z₃ = Y₁*Z₁, no aliasing
587+
r.x.square(M) # X₃ = M²
588+
r.x -= S # X₃ = M²-S
589+
r.x -= S # X₃ = M²-2*S
590+
r.y.diff(S, r.x) # Y₃ = S-X₃
591+
r.y *= M # Y₃ = M*(S-X₃)
592+
r.y -= Y # Y₃ = M*(S-X₃)-YY²
593+
564594
func double*[F; G: static Subgroup](r: var EC_ShortW_Jac[F, G], P: EC_ShortW_Jac[F, G]) {.meter.} =
565595
## Elliptic curve point doubling for Short Weierstrass curves in projective coordinate
566596
##
@@ -575,49 +605,7 @@ func double*[F; G: static Subgroup](r: var EC_ShortW_Jac[F, G], P: EC_ShortW_Jac
575605
##
576606
## Implementation is constant-time.
577607
when F.Name.getCoefA() == 0:
578-
# "dbl-2009-l" doubling formula - https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
579-
#
580-
# Cost: 2M + 5S + 6add + 3*2 + 1*3 + 1*8.
581-
# Source: 2009.04.01 Lange.
582-
# Explicit formulas:
583-
#
584-
# A = X₁²
585-
# B = Y₁²
586-
# C = B²
587-
# D = 2*((X₁+B)²-A-C)
588-
# E = 3*A
589-
# F = E²
590-
# X₃ = F-2*D
591-
# Y₃ = E*(D-X₃)-8*C
592-
# Z₃ = 2*Y₁*Z₁
593-
#
594-
var A {.noInit.}, B{.noInit.}, C {.noInit.}: F
595-
A.square(P.x)
596-
B.square(P.y)
597-
C.square(B)
598-
B += P.x
599-
# aliasing: we don't use P.x anymore
600-
601-
B.square()
602-
B -= A
603-
B -= C
604-
B.double() # D = 2*((X₁+B)²-A-C)
605-
A *= 3 # E = 3*A
606-
r.x.square(A) # F = E²
607-
608-
r.x -= B
609-
r.x -= B # X₃ = F-2*D
610-
611-
B -= r.x # (D-X₃)
612-
A *= B # E*(D-X₃)
613-
C *= 8
614-
615-
r.z.prod(P.z, P.y)
616-
r.z.double() # Z₃ = 2*Y₁*Z₁
617-
# aliasing: we don't use P.y, P.z anymore
618-
619-
r.y.diff(A, C) # Y₃ = E*(D-X₃)-8*C
620-
608+
dbl_1998_cmo_rescaled_a0_impl(r, P)
621609
else:
622610
{.error: "Not implemented.".}
623611

@@ -741,7 +729,7 @@ func sum_vartime*[F; G: static Subgroup](
741729
var U {.noInit.}, S{.noInit.}, H{.noInit.}, R{.noInit.}: F
742730

743731
if not isPz1: # case Z₁ != 1
744-
R.square(p.z, lazyReduce = true) # Z₁Z₁ = Z₁²
732+
R.square(p.z, lazyReduce = true) # Z₁Z₁ = Z₁²
745733
if isQz1: # case Z₂ = 1
746734
U = p.x # U₁ = X₁*Z₂Z₂
747735
if isPz1: # case Z₁ = Z₂ = 1

0 commit comments

Comments
 (0)
Please sign in to comment.