فهرست منبع

Clarify the logic of point-order testing for F2m curves

- expand test cases for invalid points
Ugochukwu Mmaduekwe 6 سال پیش
والد
کامیت
800eb35e0a
2فایلهای تغییر یافته به همراه108 افزوده شده و 21 حذف شده
  1. 80 7
      CryptoLib.Tests/src/Math/ECPointTests.pas
  2. 28 14
      CryptoLib/src/Math/EC/ClpECC.pas

+ 80 - 7
CryptoLib.Tests/src/Math/ECPointTests.pas

@@ -200,6 +200,9 @@ type
     procedure ImplAddSubtractMultiplyTwiceEncodingTestAllCoords
       (const x9ECParameters: IX9ECParameters);
 
+    function SolveQuadraticEquation(const c: IECCurve;
+      const rhs: IECFieldElement): IECFieldElement;
+
   protected
     procedure SetUp; override;
     procedure TearDown; override;
@@ -509,18 +512,47 @@ end;
 procedure TTestECPoint.ImplValidityTest(const c: IECCurve; const g: IECPoint);
 var
   h: TBigInteger;
-  order2, bad: IECPoint;
+  sqrtB, L, T, x, y: IECFieldElement;
+  order2, bad2, good2, order4, bad4_1, bad4_2, bad4_3, good4: IECPoint;
 begin
   CheckTrue(g.IsValid());
 
-  h := c.getCofactor();
-  if ((h.IsInitialized) and (h.CompareTo(TBigInteger.One) > 0)) then
+  if (TECAlgorithms.IsF2mCurve(c)) then
   begin
-    if (TECAlgorithms.IsF2mCurve(c)) then
+    h := c.Cofactor;
+    if (h.IsInitialized) then
     begin
-      order2 := c.CreatePoint(TBigInteger.Zero, c.b.Sqrt().ToBigInteger());
-      bad := g.Add(order2);
-      CheckFalse(bad.IsValid());
+      if (not h.TestBit(0)) then
+      begin
+        sqrtB := c.b.Sqrt();
+        order2 := c.CreatePoint(TBigInteger.Zero, sqrtB.ToBigInteger);
+        CheckTrue(order2.Twice().IsInfinity);
+        CheckFalse(order2.IsValid());
+        bad2 := g.Add(order2);
+        CheckFalse(bad2.IsValid());
+        good2 := bad2.Add(order2);
+        CheckTrue(good2.IsValid());
+
+        if (not h.TestBit(1)) then
+        begin
+          L := SolveQuadraticEquation(c, c.a);
+          CheckNotNull(L);
+          T := sqrtB;
+          x := T.Sqrt();
+          y := T.Add(x.Multiply(L));
+          order4 := c.CreatePoint(x.ToBigInteger(), y.ToBigInteger());
+          CheckTrue(order4.Twice().Equals(order2));
+          CheckFalse(order4.IsValid());
+          bad4_1 := g.Add(order4);
+          CheckFalse(bad4_1.IsValid());
+          bad4_2 := bad4_1.Add(order4);
+          CheckFalse(bad4_2.IsValid());
+          bad4_3 := bad4_2.Add(order4);
+          CheckFalse(bad4_3.IsValid());
+          good4 := bad4_3.Add(order4);
+          CheckTrue(good4.IsValid());
+        end;
+      end;
     end;
   end;
 end;
@@ -535,6 +567,47 @@ begin
   F2mInstance.CreatePoints;
 end;
 
