![JAR search and dependency download from the Maven repository](/logo.png)
vendor.github.com.cloudflare.circl.ecc.p384.point.go Maven / Gradle / Ivy
The newest version!
//go:build (!noasm && arm64) || (!noasm && amd64)
// +build !noasm,arm64 !noasm,amd64
package p384
import (
"fmt"
"math/big"
)
// affinePoint represents an affine point of the curve. The point at
// infinity is (0,0) leveraging that it is not an affine point.
type affinePoint struct{ x, y fp384 }
func newAffinePoint(x, y *big.Int) *affinePoint {
var P affinePoint
P.x.SetBigInt(x)
P.y.SetBigInt(y)
montEncode(&P.x, &P.x)
montEncode(&P.y, &P.y)
return &P
}
func zeroPoint() *affinePoint { return &affinePoint{} }
func (ap affinePoint) String() string {
if ap.isZero() {
return "inf"
}
return fmt.Sprintf("x: %v\ny: %v", ap.x, ap.y)
}
func (ap *affinePoint) isZero() bool {
zero := fp384{}
return ap.x == zero && ap.y == zero
}
func (ap *affinePoint) neg() { fp384Neg(&ap.y, &ap.y) }
func (ap *affinePoint) toInt() (x, y *big.Int) {
var x1, y1 fp384
montDecode(&x1, &ap.x)
montDecode(&y1, &ap.y)
return x1.BigInt(), y1.BigInt()
}
func (ap *affinePoint) toJacobian() *jacobianPoint {
var P jacobianPoint
if ap.isZero() {
montEncode(&P.x, &fp384{1})
montEncode(&P.y, &fp384{1})
} else {
P.x = ap.x
P.y = ap.y
montEncode(&P.z, &fp384{1})
}
return &P
}
func (ap *affinePoint) toProjective() *projectivePoint {
var P projectivePoint
if ap.isZero() {
montEncode(&P.y, &fp384{1})
} else {
P.x = ap.x
P.y = ap.y
montEncode(&P.z, &fp384{1})
}
return &P
}
// OddMultiples calculates the points iP for i={1,3,5,7,..., 2^(n-1)-1}
// Ensure that 1 < n < 31, otherwise it returns an empty slice.
func (ap affinePoint) oddMultiples(n uint) []jacobianPoint {
var t []jacobianPoint
if n > 1 && n < 31 {
P := ap.toJacobian()
s := int32(1) << (n - 1)
t = make([]jacobianPoint, s)
t[0] = *P
_2P := *P
_2P.double()
for i := int32(1); i < s; i++ {
t[i].add(&t[i-1], &_2P)
}
}
return t
}
// p2Point is a point in P^2
type p2Point struct{ x, y, z fp384 }
func (P *p2Point) String() string {
return fmt.Sprintf("x: %v\ny: %v\nz: %v", P.x, P.y, P.z)
}
func (P *p2Point) neg() { fp384Neg(&P.y, &P.y) }
// condNeg if P is negated if b=1.
func (P *p2Point) cneg(b int) {
var mY fp384
fp384Neg(&mY, &P.y)
fp384Cmov(&P.y, &mY, b)
}
// cmov sets P to Q if b=1.
func (P *p2Point) cmov(Q *p2Point, b int) {
fp384Cmov(&P.x, &Q.x, b)
fp384Cmov(&P.y, &Q.y, b)
fp384Cmov(&P.z, &Q.z, b)
}
func (P *p2Point) toInt() (x, y, z *big.Int) {
var x1, y1, z1 fp384
montDecode(&x1, &P.x)
montDecode(&y1, &P.y)
montDecode(&z1, &P.z)
return x1.BigInt(), y1.BigInt(), z1.BigInt()
}
// jacobianPoint represents a point in Jacobian coordinates. The point at
// infinity is any point (x,y,0) such that x and y are different from 0.
type jacobianPoint struct{ p2Point }
func (P *jacobianPoint) isZero() bool {
zero := fp384{}
return P.x != zero && P.y != zero && P.z == zero
}
func (P *jacobianPoint) toAffine() *affinePoint {
var aP affinePoint
z, z2 := &fp384{}, &fp384{}
fp384Inv(z, &P.z)
fp384Sqr(z2, z)
fp384Mul(&aP.x, &P.x, z2)
fp384Mul(&aP.y, &P.y, z)
fp384Mul(&aP.y, &aP.y, z2)
return &aP
}
func (P *jacobianPoint) cmov(Q *jacobianPoint, b int) { P.p2Point.cmov(&Q.p2Point, b) }
// add calculates P=Q+R such that Q and R are different than the identity point,
// and Q!==R. This function cannot be used for doublings.
func (P *jacobianPoint) add(Q, R *jacobianPoint) {
if Q.isZero() {
*P = *R
return
} else if R.isZero() {
*P = *Q
return
}
// Cohen-Miyagi-Ono (1998)
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
X1, Y1, Z1 := &Q.x, &Q.y, &Q.z
X2, Y2, Z2 := &R.x, &R.y, &R.z
Z1Z1, Z2Z2, U1, U2 := &fp384{}, &fp384{}, &fp384{}, &fp384{}
H, HH, HHH, RR := &fp384{}, &fp384{}, &fp384{}, &fp384{}
V, t4, t5, t6, t7, t8 := &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{}
t0, t1, t2, t3, S1, S2 := &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{}
fp384Sqr(Z1Z1, Z1) // Z1Z1 = Z1 ^ 2
fp384Sqr(Z2Z2, Z2) // Z2Z2 = Z2 ^ 2
fp384Mul(U1, X1, Z2Z2) // U1 = X1 * Z2Z2
fp384Mul(U2, X2, Z1Z1) // U2 = X2 * Z1Z1
fp384Mul(t0, Z2, Z2Z2) // t0 = Z2 * Z2Z2
fp384Mul(S1, Y1, t0) // S1 = Y1 * t0
fp384Mul(t1, Z1, Z1Z1) // t1 = Z1 * Z1Z1
fp384Mul(S2, Y2, t1) // S2 = Y2 * t1
fp384Sub(H, U2, U1) // H = U2 - U1
fp384Sqr(HH, H) // HH = H ^ 2
fp384Mul(HHH, H, HH) // HHH = H * HH
fp384Sub(RR, S2, S1) // r = S2 - S1
fp384Mul(V, U1, HH) // V = U1 * HH
fp384Sqr(t2, RR) // t2 = r ^ 2
fp384Add(t3, V, V) // t3 = V + V
fp384Sub(t4, t2, HHH) // t4 = t2 - HHH
fp384Sub(&P.x, t4, t3) // X3 = t4 - t3
fp384Sub(t5, V, &P.x) // t5 = V - X3
fp384Mul(t6, S1, HHH) // t6 = S1 * HHH
fp384Mul(t7, RR, t5) // t7 = r * t5
fp384Sub(&P.y, t7, t6) // Y3 = t7 - t6
fp384Mul(t8, Z2, H) // t8 = Z2 * H
fp384Mul(&P.z, Z1, t8) // Z3 = Z1 * t8
}
// mixadd calculates P=Q+R such that P and Q different than the identity point,
// and Q not in {P,-P, O}.
func (P *jacobianPoint) mixadd(Q *jacobianPoint, R *affinePoint) {
if Q.isZero() {
*P = *R.toJacobian()
return
} else if R.isZero() {
*P = *Q
return
}
z1z1, u2 := &fp384{}, &fp384{}
fp384Sqr(z1z1, &Q.z)
fp384Mul(u2, &R.x, z1z1)
s2 := &fp384{}
fp384Mul(s2, &R.y, &Q.z)
fp384Mul(s2, s2, z1z1)
if Q.x == *u2 {
if Q.y != *s2 {
*P = *(zeroPoint().toJacobian())
return
}
*P = *Q
P.double()
return
}
h, r := &fp384{}, &fp384{}
fp384Sub(h, u2, &Q.x)
fp384Mul(&P.z, h, &Q.z)
fp384Sub(r, s2, &Q.y)
h2, h3 := &fp384{}, &fp384{}
fp384Sqr(h2, h)
fp384Mul(h3, h2, h)
h3y1 := &fp384{}
fp384Mul(h3y1, h3, &Q.y)
h2x1 := &fp384{}
fp384Mul(h2x1, h2, &Q.x)
fp384Sqr(&P.x, r)
fp384Sub(&P.x, &P.x, h3)
fp384Sub(&P.x, &P.x, h2x1)
fp384Sub(&P.x, &P.x, h2x1)
fp384Sub(&P.y, h2x1, &P.x)
fp384Mul(&P.y, &P.y, r)
fp384Sub(&P.y, &P.y, h3y1)
}
func (P *jacobianPoint) double() {
delta, gamma, alpha, alpha2 := &fp384{}, &fp384{}, &fp384{}, &fp384{}
fp384Sqr(delta, &P.z)
fp384Sqr(gamma, &P.y)
fp384Sub(alpha, &P.x, delta)
fp384Add(alpha2, &P.x, delta)
fp384Mul(alpha, alpha, alpha2)
*alpha2 = *alpha
fp384Add(alpha, alpha, alpha)
fp384Add(alpha, alpha, alpha2)
beta := &fp384{}
fp384Mul(beta, &P.x, gamma)
beta8 := &fp384{}
fp384Sqr(&P.x, alpha)
fp384Add(beta8, beta, beta)
fp384Add(beta8, beta8, beta8)
fp384Add(beta8, beta8, beta8)
fp384Sub(&P.x, &P.x, beta8)
fp384Add(&P.z, &P.y, &P.z)
fp384Sqr(&P.z, &P.z)
fp384Sub(&P.z, &P.z, gamma)
fp384Sub(&P.z, &P.z, delta)
fp384Add(beta, beta, beta)
fp384Add(beta, beta, beta)
fp384Sub(beta, beta, &P.x)
fp384Mul(&P.y, alpha, beta)
fp384Sqr(gamma, gamma)
fp384Add(gamma, gamma, gamma)
fp384Add(gamma, gamma, gamma)
fp384Add(gamma, gamma, gamma)
fp384Sub(&P.y, &P.y, gamma)
}
func (P *jacobianPoint) toProjective() *projectivePoint {
var hP projectivePoint
hP.y = P.y
fp384Mul(&hP.x, &P.x, &P.z)
fp384Sqr(&hP.z, &P.z)
fp384Mul(&hP.z, &hP.z, &P.z)
return &hP
}
// projectivePoint represents a point in projective homogeneous coordinates.
// The point at infinity is (0,y,0) such that y is different from 0.
type projectivePoint struct{ p2Point }
func (P *projectivePoint) isZero() bool {
zero := fp384{}
return P.x == zero && P.y != zero && P.z == zero
}
func (P *projectivePoint) toAffine() *affinePoint {
var aP affinePoint
z := &fp384{}
fp384Inv(z, &P.z)
fp384Mul(&aP.x, &P.x, z)
fp384Mul(&aP.y, &P.y, z)
return &aP
}
// add calculates P=Q+R using complete addition formula for prime groups.
func (P *projectivePoint) completeAdd(Q, R *projectivePoint) {
// Reference:
// "Complete addition formulas for prime order elliptic curves" by
// Costello-Renes-Batina. [Alg.4] (eprint.iacr.org/2015/1060).
X1, Y1, Z1 := &Q.x, &Q.y, &Q.z
X2, Y2, Z2 := &R.x, &R.y, &R.z
X3, Y3, Z3 := &fp384{}, &fp384{}, &fp384{}
t0, t1, t2, t3, t4 := &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{}
fp384Mul(t0, X1, X2) // 1. t0 ← X1 · X2
fp384Mul(t1, Y1, Y2) // 2. t1 ← Y1 · Y2
fp384Mul(t2, Z1, Z2) // 3. t2 ← Z1 · Z2
fp384Add(t3, X1, Y1) // 4. t3 ← X1 + Y1
fp384Add(t4, X2, Y2) // 5. t4 ← X2 + Y2
fp384Mul(t3, t3, t4) // 6. t3 ← t3 · t4
fp384Add(t4, t0, t1) // 7. t4 ← t0 + t1
fp384Sub(t3, t3, t4) // 8. t3 ← t3 − t4
fp384Add(t4, Y1, Z1) // 9. t4 ← Y1 + Z1
fp384Add(X3, Y2, Z2) // 10. X3 ← Y2 + Z2
fp384Mul(t4, t4, X3) // 11. t4 ← t4 · X3
fp384Add(X3, t1, t2) // 12. X3 ← t1 + t2
fp384Sub(t4, t4, X3) // 13. t4 ← t4 − X3
fp384Add(X3, X1, Z1) // 14. X3 ← X1 + Z1
fp384Add(Y3, X2, Z2) // 15. Y3 ← X2 + Z2
fp384Mul(X3, X3, Y3) // 16. X3 ← X3 · Y3
fp384Add(Y3, t0, t2) // 17. Y3 ← t0 + t2
fp384Sub(Y3, X3, Y3) // 18. Y3 ← X3 − Y3
fp384Mul(Z3, &bb, t2) // 19. Z3 ← b · t2
fp384Sub(X3, Y3, Z3) // 20. X3 ← Y3 − Z3
fp384Add(Z3, X3, X3) // 21. Z3 ← X3 + X3
fp384Add(X3, X3, Z3) // 22. X3 ← X3 + Z3
fp384Sub(Z3, t1, X3) // 23. Z3 ← t1 − X3
fp384Add(X3, t1, X3) // 24. X3 ← t1 + X3
fp384Mul(Y3, &bb, Y3) // 25. Y3 ← b · Y3
fp384Add(t1, t2, t2) // 26. t1 ← t2 + t2
fp384Add(t2, t1, t2) // 27. t2 ← t1 + t2
fp384Sub(Y3, Y3, t2) // 28. Y3 ← Y3 − t2
fp384Sub(Y3, Y3, t0) // 29. Y3 ← Y3 − t0
fp384Add(t1, Y3, Y3) // 30. t1 ← Y3 + Y3
fp384Add(Y3, t1, Y3) // 31. Y3 ← t1 + Y3
fp384Add(t1, t0, t0) // 32. t1 ← t0 + t0
fp384Add(t0, t1, t0) // 33. t0 ← t1 + t0
fp384Sub(t0, t0, t2) // 34. t0 ← t0 − t2
fp384Mul(t1, t4, Y3) // 35. t1 ← t4 · Y3
fp384Mul(t2, t0, Y3) // 36. t2 ← t0 · Y3
fp384Mul(Y3, X3, Z3) // 37. Y3 ← X3 · Z3
fp384Add(Y3, Y3, t2) // 38. Y3 ← Y3 + t2
fp384Mul(X3, t3, X3) // 39. X3 ← t3 · X3
fp384Sub(X3, X3, t1) // 40. X3 ← X3 − t1
fp384Mul(Z3, t4, Z3) // 41. Z3 ← t4 · Z3
fp384Mul(t1, t3, t0) // 42. t1 ← t3 · t0
fp384Add(Z3, Z3, t1) // 43. Z3 ← Z3 + t1
P.x, P.y, P.z = *X3, *Y3, *Z3
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy