ECPointTests.pas 21 KB

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