+function TTestECPoint.SolveQuadraticEquation(const c: IECCurve;
+  const rhs: IECFieldElement): IECFieldElement;
+var
+  gamma, z, zeroElement, T, w, w2: IECFieldElement;
+  m, i: Int32;
+  rand: ISecureRandom;
+begin
+  if (rhs.IsZero) then
+  begin
+    result := rhs;
+    Exit;
+  end;
+
+  zeroElement := c.FromBigInteger(TBigInteger.Zero);
+  z := zeroElement;
+  gamma := z;
+
+  m := c.FieldSize;
+  rand := TSecureRandom.Create();
+
+  repeat
+    T := c.FromBigInteger(TBigInteger.Create(m, rand));
+    z := zeroElement;
+    w := rhs;
+    for i := 1 to System.Pred(m) do
+    begin
+      w2 := w.Square();
+      z := z.Square().Add(w2.Multiply(T));
+      w := w2.Add(rhs);
+    end;
+    if (not w.IsZero) then
+    begin
+      result := Nil;
+      Exit;
+    end;
+    gamma := z.Square().Add(z);
+  until (not gamma.IsZero);
+
+  result := z;
+end;
+
 procedure TTestECPoint.TearDown;
 begin
   inherited;

+ 28 - 14
CryptoLib/src/Math/EC/ClpECC.pas

@@ -6201,21 +6201,23 @@ function TAbstractF2mPoint.SatisfiesOrder: Boolean;
 var
   Cofactor: TBigInteger;
   n: IECPoint;
-  x, rhs, lambda, w, t: IECFieldElement;
+  x, rhs, L, t, y: IECFieldElement;
   Lcurve: IECCurve;
 begin
   Lcurve := curve;
   Cofactor := Lcurve.GetCofactor();
   if (TBigInteger.Two.Equals(Cofactor)) then
   begin
-    // /*
-    // *  Check that the trace of (X + A) is 0, then there exists a solution to L^2 + L = X + A,
-    // *  and so a halving is possible, so this point is the double of another.
-    // */
+    (*
+      * Check that 0 == Tr(X + A); then there exists a solution to L^2 + L = X + A, and
+      * so a halving is possible, so this point is the double of another.
+      *
+      * Note: Tr(A) == 1 for cofactor 2 curves.
+    *)
     n := Normalize();
     x := n.AffineXCoord;
     rhs := x.Add(Lcurve.a);
-    result := (rhs as IAbstractF2mFieldElement).Trace() = 0;
+    result := (x as IAbstractF2mFieldElement).Trace() <> 0;
     Exit;
   end;
   if (TBigInteger.Four.Equals(Cofactor)) then
@@ -6226,21 +6228,33 @@ begin
     // * and check if Tr(w + A) == 0 for at least one; then a second halving is possible
     // * (see comments for cofactor 2 above), so this point is four times another.
     // *
-    // * Note: Tr(x^2) == Tr(x).
+    // * Note: Tr(A) == 0 for cofactor 4 curves.
     // */
     n := Normalize();
     x := n.AffineXCoord;
-    lambda := (Lcurve as IAbstractF2mCurve).SolveQuadraticEquation
-      (x.Add(curve.a));
-    if (lambda = Nil) then
+    L := (Lcurve as IAbstractF2mCurve).SolveQuadraticEquation(x.Add(curve.a));
+    if (L = Nil) then
     begin
       result := false;
       Exit;
     end;
-    w := x.Multiply(lambda).Add(n.AffineYCoord);
-    t := w.Add(Lcurve.a);
-    result := ((t as IAbstractF2mFieldElement).Trace() = 0) or
-      ((t.Add(x) as IAbstractF2mFieldElement).Trace() = 0);
+
+    (*
+      * A solution exists, therefore 0 == Tr(X + A) == Tr(X).
+    *)
+    y := n.AffineYCoord;
+    t := x.Multiply(L).Add(y);
+
+    (*
+      * Either T or (T + X) is the square of a half-point's x coordinate (hx). In either
+      * case, the half-point can be halved again when 0 == Tr(hx + A).
+      *
+      * Note: Tr(hx + A) == Tr(hx) == Tr(hx^2) == Tr(T) == Tr(T + X)
+      *
+      * Check that 0 == Tr(T); then there exists a solution to L^2 + L = hx + A, and so a
+      * second halving is possible and this point is four times some other.
+    *)
+    result := (t as IAbstractF2mFieldElement).Trace() = 0;
     Exit;
   end;