ECPointTests.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. { *********************************************************************************** }
  2. { * CryptoLib Library * }
  3. { * Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe * }
  4. { * Github Repository <https://github.com/Xor-el> * }
  5. { * Distributed under the MIT software license, see the accompanying file LICENSE * }
  6. { * or visit http://www.opensource.org/licenses/mit-license.php. * }
  7. { * Acknowledgements: * }
  8. { * * }
  9. { * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * }
  10. { * development of this library * }
  11. { * ******************************************************************************* * }
  12. (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
  13. unit ECPointTests;
  14. interface
  15. {$IFDEF FPC}
  16. {$MODE DELPHI}
  17. {$ENDIF FPC}
  18. uses
  19. Classes,
  20. SysUtils,
  21. {$IFDEF FPC}
  22. fpcunit,
  23. testregistry,
  24. {$ELSE}
  25. TestFramework,
  26. {$ENDIF FPC}
  27. Generics.Collections,
  28. ClpCustomNamedCurves,
  29. ClpECNamedCurveTable,
  30. ClpCryptoLibTypes,
  31. ClpSecureRandom,
  32. ClpISecureRandom,
  33. ClpBigInteger,
  34. ClpBigIntegers,
  35. ClpECAlgorithms,
  36. ClpIFiniteField,
  37. ClpIX9ECParameters,
  38. ClpECC,
  39. ClpIECC,
  40. CryptoLibTestBase;
  41. type
  42. // /**
  43. // * Nested class containing sample literature values for <code>Fp</code>.
  44. // */
  45. TFp = class
  46. public
  47. var
  48. Fq, Fa, Fb, Fn, Fh: TBigInteger;
  49. Fcurve: IECCurve;
  50. FInfinity: IECPoint;
  51. FpointSource: TCryptoLibInt32Array;
  52. Fp: TCryptoLibGenericArray<IECPoint>;
  53. constructor Create();
  54. procedure CreatePoints();
  55. end;
  56. type
  57. // /**
  58. // * Nested class containing sample literature values for <code>F2m</code>.
  59. // */
  60. TF2m = class
  61. public const
  62. // Irreducible polynomial for TPB z^4 + z + 1
  63. m = Int32(4);
  64. k1 = Int32(1);
  65. var
  66. FaTpb, FbTpb, Fn, Fh: TBigInteger;
  67. Fcurve: IECCurve;
  68. FInfinity: IECPoint;
  69. FpointSource: TCryptoLibStringArray;
  70. Fp: TCryptoLibGenericArray<IECPoint>;
  71. constructor Create();
  72. procedure CreatePoints();
  73. end;
  74. type
  75. TTestECPoint = class(TCryptoLibAlgorithmTestCase)
  76. private
  77. var
  78. // /**
  79. // * Random source used to generate random points
  80. // */
  81. FRandom: ISecureRandom;
  82. FpInstance: TFp;
  83. F2mInstance: TF2m;
  84. procedure AssertPointsEqual(const msg: String; const a, b: IECPoint);
  85. procedure AssertBigIntegersEqual(const a, b: TBigInteger);
  86. procedure AssertIFiniteFieldsEqual(const a, b: IFiniteField);
  87. procedure AssertOptionalValuesAgree(const a, b: TBigInteger); overload;
  88. procedure AssertOptionalValuesAgree(const a, b: TBytes); overload;
  89. procedure AssertECFieldElementsEqual(const a, b: IECFieldElement);
  90. // /**
  91. // * Tests <code>ECPoint.add()</code> against literature values.
  92. // *
  93. // * @param p
  94. // * The array of literature values.
  95. // * @param infinity
  96. // * The point at infinity on the respective curve.
  97. // */
  98. procedure ImplTestAdd(const p: TCryptoLibGenericArray<IECPoint>;
  99. const infinity: IECPoint);
  100. // /**
  101. // * Tests <code>ECPoint.twice()</code> against literature values.
  102. // *
  103. // * @param p
  104. // * The array of literature values.
  105. // */
  106. procedure ImplTestTwice(const p: TCryptoLibGenericArray<IECPoint>);
  107. procedure ImplTestThreeTimes(const p: TCryptoLibGenericArray<IECPoint>);
  108. // /**
  109. // * Goes through all points on an elliptic curve and checks, if adding a
  110. // * point <code>k</code>-times is the same as multiplying the point by
  111. // * <code>k</code>, for all <code>k</code>. Should be called for points
  112. // * on very small elliptic curves only.
  113. // *
  114. // * @param p
  115. // * The base point on the elliptic curve.
  116. // * @param infinity
  117. // * The point at infinity on the elliptic curve.
  118. // */
  119. procedure ImplTestAllPoints(const p, infinity: IECPoint);
  120. // /**
  121. // * Checks, if the point multiplication algorithm of the given point yields
  122. // * the same result as point multiplication done by the reference
  123. // * implementation given in <code>multiply()</code>. This method chooses a
  124. // * random number by which the given point <code>p</code> is multiplied.
  125. // *
  126. // * @param p
  127. // * The point to be multiplied.
  128. // * @param numBits
  129. // * The bitlength of the random number by which <code>p</code>
  130. // * is multiplied.
  131. // */
  132. procedure ImplTestMultiply(const p: IECPoint; numBits: Int32);
  133. // /**
  134. // * Checks, if the point multiplication algorithm of the given point yields
  135. // * the same result as point multiplication done by the reference
  136. // * implementation given in <code>multiply()</code>. This method tests
  137. // * multiplication of <code>p</code> by every number of bitlength
  138. // * <code>numBits</code> or less.
  139. // *
  140. // * @param p
  141. // * The point to be multiplied.
  142. // * @param numBits
  143. // * Try every multiplier up to this bitlength
  144. // */
  145. procedure ImplTestMultiplyAll(const p: IECPoint; numBits: Int32);
  146. // /**
  147. // * Tests <code>ECPoint.add()</code> and <code>ECPoint.subtract()</code>
  148. // * for the given point and the given point at infinity.
  149. // *
  150. // * @param p
  151. // * The point on which the tests are performed.
  152. // * @param infinity
  153. // * The point at infinity on the same curve as <code>p</code>.
  154. // */
  155. procedure ImplTestAddSubtract(const p, infinity: IECPoint);
  156. // /**
  157. // * Test encoding with and without point compression.
  158. // *
  159. // * @param p
  160. // * The point to be encoded and decoded.
  161. // */
  162. procedure ImplTestEncoding(const p: IECPoint);
  163. procedure ImplAddSubtractMultiplyTwiceEncodingTest(const curve: IECCurve;
  164. const q: IECPoint; const n: TBigInteger);
  165. procedure ImplSqrtTest(const c: IECCurve);
  166. procedure ImplValidityTest(const c: IECCurve; const g: IECPoint);
  167. procedure ImplAddSubtractMultiplyTwiceEncodingTestAllCoords
  168. (const x9ECParameters: IX9ECParameters);
  169. protected
  170. procedure SetUp; override;
  171. procedure TearDown; override;
  172. published
  173. /// <summary>
  174. /// Tests, if inconsistent points can be created, i.e. points with
  175. /// exactly one null coordinate (not permitted).
  176. /// </summary>
  177. procedure TestPointCreationConsistency();
  178. // /**
  179. // * Calls <code>implTestAdd()</code> for <code>Fp</code> and
  180. // * <code>F2m</code>.
  181. // */
  182. procedure TestAdd();
  183. // /**
  184. // * Calls <code>implTestTwice()</code> for <code>Fp</code> and
  185. // * <code>F2m</code>.
  186. // */
  187. procedure TestTwice();
  188. // /**
  189. // * Calls <code>implTestThreeTimes()</code> for <code>Fp</code> and
  190. // * <code>F2m</code>.
  191. // */
  192. procedure TestThreeTimes();
  193. // /**
  194. // * Calls <code>implTestAllPoints()</code> for the small literature curves,
  195. // * both for <code>Fp</code> and <code>F2m</code>.
  196. // */
  197. procedure TestAllPoints();
  198. // /**
  199. // * Calls <code>implTestAddSubtract()</code> for literature values, both
  200. // * for <code>Fp</code> and <code>F2m</code>.
  201. // */
  202. procedure TestAddSubtractMultiplySimple();
  203. // /**
  204. // * Calls <code>implTestAddSubtract()</code>,
  205. // * <code>implTestMultiply</code> and <code>implTestEncoding</code> for
  206. // * the standard elliptic curves as given in <code>SecNamedCurves</code>.
  207. // */
  208. procedure TestAddSubtractMultiplyTwiceEncoding();
  209. end;
  210. implementation
  211. { TTestECPoint }
  212. procedure TTestECPoint.AssertECFieldElementsEqual(const a, b: IECFieldElement);
  213. begin
  214. CheckEquals(True, a.Equals(b));
  215. end;
  216. procedure TTestECPoint.AssertBigIntegersEqual(const a, b: TBigInteger);
  217. begin
  218. CheckEquals(True, a.Equals(b));
  219. end;
  220. procedure TTestECPoint.AssertIFiniteFieldsEqual(const a, b: IFiniteField);
  221. begin
  222. CheckEquals(True, (a as TObject).Equals(b as TObject));
  223. end;
  224. procedure TTestECPoint.AssertOptionalValuesAgree(const a, b: TBigInteger);
  225. begin
  226. if ((a.IsInitialized) and (b.IsInitialized)) then
  227. begin
  228. AssertBigIntegersEqual(a, b);
  229. end;
  230. end;
  231. procedure TTestECPoint.AssertOptionalValuesAgree(const a, b: TBytes);
  232. begin
  233. if ((a <> Nil) and (b <> Nil)) then
  234. begin
  235. CheckTrue(AreEqual(a, b));
  236. end;
  237. end;
  238. procedure TTestECPoint.AssertPointsEqual(const msg: String;
  239. const a, b: IECPoint);
  240. begin
  241. CheckEquals(True, a.Equals(b), msg);
  242. CheckEquals(True, b.Equals(a), msg);
  243. end;
  244. procedure TTestECPoint.ImplAddSubtractMultiplyTwiceEncodingTest
  245. (const curve: IECCurve; const q: IECPoint; const n: TBigInteger);
  246. var
  247. infinity, p: IECPoint;
  248. i: Int32;
  249. begin
  250. // Get point at infinity on the curve
  251. infinity := curve.infinity;
  252. ImplTestAddSubtract(q, infinity);
  253. ImplTestMultiply(q, n.BitLength);
  254. ImplTestMultiply(infinity, n.BitLength);
  255. //
  256. p := q;
  257. i := 0;
  258. while i < 10 do
  259. begin
  260. ImplTestEncoding(p);
  261. p := p.Twice();
  262. System.Inc(i);
  263. end;
  264. end;
  265. procedure TTestECPoint.ImplAddSubtractMultiplyTwiceEncodingTestAllCoords
  266. (const x9ECParameters: IX9ECParameters);
  267. var
  268. n, b: TBigInteger;
  269. g, sg, q: IECPoint;
  270. c, sc: IECCurve;
  271. coords: TCryptoLibInt32Array;
  272. i, coord: Int32;
  273. begin
  274. n := x9ECParameters.n;
  275. g := x9ECParameters.g;
  276. c := x9ECParameters.curve;
  277. coords := TECCurve.GetAllCoordinateSystems();
  278. i := 0;
  279. while i < System.Length(coords) do
  280. begin
  281. coord := coords[i];
  282. if (c.SupportsCoordinateSystem(coord)) then
  283. begin
  284. sc := c;
  285. sg := g;
  286. if (sc.CoordinateSystem <> coord) then
  287. begin
  288. sc := c.Configure().SetCoordinateSystem(coord).CreateCurve();
  289. sg := sc.ImportPoint(g);
  290. end;
  291. // The generator is multiplied by random b to get random q
  292. b := TBigInteger.Create(n.BitLength, FRandom);
  293. q := sg.Multiply(b).Normalize();
  294. ImplAddSubtractMultiplyTwiceEncodingTest(sc, q, n);
  295. ImplSqrtTest(sc);
  296. ImplValidityTest(sc, sg);
  297. end;
  298. System.Inc(i);
  299. end;
  300. end;
  301. procedure TTestECPoint.ImplSqrtTest(const c: IECCurve);
  302. var
  303. p, pMinusOne, legendreExponent, nonSquare, x: TBigInteger;
  304. m, count, i: Int32;
  305. root, fe, sq, check: IECFieldElement;
  306. begin
  307. if (TECAlgorithms.IsFpCurve(c)) then
  308. begin
  309. p := c.Field.Characteristic;
  310. pMinusOne := p.Subtract(TBigInteger.One);
  311. legendreExponent := p.ShiftRight(1);
  312. count := 0;
  313. while (count < 10) do
  314. begin
  315. nonSquare := TBigIntegers.CreateRandomInRange(TBigInteger.Two,
  316. pMinusOne, FRandom);
  317. if (not nonSquare.ModPow(legendreExponent, p).Equals(TBigInteger.One))
  318. then
  319. begin
  320. root := c.FromBigInteger(nonSquare).Sqrt();
  321. CheckNull(root);
  322. System.Inc(count);
  323. end;
  324. end
  325. end
  326. else if (TECAlgorithms.IsF2mCurve(c)) then
  327. begin
  328. m := c.FieldSize;
  329. x := TBigInteger.Create(m, FRandom);
  330. fe := c.FromBigInteger(x);
  331. i := 0;
  332. while i < 100 do
  333. begin
  334. sq := fe.Square();
  335. check := sq.Sqrt();
  336. AssertECFieldElementsEqual(fe, check);
  337. fe := sq;
  338. System.Inc(i);
  339. end;
  340. end;
  341. end;
  342. procedure TTestECPoint.ImplTestAdd(const p: TCryptoLibGenericArray<IECPoint>;
  343. const infinity: IECPoint);
  344. var
  345. i: Int32;
  346. begin
  347. AssertPointsEqual('p0 plus p1 does not equal p2', p[2], p[0].Add(p[1]));
  348. AssertPointsEqual('p1 plus p0 does not equal p2', p[2], p[1].Add(p[0]));
  349. for i := 0 to System.Pred(System.Length(p)) do
  350. begin
  351. AssertPointsEqual('Adding infinity failed', p[i], p[i].Add(infinity));
  352. AssertPointsEqual('Adding to infinity failed', p[i], infinity.Add(p[i]));
  353. end;
  354. end;
  355. procedure TTestECPoint.ImplTestAddSubtract(const p, infinity: IECPoint);
  356. begin
  357. AssertPointsEqual('Twice and Add inconsistent', p.Twice(), p.Add(p));
  358. AssertPointsEqual('Twice p - p is not p', p, p.Twice().Subtract(p));
  359. AssertPointsEqual('TwicePlus(p, -p) is not p', p, p.TwicePlus(p.Negate()));
  360. AssertPointsEqual('p - p is not infinity', infinity, p.Subtract(p));
  361. AssertPointsEqual('p plus infinity is not p', p, p.Add(infinity));
  362. AssertPointsEqual('infinity plus p is not p', p, infinity.Add(p));
  363. AssertPointsEqual('infinity plus infinity is not infinity ', infinity,
  364. infinity.Add(infinity));
  365. AssertPointsEqual('Twice infinity is not infinity ', infinity,
  366. infinity.Twice());
  367. end;
  368. procedure TTestECPoint.ImplTestAllPoints(const p, infinity: IECPoint);
  369. var
  370. adder, multiplier: IECPoint;
  371. i: TBigInteger;
  372. begin
  373. adder := infinity;
  374. multiplier := infinity;
  375. i := TBigInteger.One;
  376. repeat
  377. adder := adder.Add(p);
  378. multiplier := p.Multiply(i);
  379. AssertPointsEqual('Results of Add() and Multiply() are inconsistent ' +
  380. i.ToString, adder, multiplier);
  381. i := i.Add(TBigInteger.One);
  382. until ((adder.Equals(infinity)));
  383. end;
  384. procedure TTestECPoint.ImplTestEncoding(const p: IECPoint);
  385. var
  386. unCompBarr, compBarr: TBytes;
  387. decUnComp, decComp: IECPoint;
  388. begin
  389. // Not Point Compression
  390. unCompBarr := p.GetEncoded(false);
  391. decUnComp := p.curve.DecodePoint(unCompBarr);
  392. AssertPointsEqual('Error decoding uncompressed point', p, decUnComp);
  393. // Point compression
  394. compBarr := p.GetEncoded(True);
  395. decComp := p.curve.DecodePoint(compBarr);
  396. AssertPointsEqual('Error decoding compressed point', p, decComp);
  397. end;
  398. procedure TTestECPoint.ImplTestMultiply(const p: IECPoint; numBits: Int32);
  399. var
  400. k: TBigInteger;
  401. reff, q: IECPoint;
  402. begin
  403. k := TBigInteger.Create(numBits, FRandom);
  404. reff := TECAlgorithms.ReferenceMultiply(p, k);
  405. q := p.Multiply(k);
  406. AssertPointsEqual('ECPoint.Multiply is incorrect', reff, q);
  407. end;
  408. procedure TTestECPoint.ImplTestMultiplyAll(const p: IECPoint; numBits: Int32);
  409. var
  410. bound, k: TBigInteger;
  411. reff, q: IECPoint;
  412. begin
  413. bound := TBigInteger.One.ShiftLeft(numBits);
  414. k := TBigInteger.Zero;
  415. repeat
  416. reff := TECAlgorithms.ReferenceMultiply(p, k);
  417. q := p.Multiply(k);
  418. AssertPointsEqual('ECPoint.Multiply is incorrect', reff, q);
  419. k := k.Add(TBigInteger.One);
  420. until (not(k.CompareTo(bound) < 0));
  421. end;
  422. procedure TTestECPoint.ImplTestThreeTimes
  423. (const p: TCryptoLibGenericArray<IECPoint>);
  424. var
  425. Lp, _3P: IECPoint;
  426. begin
  427. Lp := p[0];
  428. _3P := Lp.Add(Lp).Add(Lp);
  429. AssertPointsEqual('ThreeTimes incorrect', _3P, Lp.ThreeTimes());
  430. AssertPointsEqual('TwicePlus incorrect', _3P, Lp.TwicePlus(Lp));
  431. end;
  432. procedure TTestECPoint.ImplTestTwice(const p: TCryptoLibGenericArray<IECPoint>);
  433. begin
  434. AssertPointsEqual('Twice incorrect', p[3], p[0].Twice());
  435. AssertPointsEqual('Add same point incorrect', p[3], p[0].Add(p[0]));
  436. end;
  437. procedure TTestECPoint.ImplValidityTest(const c: IECCurve; const g: IECPoint);
  438. var
  439. h: TBigInteger;
  440. order2, bad: IECPoint;
  441. begin
  442. CheckTrue(g.IsValid());
  443. h := c.getCofactor();
  444. if ((h.IsInitialized) and (h.CompareTo(TBigInteger.One) > 0)) then
  445. begin
  446. if (TECAlgorithms.IsF2mCurve(c)) then
  447. begin
  448. order2 := c.CreatePoint(TBigInteger.Zero, c.b.Sqrt().ToBigInteger());
  449. bad := g.Add(order2);
  450. CheckFalse(bad.IsValid());
  451. end;
  452. end;
  453. end;
  454. procedure TTestECPoint.SetUp;
  455. begin
  456. inherited;
  457. FRandom := TSecureRandom.Create();
  458. FpInstance := TFp.Create;
  459. FpInstance.CreatePoints;
  460. F2mInstance := TF2m.Create;
  461. F2mInstance.CreatePoints;
  462. end;
  463. procedure TTestECPoint.TearDown;
  464. begin
  465. inherited;
  466. FpInstance.Free;
  467. F2mInstance.Free;
  468. end;
  469. procedure TTestECPoint.TestAdd;
  470. begin
  471. ImplTestAdd(FpInstance.Fp, FpInstance.FInfinity);
  472. ImplTestAdd(F2mInstance.Fp, F2mInstance.FInfinity);
  473. end;
  474. procedure TTestECPoint.TestAddSubtractMultiplySimple;
  475. var
  476. fpBits, iFp, f2mBits, iF2m: Int32;
  477. begin
  478. fpBits := FpInstance.Fcurve.Order.BitLength;
  479. for iFp := 0 to System.Pred(System.Length(FpInstance.FpointSource) div 2) do
  480. begin
  481. ImplTestAddSubtract(FpInstance.Fp[iFp], FpInstance.FInfinity);
  482. ImplTestMultiplyAll(FpInstance.Fp[iFp], fpBits);
  483. ImplTestMultiplyAll(FpInstance.FInfinity, fpBits);
  484. end;
  485. f2mBits := F2mInstance.Fcurve.Order.BitLength;
  486. for iF2m := 0 to System.Pred(System.Length(F2mInstance.FpointSource) div 2) do
  487. begin
  488. ImplTestAddSubtract(F2mInstance.Fp[iF2m], F2mInstance.FInfinity);
  489. ImplTestMultiplyAll(F2mInstance.Fp[iF2m], f2mBits);
  490. ImplTestMultiplyAll(F2mInstance.FInfinity, f2mBits);
  491. end;
  492. end;
  493. procedure TTestECPoint.TestAddSubtractMultiplyTwiceEncoding;
  494. var
  495. tempList: TList<String>;
  496. tempDict: TDictionary<String, String>;
  497. uniqNames: TCryptoLibStringArray;
  498. s, name: string;
  499. x9A, x9B: IX9ECParameters;
  500. pA, pB: IECPoint;
  501. k: TBigInteger;
  502. begin
  503. tempList := TList<String>.Create();
  504. try
  505. tempList.AddRange(TECNamedCurveTable.names); // get all collections
  506. tempList.AddRange(TCustomNamedCurves.names);
  507. tempDict := TDictionary<String, String>.Create();
  508. try
  509. for s in tempList do
  510. begin
  511. tempDict.AddOrSetValue(s, s); // make sure they are unique
  512. end;
  513. uniqNames := tempDict.Values.ToArray; // save unique instances to array
  514. finally
  515. tempDict.Free;
  516. end;
  517. finally
  518. tempList.Free;
  519. end;
  520. for name in uniqNames do
  521. begin
  522. x9A := TECNamedCurveTable.GetByName(name);
  523. x9B := TCustomNamedCurves.GetByName(name);
  524. if ((x9A <> Nil) and (x9B <> Nil)) then
  525. begin
  526. AssertIFiniteFieldsEqual(x9A.curve.Field, x9B.curve.Field);
  527. AssertBigIntegersEqual(x9A.curve.a.ToBigInteger(),
  528. x9B.curve.a.ToBigInteger());
  529. AssertBigIntegersEqual(x9A.curve.b.ToBigInteger(),
  530. x9B.curve.b.ToBigInteger());
  531. AssertOptionalValuesAgree(x9A.curve.Cofactor, x9B.curve.Cofactor);
  532. AssertOptionalValuesAgree(x9A.curve.Order, x9B.curve.Order);
  533. AssertPointsEqual('Custom curve base-point inconsistency', x9A.g, x9B.g);
  534. AssertBigIntegersEqual(x9A.h, x9B.h);
  535. AssertBigIntegersEqual(x9A.n, x9B.n);
  536. AssertOptionalValuesAgree(x9A.GetSeed(), x9B.GetSeed());
  537. k := TBigInteger.Create(x9A.n.BitLength, FRandom);
  538. pA := x9A.g.Multiply(k);
  539. pB := x9B.g.Multiply(k);
  540. AssertPointsEqual('Custom curve multiplication inconsistency', pA, pB);
  541. end;
  542. if (x9A <> Nil) then
  543. begin
  544. ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9A);
  545. end;
  546. if (x9B <> Nil) then
  547. begin
  548. ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9B);
  549. end;
  550. end;
  551. end;
  552. procedure TTestECPoint.TestAllPoints;
  553. var
  554. i: Int32;
  555. begin
  556. i := 0;
  557. while i < System.Length(FpInstance.Fp) do
  558. begin
  559. ImplTestAllPoints(FpInstance.Fp[i], FpInstance.FInfinity);
  560. System.Inc(i);
  561. end;
  562. i := 0;
  563. while i < System.Length(F2mInstance.Fp) do
  564. begin
  565. ImplTestAllPoints(F2mInstance.Fp[i], F2mInstance.FInfinity);
  566. System.Inc(i);
  567. end;
  568. end;
  569. procedure TTestECPoint.TestPointCreationConsistency;
  570. begin
  571. try
  572. FpInstance.Fcurve.CreatePoint(TBigInteger.ValueOf(12),
  573. Default (TBigInteger));
  574. Fail('expected EArgumentCryptoLibException');
  575. except
  576. on e: EArgumentCryptoLibException do
  577. begin
  578. // expected
  579. end;
  580. end;
  581. try
  582. FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
  583. TBigInteger.ValueOf(12));
  584. Fail('expected EArgumentCryptoLibException');
  585. except
  586. on e: EArgumentCryptoLibException do
  587. begin
  588. // expected
  589. end;
  590. end;
  591. try
  592. FpInstance.Fcurve.CreatePoint(TBigInteger.Create('1011'),
  593. Default (TBigInteger));
  594. Fail('expected EArgumentCryptoLibException');
  595. except
  596. on e: EArgumentCryptoLibException do
  597. begin
  598. // expected
  599. end;
  600. end;
  601. try
  602. FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
  603. TBigInteger.Create('1011'));
  604. Fail('expected EArgumentCryptoLibException');
  605. except
  606. on e: EArgumentCryptoLibException do
  607. begin
  608. // expected
  609. end;
  610. end;
  611. end;
  612. procedure TTestECPoint.TestThreeTimes;
  613. begin
  614. ImplTestThreeTimes(FpInstance.Fp);
  615. ImplTestThreeTimes(F2mInstance.Fp);
  616. end;
  617. procedure TTestECPoint.TestTwice;
  618. begin
  619. ImplTestTwice(FpInstance.Fp);
  620. ImplTestTwice(F2mInstance.Fp);
  621. end;
  622. { TFp }
  623. constructor TFp.Create;
  624. begin
  625. Fq := TBigInteger.Create('29');
  626. Fa := TBigInteger.Create('4');
  627. Fb := TBigInteger.Create('20');
  628. Fn := TBigInteger.Create('38');
  629. Fh := TBigInteger.Create('1');
  630. Fcurve := TFpCurve.Create(Fq, Fa, Fb, Fn, Fh);
  631. FInfinity := Fcurve.infinity;
  632. FpointSource := TCryptoLibInt32Array.Create(5, 22, 16, 27, 13, 6, 14, 6);
  633. System.SetLength(Fp, System.Length(FpointSource) div 2);
  634. end;
  635. procedure TFp.CreatePoints;
  636. var
  637. i: Int32;
  638. begin
  639. for i := 0 to System.Pred(System.Length(FpointSource) div 2) do
  640. begin
  641. Fp[i] := Fcurve.CreatePoint(TBigInteger.Create(IntToStr(FpointSource[2 * i])
  642. ), TBigInteger.Create(IntToStr(FpointSource[2 * i + 1])));
  643. end;
  644. end;
  645. { TF2m }
  646. constructor TF2m.Create;
  647. begin
  648. // a = z^3
  649. FaTpb := TBigInteger.Create('1000', 2);
  650. // b = z^3 + 1
  651. FbTpb := TBigInteger.Create('1001', 2);
  652. Fn := TBigInteger.Create('23');
  653. Fh := TBigInteger.Create('1');
  654. Fcurve := TF2mCurve.Create(m, k1, FaTpb, FbTpb, Fn, Fh);
  655. FInfinity := Fcurve.infinity;
  656. FpointSource := TCryptoLibStringArray.Create('0010', '1111', '1100', '1100',
  657. '0001', '0001', '1011', '0010');
  658. System.SetLength(Fp, System.Length(FpointSource) div 2);
  659. end;
  660. procedure TF2m.CreatePoints;
  661. var
  662. i: Int32;
  663. begin
  664. for i := 0 to System.Pred(System.Length(FpointSource) div 2) do
  665. begin
  666. Fp[i] := Fcurve.CreatePoint(TBigInteger.Create(FpointSource[2 * i], 2),
  667. TBigInteger.Create(FpointSource[(2 * i) + 1], 2));
  668. end;
  669. end;
  670. initialization
  671. // Register any test cases with the test runner
  672. {$IFDEF FPC}
  673. RegisterTest(TTestECPoint);
  674. {$ELSE}
  675. RegisterTest(TTestECPoint.Suite);
  676. {$ENDIF FPC}
  677. end.