diff --git a/dh/sidh/internal/p751/curve.go b/dh/sidh/internal/p751/curve.go index 429c6f7..061246a 100644 --- a/dh/sidh/internal/p751/curve.go +++ b/dh/sidh/internal/p751/curve.go @@ -11,8 +11,8 @@ type ProjectiveCurveParameters struct { // Stores curve projective parameters equivalent to A/C. Meaning of the // values depends on the context. When working with isogenies over // subgroup that are powers of: -// * three then A=(A+2C)/4; C=(A-2C)/4 -// * four then A=(A+2C)/4; C=4C +// * three then (A:C) ~ (A+2C:A-2C) +// * four then (A:C) ~ (A+2C: 4C) // See Appendix A of SIKE for more details type CurveCoefficientsEquiv struct { A ExtensionFieldElement @@ -93,26 +93,25 @@ func (curve *ProjectiveCurveParameters) RecoverCoordinateA(xp, xq, xr *Extension // Computes equivalence (A:C) ~ (A+2C : A-2C) func (curve *ProjectiveCurveParameters) CalcCurveParamsEquiv3() CurveCoefficientsEquiv { var coef CurveCoefficientsEquiv - var tmp ExtensionFieldElement + var c2 ExtensionFieldElement // TODO: Calling code sets C=1, always (all functions). Currently only tests // require C to be customizable. - // C24 = 2*C - tmp.Add(&curve.C, &curve.C) - // A24_plus = A + 2C - coef.A.Add(&curve.A, &tmp) - // A24_minus = A - 2C - coef.C.Sub(&curve.A, &tmp) + c2.Add(&curve.C, &curve.C) + // A24p = A+2*C + coef.A.Add(&curve.A, &c2) + // A24m = A-2*C + coef.C.Sub(&curve.A, &c2) return coef } -// Computes equivalence (A:C) ~ (A+2C : 2C) +// Computes equivalence (A:C) ~ (A+2C : 4C) func (cparams *ProjectiveCurveParameters) CalcCurveParamsEquiv4() CurveCoefficientsEquiv { var coefEq CurveCoefficientsEquiv - // C = 2*cparams.C + coefEq.C.Add(&cparams.C, &cparams.C) - // A24_plus = A + 2C + // A24p = A + 2C coefEq.A.Add(&cparams.A, &coefEq.C) // C24 = 4*C coefEq.C.Add(&coefEq.C, &coefEq.C) @@ -136,18 +135,31 @@ func (cparams *ProjectiveCurveParameters) calcAplus2Over4() (ret ExtensionFieldE // Recovers (A:C) curve parameters from projectively equivalent (A+2C:A-2C). func (cparams *ProjectiveCurveParameters) RecoverCurveCoefficients3(coefEq *CurveCoefficientsEquiv) { cparams.A.Add(&coefEq.A, &coefEq.C) + // cparams.A = 2*(A+2C+A-2C) = 4A cparams.A.Add(&cparams.A, &cparams.A) + // cparams.C = (A+2C-A+2C) = 4C cparams.C.Sub(&coefEq.A, &coefEq.C) return } -// Recovers (A:C) curve parameters from projectively equivalent (A+2C:2C). +// Recovers (A:C) curve parameters from projectively equivalent (A+2C:4C). func (cparams *ProjectiveCurveParameters) RecoverCurveCoefficients4(coefEq *CurveCoefficientsEquiv) { - var tmp ExtensionFieldElement - tmp.Add(&oneExtensionField, &oneExtensionField).Inv(&tmp) - cparams.C.Mul(&coefEq.C, &tmp) + // Represents 1/2 in montgomery form + var half = ExtensionFieldElement{ + A: Fp751Element{ + 0x00000000000124D6, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0xB8E0000000000000, + 0x9C8A2434C0AA7287, 0xA206996CA9A378A3, 0x6876280D41A41B52, + 0xE903B49F175CE04F, 0x0F8511860666D227, 0x00004EA07CFF6E7F}, + B: Fp751Element{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + } + + // cparams.C = (4C)*1/2=2C + cparams.C.Mul(&coefEq.C, &half) + // cparams.A = A+2C - 2C = A cparams.A.Sub(&coefEq.A, &cparams.C) - cparams.C.Mul(&cparams.C, &tmp) + // cparams.C = 2C * 1/2 = C + cparams.C.Mul(&cparams.C, &half) return } diff --git a/dh/sidh/internal/p751/curve_test.go b/dh/sidh/internal/p751/curve_test.go index 6d2e214..ce9dea5 100644 --- a/dh/sidh/internal/p751/curve_test.go +++ b/dh/sidh/internal/p751/curve_test.go @@ -93,6 +93,8 @@ var threePointLadderInputs = []ProjectivePoint{ }, } +// Helpers + func (P ProjectivePoint) Generate(rand *rand.Rand, size int) reflect.Value { f := ExtensionFieldElement{} x, _ := f.Generate(rand, size).Interface().(ExtensionFieldElement) @@ -113,6 +115,25 @@ func (curve ProjectiveCurveParameters) Generate(rand *rand.Rand, size int) refle }) } +// Sets FP(p^2) from uint64. x sets ExtensionsFieldElement.A (real part) and y +// ExtensionFieldElement.B (imaginary part). +// +// Returns dest to allow chaining operations. +func (dest *ExtensionFieldElement) SetUint64(x, y uint64) *ExtensionFieldElement { + var xRR fp751X2 + dest.A = Fp751Element{} // = 0 + dest.A[0] = x // = x + fp751Mul(&xRR, &dest.A, &montgomeryRsq) // = x*R*R + fp751MontgomeryReduce(&dest.A, &xRR) // = x*R mod p + + dest.B = Fp751Element{} // = 0 + dest.B[0] = y // = y + fp751Mul(&xRR, &dest.B, &montgomeryRsq) // = y*R*R + fp751MontgomeryReduce(&dest.B, &xRR) // = y*R mod p + + return dest +} + // Helpers // Given xP = x(P), xQ = x(Q), and xPmQ = x(P-Q), compute xR = x(P+Q). @@ -355,6 +376,36 @@ func TestPointTripleVersusAddDouble(t *testing.T) { } } +func TestProjectiveParamsRecovery(t *testing.T) { + var crv1, crv2 ProjectiveCurveParameters + var A4, C4, four ExtensionFieldElement + four.SetUint64(4, 0) + + eqivParams3 := curve.CalcCurveParamsEquiv3() + eqivParams4 := curve.CalcCurveParamsEquiv4() + + // This returns 4*A and 4*C + crv1.RecoverCurveCoefficients3(&eqivParams3) + crv2.RecoverCurveCoefficients4(&eqivParams4) + + A4.Mul(&curve_A, &four) + C4.Mul(&curve_C, &four) + + if !crv1.A.VartimeEq(&A4) { + t.Error("\nExpected\n", crv1.A, "\nfound\n", A4) + } + if !crv1.C.VartimeEq(&C4) { + t.Error("\nExpected\n", crv1.C, "\nfound\n", C4) + } + + if !crv2.A.VartimeEq(&curve_A) { + t.Error("\nExpected\n", crv2.A, "\nfound\n", curve_A) + } + if !crv2.C.VartimeEq(&curve_C) { + t.Error("\nExpected\n", crv2.C, "\nfound\n", curve_C) + } +} + func BenchmarkThreePointLadder379BitScalar(b *testing.B) { var mScalarBytes = [...]uint8{84, 222, 146, 63, 85, 18, 173, 162, 167, 38, 10, 8, 143, 176, 93, 228, 247, 128, 50, 128, 205, 42, 15, 137, 119, 67, 43, 3, 61, 91, 237, 24, 235, 12, 53, 96, 186, 164, 232, 223, 197, 224, 64, 109, 137, 63, 246, 4}