2
0

ClpECCurve.pas 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862
  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 ClpECCurve;
  14. {$I ..\..\Include\CryptoLib.inc}
  15. interface
  16. uses
  17. SyncObjs,
  18. SysUtils,
  19. Generics.Collections,
  20. ClpECPoint,
  21. ClpCryptoLibTypes,
  22. ClpBigInteger,
  23. ClpBits,
  24. ClpIGlvEndomorphism,
  25. ClpECAlgorithms,
  26. ClpIECFieldElement,
  27. ClpECFieldElement,
  28. ClpLongArray,
  29. ClpGlvMultiplier,
  30. ClpWNafL2RMultiplier,
  31. ClpWTauNafMultiplier,
  32. ClpFiniteFields,
  33. ClpTnaf,
  34. ClpIECInterface,
  35. ClpIFiniteField,
  36. ClpIPreCompInfo;
  37. resourcestring
  38. SUnSupportedCoordinateSystem = 'UnSupported Coordinate System';
  39. SCurrentCurve = 'Implementation returned Current Curve';
  40. SInvalidPointCoordinates = 'Invalid Point Coordinates';
  41. SInvalidAffineCoordinates = 'not valid for affine coordinates, "iso"';
  42. SInvalidPointOnCurve = 'must be non-null and on this curve, "point"';
  43. SInvalidPointOnCurve2 = 'Entries must be null or on this curve, "points"';
  44. SPointsNil = 'points';
  45. SInvalidRangeSpecified = 'Invalid Range Specified", "points"';
  46. SInvalidPointCompression = 'Invalid Point Compression';
  47. SInvalidK1 = 'k1 must be > 0';
  48. SInvalidK3 = 'k3 must be 0 if k2 == 0';
  49. SK2K1MisMatch = 'k2 must be > k1';
  50. SK3K2Mismatch = 'k3 must be > k2';
  51. SInvalidInfinityEncoding = 'Invalid Infinity Encoding, "encoded"';
  52. SInvalidPointEncoding = 'Invalid Point Encoding %u';
  53. SIncorrectLengthInfinityEncoding =
  54. 'Incorrect Length for infinity encoding", "encoded"';
  55. SIncorrectLengthCompressedEncoding =
  56. 'Incorrect Length for Compressed Encoding", "encoded"';
  57. SInvalidPoint = 'Invalid Point';
  58. SIncorrectLengthUnCompressedEncoding =
  59. 'Incorrect Length for UnCompressed Encoding", "encoded"';
  60. SIncorrectLengthHybridEncoding =
  61. 'Incorrect Length for Hybrid Encoding", "encoded"';
  62. SInConsistentYCoord =
  63. 'Inconsistent Y Coordinate in Hybrid Encoding", "encoded"';
  64. type
  65. /// <summary>
  66. /// Base class for an elliptic curve.
  67. /// </summary>
  68. TECCurve = class abstract(TInterfacedObject, IECCurve)
  69. strict private
  70. procedure SetCoord(const Value: Int32); inline;
  71. procedure SetEndomorphism(const Value: IECEndomorphism); inline;
  72. procedure SetMultiplier(const Value: IECMultiplier); inline;
  73. function GetField: IFiniteField; virtual;
  74. function GetA: IECFieldElement; virtual;
  75. function GetB: IECFieldElement; virtual;
  76. function GetOrder: TBigInteger; virtual;
  77. function GetCofactor: TBigInteger; virtual;
  78. function GetCoordinateSystem: Int32; virtual;
  79. class constructor CreateECCurve();
  80. class destructor DestroyECCurve();
  81. strict protected
  82. class var
  83. FLock: TCriticalSection;
  84. var
  85. Fm_field: IFiniteField;
  86. Fm_order, Fm_cofactor: TBigInteger;
  87. Fm_coord: Int32;
  88. Fm_endomorphism: IECEndomorphism;
  89. Fm_multiplier: IECMultiplier;
  90. Fm_a, Fm_b: IECFieldElement;
  91. constructor Create(const field: IFiniteField);
  92. function CloneCurve(): IECCurve; virtual; abstract;
  93. function CreateRawPoint(const x, y: IECFieldElement;
  94. withCompression: Boolean): IECPoint; overload; virtual; abstract;
  95. function CreateRawPoint(const x, y: IECFieldElement;
  96. zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
  97. : IECPoint; overload; virtual; abstract;
  98. function CreateDefaultMultiplier(): IECMultiplier; virtual;
  99. procedure CheckPoint(const point: IECPoint); virtual;
  100. procedure CheckPoints(points: TCryptoLibGenericArray<IECPoint>);
  101. overload; virtual;
  102. procedure CheckPoints(points: TCryptoLibGenericArray<IECPoint>;
  103. off, len: Int32); overload; virtual;
  104. function DecompressPoint(yTilde: Int32; X1: TBigInteger): IECPoint;
  105. virtual; abstract;
  106. public
  107. const
  108. COORD_AFFINE = Int32(0);
  109. COORD_HOMOGENEOUS = Int32(1);
  110. COORD_JACOBIAN = Int32(2);
  111. COORD_JACOBIAN_CHUDNOVSKY = Int32(3);
  112. COORD_JACOBIAN_MODIFIED = Int32(4);
  113. COORD_LAMBDA_AFFINE = Int32(5);
  114. COORD_LAMBDA_PROJECTIVE = Int32(6);
  115. COORD_SKEWED = Int32(7);
  116. type
  117. TConfig = class(TInterfacedObject, IConfig)
  118. strict protected
  119. var
  120. Fouter: IECCurve;
  121. Fcoord: Int32;
  122. Fendomorphism: IECEndomorphism;
  123. Fmultiplier: IECMultiplier;
  124. public
  125. constructor Create(const outer: IECCurve; coord: Int32;
  126. const endomorphism: IECEndomorphism;
  127. const multiplier: IECMultiplier); overload;
  128. destructor Destroy(); override;
  129. function SetCoordinateSystem(coord: Int32): IConfig; inline;
  130. function SetEndomorphism(const endomorphism: IECEndomorphism)
  131. : IConfig; inline;
  132. function SetMultiplier(const multiplier: IECMultiplier): IConfig; inline;
  133. function CreateCurve(): IECCurve;
  134. end;
  135. function GetFieldSize: Int32; virtual; abstract;
  136. function GetInfinity: IECPoint; virtual; abstract;
  137. function FromBigInteger(x: TBigInteger): IECFieldElement; virtual; abstract;
  138. function IsValidFieldElement(x: TBigInteger): Boolean; virtual; abstract;
  139. function Configure(): IConfig; virtual;
  140. function ValidatePoint(const x, y: TBigInteger): IECPoint; overload; virtual;
  141. function ValidatePoint(const x, y: TBigInteger; withCompression: Boolean)
  142. : IECPoint; overload; virtual;
  143. deprecated 'Per-point compression property will be removed';
  144. /// <summary>
  145. /// Create a cache-safe lookup table for the specified sequence of points.
  146. /// All the points MUST <br />belong to this <c>ECCurve</c> instance, and
  147. /// MUST already be normalized.
  148. /// </summary>
  149. function CreateCacheSafeLookupTable(points: TCryptoLibGenericArray<IECPoint>;
  150. off, len: Int32): IECLookupTable; virtual;
  151. function CreatePoint(const x, y: TBigInteger): IECPoint; overload; virtual;
  152. function CreatePoint(const x, y: TBigInteger; withCompression: Boolean)
  153. : IECPoint; overload; virtual;
  154. deprecated 'Per-point compression property will be removed';
  155. function SupportsCoordinateSystem(coord: Int32): Boolean; virtual;
  156. function GetPreCompInfo(const point: IECPoint; const name: String)
  157. : IPreCompInfo; virtual;
  158. /// <summary>
  159. /// Adds <c>PreCompInfo</c> for a point on this curve, under a given name.
  160. /// Used by <c>ECMultiplier</c> to save the precomputation for this <c>
  161. /// ECPoint</c> for use by subsequent multiplication.
  162. /// </summary>
  163. /// <param name="point">
  164. /// The <c>ECPoint</c> to store precomputations for.
  165. /// </param>
  166. /// <param name="name">
  167. /// A <c>String</c> used to index precomputations of different types.
  168. /// </param>
  169. /// <param name="preCompInfo">
  170. /// The values precomputed by the <c>ECMultiplier.</c>
  171. /// </param>
  172. procedure SetPreCompInfo(const point: IECPoint; const name: String;
  173. const preCompInfo: IPreCompInfo); virtual;
  174. function ImportPoint(const p: IECPoint): IECPoint; virtual;
  175. /// <summary>
  176. /// Normalization ensures that any projective coordinate is 1, and
  177. /// therefore that the x, y coordinates reflect those of the equivalent
  178. /// point in an affine coordinate system. Where more than one point is to
  179. /// be normalized, this method will generally be more efficient than
  180. /// normalizing each point separately.
  181. /// </summary>
  182. /// <param name="points">
  183. /// An array of points that will be updated in place with their normalized
  184. /// versions, where necessary
  185. /// </param>
  186. procedure NormalizeAll(points: TCryptoLibGenericArray<IECPoint>);
  187. overload; virtual;
  188. /// <summary>
  189. /// Normalization ensures that any projective coordinate is 1, and
  190. /// therefore that the x, y coordinates reflect those of the equivalent
  191. /// point in an affine coordinate system. Where more than one point is to
  192. /// be normalized, this method will generally be more efficient than
  193. /// normalizing each point separately. An (optional) z-scaling factor can
  194. /// be applied; effectively each z coordinate is scaled by this value prior
  195. /// to normalization (but only one actual multiplication is needed).
  196. /// </summary>
  197. /// <param name="points">
  198. /// An array of points that will be updated in place with their normalized
  199. /// versions, where necessary
  200. /// </param>
  201. /// <param name="off">
  202. /// The start of the range of points to normalize
  203. /// </param>
  204. /// <param name="len">
  205. /// The length of the range of points to normalize
  206. /// </param>
  207. /// <param name="iso">
  208. /// The (optional) z-scaling factor - can be null
  209. /// </param>
  210. procedure NormalizeAll(points: TCryptoLibGenericArray<IECPoint>;
  211. off, len: Int32; const iso: IECFieldElement); overload; virtual;
  212. function GetEndomorphism(): IECEndomorphism; virtual;
  213. /// <summary>
  214. /// Sets the default <c>ECMultiplier</c>, unless already set.
  215. /// </summary>
  216. function GetMultiplier(): IECMultiplier; virtual;
  217. /// <summary>
  218. /// Decode a point on this curve from its ASN.1 encoding. The different
  219. /// encodings are taken account of, including point compression for <br /><c>
  220. /// F</c><b>p</b> (X9.62 s 4.2.1 pg 17).
  221. /// </summary>
  222. /// <returns>
  223. /// The decoded point.
  224. /// </returns>
  225. function DecodePoint(encoded: TCryptoLibByteArray): IECPoint; virtual;
  226. property coord: Int32 write SetCoord;
  227. property endomorphism: IECEndomorphism write SetEndomorphism;
  228. property multiplier: IECMultiplier write SetMultiplier;
  229. property FieldSize: Int32 read GetFieldSize;
  230. property Infinity: IECPoint read GetInfinity;
  231. property field: IFiniteField read GetField;
  232. property A: IECFieldElement read GetA;
  233. property B: IECFieldElement read GetB;
  234. property Order: TBigInteger read GetOrder;
  235. property Cofactor: TBigInteger read GetCofactor;
  236. property CoordinateSystem: Int32 read GetCoordinateSystem;
  237. function Equals(const other: IECCurve): Boolean; reintroduce;
  238. function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
  239. {$ENDIF DELPHI}override;
  240. destructor Destroy; override;
  241. class function GetAllCoordinateSystems(): TCryptoLibInt32Array;
  242. static; inline;
  243. end;
  244. type
  245. TDefaultLookupTable = class(TInterfacedObject, IDefaultLookupTable,
  246. IECLookupTable)
  247. strict private
  248. var
  249. Fm_outer: IECCurve;
  250. Fm_table: TCryptoLibByteArray;
  251. Fm_size: Int32;
  252. public
  253. constructor Create(const outer: IECCurve; table: TCryptoLibByteArray;
  254. size: Int32);
  255. function GetSize: Int32; virtual;
  256. function Lookup(index: Int32): IECPoint; virtual;
  257. property size: Int32 read GetSize;
  258. end;
  259. type
  260. TAbstractFpCurve = class(TECCurve, IAbstractFpCurve)
  261. strict protected
  262. constructor Create(const q: TBigInteger);
  263. function DecompressPoint(yTilde: Int32; X1: TBigInteger): IECPoint;
  264. override;
  265. public
  266. destructor Destroy; override;
  267. function IsValidFieldElement(x: TBigInteger): Boolean; override;
  268. end;
  269. type
  270. TDefaultF2mLookupTable = class(TInterfacedObject, IDefaultF2mLookupTable,
  271. IECLookupTable)
  272. strict private
  273. var
  274. Fm_outer: IF2mCurve;
  275. Fm_table: TCryptoLibInt64Array;
  276. Fm_size: Int32;
  277. public
  278. constructor Create(const outer: IF2mCurve; table: TCryptoLibInt64Array;
  279. size: Int32);
  280. function GetSize: Int32; virtual;
  281. function Lookup(index: Int32): IECPoint; virtual;
  282. property size: Int32 read GetSize;
  283. end;
  284. type
  285. TFpCurve = class(TAbstractFpCurve, IFpCurve)
  286. strict private
  287. const
  288. FP_DEFAULT_COORDS = Int32(TECCurve.COORD_JACOBIAN_MODIFIED);
  289. function GetQ: TBigInteger; virtual;
  290. strict protected
  291. var
  292. Fm_q, Fm_r: TBigInteger;
  293. Fm_infinity: IFpPoint;
  294. constructor Create(const q, r: TBigInteger;
  295. const A, B: IECFieldElement); overload;
  296. constructor Create(const q, r: TBigInteger; const A, B: IECFieldElement;
  297. const Order, Cofactor: TBigInteger); overload;
  298. function CloneCurve(): IECCurve; override;
  299. function CreateRawPoint(const x, y: IECFieldElement;
  300. withCompression: Boolean): IECPoint; overload; override;
  301. function CreateRawPoint(const x, y: IECFieldElement;
  302. zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
  303. : IECPoint; overload; override;
  304. public
  305. constructor Create(const q, A, B: TBigInteger); overload;
  306. constructor Create(const q, A, B, Order, Cofactor: TBigInteger); overload;
  307. destructor Destroy; override;
  308. function GetInfinity: IECPoint; override;
  309. function GetFieldSize: Int32; override;
  310. function FromBigInteger(x: TBigInteger): IECFieldElement; override;
  311. function ImportPoint(const p: IECPoint): IECPoint; override;
  312. function SupportsCoordinateSystem(coord: Int32): Boolean; override;
  313. property q: TBigInteger read GetQ;
  314. property Infinity: IECPoint read GetInfinity;
  315. property FieldSize: Int32 read GetFieldSize;
  316. end;
  317. type
  318. TAbstractF2mCurve = class abstract(TECCurve, IAbstractF2mCurve)
  319. strict private
  320. /// <summary>
  321. /// The auxiliary values <c>s</c><b>0</b> and <c>s</c><b>1</b> used for
  322. /// partial modular reduction for Koblitz curves.
  323. /// </summary>
  324. Fsi: TCryptoLibGenericArray<TBigInteger>;
  325. /// <summary>
  326. /// Returns true if this is a Koblitz curve (ABC curve).
  327. /// </summary>
  328. /// <returns>
  329. /// true if this is a Koblitz curve (ABC curve), false otherwise
  330. /// </returns>
  331. function GetIsKoblitz: Boolean; virtual;
  332. class function BuildField(m, k1, k2, k3: Int32): IFiniteField; static;
  333. // /**
  334. // * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
  335. // * D.1.6) The other solution is <code>z + 1</code>.
  336. // *
  337. // * @param beta
  338. // * The value to solve the qradratic equation for.
  339. // * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
  340. // * <code>null</code> if no solution exists.
  341. // */
  342. function SolveQuadradicEquation(const beta: IECFieldElement)
  343. : IECFieldElement;
  344. strict protected
  345. constructor Create(m, k1, k2, k3: Int32);
  346. function DecompressPoint(yTilde: Int32; X1: TBigInteger): IECPoint;
  347. override;
  348. public
  349. destructor Destroy; override;
  350. function IsValidFieldElement(x: TBigInteger): Boolean; override;
  351. function CreatePoint(const x, y: TBigInteger; withCompression: Boolean)
  352. : IECPoint; override;
  353. deprecated 'Per-point compression property will be removed';
  354. // /**
  355. // * @return the auxiliary values <code>s<sub>0</sub></code> and
  356. // * <code>s<sub>1</sub></code> used for partial modular reduction for
  357. // * Koblitz curves.
  358. // */
  359. function GetSi(): TCryptoLibGenericArray<TBigInteger>; virtual;
  360. property IsKoblitz: Boolean read GetIsKoblitz;
  361. class function Inverse(m: Int32; ks: TCryptoLibInt32Array;
  362. const x: TBigInteger): TBigInteger; static; inline;
  363. end;
  364. type
  365. // /**
  366. // * Elliptic curves over F2m. The Weierstrass equation is given by
  367. // * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
  368. // */
  369. TF2mCurve = class sealed(TAbstractF2mCurve, IF2mCurve)
  370. strict private
  371. const
  372. F2M_DEFAULT_COORDS = Int32(TECCurve.COORD_LAMBDA_PROJECTIVE);
  373. var
  374. // /**
  375. // * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
  376. // */
  377. Fm: Int32;
  378. // /**
  379. // * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
  380. // * x<sup>k</sup> + 1</code> represents the reduction polynomial
  381. // * <code>f(z)</code>.<br/>
  382. // * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
  383. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  384. // * represents the reduction polynomial <code>f(z)</code>.<br/>
  385. // */
  386. Fk1: Int32;
  387. // /**
  388. // * TPB: Always set to <code>0</code><br/>
  389. // * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
  390. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  391. // * represents the reduction polynomial <code>f(z)</code>.<br/>
  392. // */
  393. Fk2: Int32;
  394. //
  395. // /**
  396. // * TPB: Always set to <code>0</code><br/>
  397. // * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
  398. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  399. // * represents the reduction polynomial <code>f(z)</code>.<br/>
  400. // */
  401. Fk3: Int32;
  402. /// <summary>
  403. /// The point at infinity on this curve.
  404. /// </summary>
  405. Fm_infinity: IF2mPoint;
  406. constructor Create(m, k1, k2, k3: Int32; const A, B: IECFieldElement;
  407. const Order, Cofactor: TBigInteger); overload;
  408. function GetM: Int32; inline;
  409. function GetK1: Int32; inline;
  410. function GetK2: Int32; inline;
  411. function GetK3: Int32; inline;
  412. strict protected
  413. function CloneCurve(): IECCurve; override;
  414. function CreateDefaultMultiplier(): IECMultiplier; override;
  415. function CreateRawPoint(const x, y: IECFieldElement;
  416. withCompression: Boolean): IECPoint; overload; override;
  417. function CreateRawPoint(const x, y: IECFieldElement;
  418. zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
  419. : IECPoint; overload; override;
  420. public
  421. // /**
  422. // * Constructor for Trinomial Polynomial Basis (TPB).
  423. // * @param m The exponent <code>m</code> of
  424. // * <code>F<sub>2<sup>m</sup></sub></code>.
  425. // * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
  426. // * x<sup>k</sup> + 1</code> represents the reduction
  427. // * polynomial <code>f(z)</code>.
  428. // * @param a The coefficient <code>a</code> in the Weierstrass equation
  429. // * for non-supersingular elliptic curves over
  430. // * <code>F<sub>2<sup>m</sup></sub></code>.
  431. // * @param b The coefficient <code>b</code> in the Weierstrass equation
  432. // * for non-supersingular elliptic curves over
  433. // * <code>F<sub>2<sup>m</sup></sub></code>.
  434. // */
  435. constructor Create(m, k: Int32; const A, B: TBigInteger); overload;
  436. // /**
  437. // * Constructor for Trinomial Polynomial Basis (TPB).
  438. // * @param m The exponent <code>m</code> of
  439. // * <code>F<sub>2<sup>m</sup></sub></code>.
  440. // * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
  441. // * x<sup>k</sup> + 1</code> represents the reduction
  442. // * polynomial <code>f(z)</code>.
  443. // * @param a The coefficient <code>a</code> in the Weierstrass equation
  444. // * for non-supersingular elliptic curves over
  445. // * <code>F<sub>2<sup>m</sup></sub></code>.
  446. // * @param b The coefficient <code>b</code> in the Weierstrass equation
  447. // * for non-supersingular elliptic curves over
  448. // * <code>F<sub>2<sup>m</sup></sub></code>.
  449. // * @param order The order of the main subgroup of the elliptic curve.
  450. // * @param cofactor The cofactor of the elliptic curve, i.e.
  451. // * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
  452. // */
  453. constructor Create(m, k: Int32;
  454. const A, B, Order, Cofactor: TBigInteger); overload;
  455. // /**
  456. // * Constructor for Pentanomial Polynomial Basis (PPB).
  457. // * @param m The exponent <code>m</code> of
  458. // * <code>F<sub>2<sup>m</sup></sub></code>.
  459. // * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
  460. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  461. // * represents the reduction polynomial <code>f(z)</code>.
  462. // * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
  463. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  464. // * represents the reduction polynomial <code>f(z)</code>.
  465. // * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
  466. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  467. // * represents the reduction polynomial <code>f(z)</code>.
  468. // * @param a The coefficient <code>a</code> in the Weierstrass equation
  469. // * for non-supersingular elliptic curves over
  470. // * <code>F<sub>2<sup>m</sup></sub></code>.
  471. // * @param b The coefficient <code>b</code> in the Weierstrass equation
  472. // * for non-supersingular elliptic curves over
  473. // * <code>F<sub>2<sup>m</sup></sub></code>.
  474. // */
  475. constructor Create(m, k1, k2, k3: Int32; const A, B: TBigInteger); overload;
  476. // /**
  477. // * Constructor for Pentanomial Polynomial Basis (PPB).
  478. // * @param m The exponent <code>m</code> of
  479. // * <code>F<sub>2<sup>m</sup></sub></code>.
  480. // * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
  481. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  482. // * represents the reduction polynomial <code>f(z)</code>.
  483. // * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
  484. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  485. // * represents the reduction polynomial <code>f(z)</code>.
  486. // * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
  487. // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  488. // * represents the reduction polynomial <code>f(z)</code>.
  489. // * @param a The coefficient <code>a</code> in the Weierstrass equation
  490. // * for non-supersingular elliptic curves over
  491. // * <code>F<sub>2<sup>m</sup></sub></code>.
  492. // * @param b The coefficient <code>b</code> in the Weierstrass equation
  493. // * for non-supersingular elliptic curves over
  494. // * <code>F<sub>2<sup>m</sup></sub></code>.
  495. // * @param order The order of the main subgroup of the elliptic curve.
  496. // * @param cofactor The cofactor of the elliptic curve, i.e.
  497. // * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
  498. // */
  499. constructor Create(m, k1, k2, k3: Int32;
  500. const A, B, Order, Cofactor: TBigInteger); overload;
  501. destructor Destroy; override;
  502. function GetFieldSize: Int32; override;
  503. function GetInfinity: IECPoint; override;
  504. function SupportsCoordinateSystem(coord: Int32): Boolean; override;
  505. function FromBigInteger(x: TBigInteger): IECFieldElement; override;
  506. /// <summary>
  507. /// Return true if curve uses a Trinomial basis.
  508. /// </summary>
  509. /// <returns>
  510. /// return true if curve Trinomial, false otherwise.
  511. /// </returns>
  512. function IsTrinomial(): Boolean; inline;
  513. function CreateCacheSafeLookupTable
  514. (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32)
  515. : IECLookupTable; override;
  516. property FieldSize: Int32 read GetFieldSize;
  517. property Infinity: IECPoint read GetInfinity;
  518. property m: Int32 read GetM;
  519. property k1: Int32 read GetK1;
  520. property k2: Int32 read GetK2;
  521. property k3: Int32 read GetK3;
  522. end;
  523. implementation
  524. { TECCurve }
  525. procedure TECCurve.CheckPoint(const point: IECPoint);
  526. begin
  527. if ((point = Nil) or ((Self as IECCurve) <> point.Curve)) then
  528. begin
  529. raise EArgumentCryptoLibException.CreateRes(@SInvalidPointOnCurve);
  530. end;
  531. end;
  532. procedure TECCurve.CheckPoints(points: TCryptoLibGenericArray<IECPoint>);
  533. begin
  534. CheckPoints(points, 0, System.Length(points));
  535. end;
  536. procedure TECCurve.CheckPoints(points: TCryptoLibGenericArray<IECPoint>;
  537. off, len: Int32);
  538. var
  539. i: Int32;
  540. point: IECPoint;
  541. begin
  542. if (points = Nil) then
  543. begin
  544. raise EArgumentNilCryptoLibException.CreateRes(@SPointsNil);
  545. end;
  546. if ((off < 0) or (len < 0) or (off > (System.Length(points) - len))) then
  547. begin
  548. raise EArgumentCryptoLibException.CreateRes(@SInvalidRangeSpecified);
  549. end;
  550. for i := 0 to System.Pred(len) do
  551. begin
  552. point := points[off + i];
  553. if ((point <> Nil) and ((Self as IECCurve) <> point.Curve)) then
  554. begin
  555. raise EArgumentCryptoLibException.CreateRes(@SInvalidPointOnCurve2);
  556. end;
  557. end;
  558. end;
  559. function TECCurve.Configure: IConfig;
  560. begin
  561. Result := TConfig.Create(Self as IECCurve, Self.Fm_coord,
  562. Self.Fm_endomorphism, Self.Fm_multiplier);
  563. end;
  564. constructor TECCurve.Create(const field: IFiniteField);
  565. begin
  566. inherited Create();
  567. Fm_field := field;
  568. end;
  569. function TECCurve.CreateCacheSafeLookupTable
  570. (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
  571. var
  572. FE_BYTES, position, i, pxStart, pyStart, pxLen, pyLen: Int32;
  573. table, px, py: TCryptoLibByteArray;
  574. p: IECPoint;
  575. begin
  576. FE_BYTES := (FieldSize + 7) div 8;
  577. System.SetLength(table, len * FE_BYTES * 2);
  578. position := 0;
  579. for i := 0 to System.Pred(len) do
  580. begin
  581. p := points[off + i];
  582. px := p.RawXCoord.ToBigInteger().ToByteArray();
  583. py := p.RawYCoord.ToBigInteger().ToByteArray();
  584. if System.Length(px) > FE_BYTES then
  585. begin
  586. pxStart := 1
  587. end
  588. else
  589. begin
  590. pxStart := 0
  591. end;
  592. pxLen := System.Length(px) - pxStart;
  593. if System.Length(py) > FE_BYTES then
  594. begin
  595. pyStart := 1
  596. end
  597. else
  598. begin
  599. pyStart := 0
  600. end;
  601. pyLen := System.Length(py) - pyStart;
  602. System.Move(px[pxStart], table[position + FE_BYTES - pxLen],
  603. pxLen * System.SizeOf(Byte));
  604. position := position + FE_BYTES;
  605. System.Move(py[pyStart], table[position + FE_BYTES - pyLen],
  606. pyLen * System.SizeOf(Byte));
  607. position := position + FE_BYTES;
  608. end;
  609. Result := TDefaultLookupTable.Create(Self as IECCurve, table, len);
  610. end;
  611. function TECCurve.CreateDefaultMultiplier: IECMultiplier;
  612. var
  613. glvEndomorphism: IGlvEndomorphism;
  614. begin
  615. if (Supports(Fm_endomorphism, IGlvEndomorphism, glvEndomorphism)) then
  616. begin
  617. Result := TGlvMultiplier.Create(Self as IECCurve, glvEndomorphism);
  618. Exit;
  619. end;
  620. Result := TWNafL2RMultiplier.Create();
  621. end;
  622. class constructor TECCurve.CreateECCurve;
  623. begin
  624. FLock := TCriticalSection.Create;
  625. end;
  626. function TECCurve.CreatePoint(const x, y: TBigInteger): IECPoint;
  627. begin
  628. Result := CreatePoint(x, y, false);
  629. end;
  630. function TECCurve.CreatePoint(const x, y: TBigInteger; withCompression: Boolean)
  631. : IECPoint;
  632. begin
  633. Result := CreateRawPoint(FromBigInteger(x), FromBigInteger(y),
  634. withCompression);
  635. end;
  636. function TECCurve.DecodePoint(encoded: TCryptoLibByteArray): IECPoint;
  637. var
  638. x, y: TBigInteger;
  639. p: IECPoint;
  640. expectedLength, yTilde: Int32;
  641. ltype: Byte;
  642. begin
  643. p := Nil;
  644. expectedLength := (FieldSize + 7) div 8;
  645. ltype := encoded[0];
  646. case ltype of
  647. $00: // infinity
  648. begin
  649. if (System.Length(encoded) <> 1) then
  650. begin
  651. raise EArgumentCryptoLibException.CreateRes
  652. (@SIncorrectLengthInfinityEncoding);
  653. end;
  654. p := Infinity;
  655. end;
  656. $02, // compressed
  657. $03: // compressed
  658. begin
  659. if (System.Length(encoded) <> (expectedLength + 1)) then
  660. begin
  661. raise EArgumentCryptoLibException.CreateRes
  662. (@SIncorrectLengthCompressedEncoding);
  663. end;
  664. yTilde := ltype and 1;
  665. x := TBigInteger.Create(1, encoded, 1, expectedLength);
  666. p := DecompressPoint(yTilde, x);
  667. if ((not p.SatisfiesCofactor())) then
  668. begin
  669. raise EArgumentCryptoLibException.CreateRes(@SInvalidPoint);
  670. end;
  671. end;
  672. $04: // uncompressed
  673. begin
  674. if (System.Length(encoded) <> ((2 * expectedLength) + 1)) then
  675. begin
  676. raise EArgumentCryptoLibException.CreateRes
  677. (@SIncorrectLengthUnCompressedEncoding);
  678. end;
  679. x := TBigInteger.Create(1, encoded, 1, expectedLength);
  680. y := TBigInteger.Create(1, encoded, 1 + expectedLength, expectedLength);
  681. p := ValidatePoint(x, y);
  682. end;
  683. $06, // hybrid
  684. $07: // hybrid
  685. begin
  686. if (System.Length(encoded) <> ((2 * expectedLength) + 1)) then
  687. begin
  688. raise EArgumentCryptoLibException.CreateRes
  689. (@SIncorrectLengthHybridEncoding);
  690. end;
  691. x := TBigInteger.Create(1, encoded, 1, expectedLength);
  692. y := TBigInteger.Create(1, encoded, 1 + expectedLength, expectedLength);
  693. if ((y.TestBit(0)) <> (ltype = $07)) then
  694. begin
  695. raise EArgumentCryptoLibException.CreateRes(@SInConsistentYCoord);
  696. end;
  697. p := ValidatePoint(x, y);
  698. end
  699. else
  700. begin
  701. raise EFormatCryptoLibException.CreateResFmt
  702. (@SInvalidPointEncoding, [ltype]);
  703. end;
  704. end;
  705. if ((ltype <> $00) and (p.IsInfinity)) then
  706. begin
  707. raise EArgumentCryptoLibException.CreateRes(@SInvalidInfinityEncoding);
  708. end;
  709. Result := p;
  710. end;
  711. destructor TECCurve.Destroy;
  712. begin
  713. inherited Destroy;
  714. end;
  715. class destructor TECCurve.DestroyECCurve;
  716. begin
  717. FLock.Free;
  718. end;
  719. function TECCurve.Equals(const other: IECCurve): Boolean;
  720. begin
  721. if ((Self as IECCurve) = other) then
  722. begin
  723. Result := true;
  724. Exit;
  725. end;
  726. if (other = Nil) then
  727. begin
  728. Result := false;
  729. Exit;
  730. end;
  731. Result := (field as TObject).Equals(other.field as TObject) and
  732. (A.ToBigInteger().Equals(other.A.ToBigInteger())) and
  733. (B.ToBigInteger().Equals(other.B.ToBigInteger()));
  734. end;
  735. function TECCurve.GetA: IECFieldElement;
  736. begin
  737. Result := Fm_a;
  738. end;
  739. class function TECCurve.GetAllCoordinateSystems: TCryptoLibInt32Array;
  740. begin
  741. Result := TCryptoLibInt32Array.Create(COORD_AFFINE, COORD_HOMOGENEOUS,
  742. COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY, COORD_JACOBIAN_MODIFIED,
  743. COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED);
  744. end;
  745. function TECCurve.GetB: IECFieldElement;
  746. begin
  747. Result := Fm_b;
  748. end;
  749. function TECCurve.GetCofactor: TBigInteger;
  750. begin
  751. Result := Fm_cofactor;
  752. end;
  753. function TECCurve.GetCoordinateSystem: Int32;
  754. begin
  755. Result := Fm_coord;
  756. end;
  757. function TECCurve.GetEndomorphism: IECEndomorphism;
  758. begin
  759. Result := Fm_endomorphism;
  760. end;
  761. function TECCurve.GetField: IFiniteField;
  762. begin
  763. Result := Fm_field;
  764. end;
  765. function TECCurve.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
  766. {$ENDIF DELPHI}
  767. begin
  768. Result := (field as TObject).GetHashCode()
  769. xor Int32(TBits.RotateLeft32(A.ToBigInteger().GetHashCode(), 8))
  770. xor Int32(TBits.RotateLeft32(B.ToBigInteger().GetHashCode(), 16));
  771. end;
  772. function TECCurve.GetMultiplier: IECMultiplier;
  773. begin
  774. FLock.Acquire;
  775. try
  776. if (Fm_multiplier = Nil) then
  777. begin
  778. Fm_multiplier := CreateDefaultMultiplier();
  779. end;
  780. Result := Fm_multiplier;
  781. finally
  782. FLock.Release;
  783. end;
  784. end;
  785. function TECCurve.GetOrder: TBigInteger;
  786. begin
  787. Result := Fm_order;
  788. end;
  789. function TECCurve.GetPreCompInfo(const point: IECPoint; const name: String)
  790. : IPreCompInfo;
  791. var
  792. table: TDictionary<String, IPreCompInfo>;
  793. begin
  794. CheckPoint(point);
  795. FLock.Acquire;
  796. try
  797. table := point.preCompTable;
  798. if table = Nil then
  799. begin
  800. Result := Nil;
  801. end
  802. else
  803. begin
  804. table.TryGetValue(name, Result);
  805. end;
  806. finally
  807. FLock.Release;
  808. end;
  809. end;
  810. function TECCurve.ImportPoint(const p: IECPoint): IECPoint;
  811. var
  812. Lp: IECPoint;
  813. begin
  814. if ((Self as IECCurve) = p.Curve) then
  815. begin
  816. Result := p;
  817. Exit;
  818. end;
  819. if (p.IsInfinity) then
  820. begin
  821. Result := Infinity;
  822. Exit;
  823. end;
  824. // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
  825. Lp := p.Normalize();
  826. Result := ValidatePoint(Lp.XCoord.ToBigInteger(), Lp.YCoord.ToBigInteger(),
  827. Lp.IsCompressed);
  828. end;
  829. procedure TECCurve.NormalizeAll(points: TCryptoLibGenericArray<IECPoint>;
  830. off, len: Int32; const iso: IECFieldElement);
  831. var
  832. zs: TCryptoLibGenericArray<IECFieldElement>;
  833. indices: TCryptoLibInt32Array;
  834. count, i, j, index: Int32;
  835. p: IECPoint;
  836. begin
  837. CheckPoints(points, off, len);
  838. case CoordinateSystem of
  839. COORD_AFFINE, COORD_LAMBDA_AFFINE:
  840. begin
  841. if (iso <> Nil) then
  842. begin
  843. raise EArgumentCryptoLibException.CreateRes
  844. (@SInvalidAffineCoordinates);
  845. end;
  846. Exit;
  847. end;
  848. end;
  849. // /*
  850. // * Figure out which of the points actually need to be normalized
  851. // */
  852. System.SetLength(zs, len);
  853. System.SetLength(indices, len);
  854. count := 0;
  855. for i := 0 to System.Pred(len) do
  856. begin
  857. p := points[off + i];
  858. if ((p <> Nil) and ((iso <> Nil) or (not(p.IsNormalized())))) then
  859. begin
  860. zs[count] := p.GetZCoord(0);
  861. indices[count] := off + i;
  862. System.Inc(count);
  863. end;
  864. end;
  865. if (count = 0) then
  866. begin
  867. Exit;
  868. end;
  869. TECAlgorithms.MontgomeryTrick(zs, 0, count, iso);
  870. for j := 0 to System.Pred(count) do
  871. begin
  872. index := indices[j];
  873. points[index] := points[index].Normalize(zs[j]);
  874. end;
  875. end;
  876. procedure TECCurve.NormalizeAll(points: TCryptoLibGenericArray<IECPoint>);
  877. begin
  878. NormalizeAll(points, 0, System.Length(points), Nil);
  879. end;
  880. procedure TECCurve.SetCoord(const Value: Int32);
  881. begin
  882. Fm_coord := Value;
  883. end;
  884. procedure TECCurve.SetEndomorphism(const Value: IECEndomorphism);
  885. begin
  886. Fm_endomorphism := Value;
  887. end;
  888. procedure TECCurve.SetMultiplier(const Value: IECMultiplier);
  889. begin
  890. Fm_multiplier := Value;
  891. end;
  892. procedure TECCurve.SetPreCompInfo(const point: IECPoint; const name: String;
  893. const preCompInfo: IPreCompInfo);
  894. var
  895. table: TDictionary<String, IPreCompInfo>;
  896. begin
  897. CheckPoint(point);
  898. FLock.Acquire;
  899. try
  900. table := point.preCompTable;
  901. if table = Nil then
  902. begin
  903. table := TDictionary<String, IPreCompInfo>.Create(4);
  904. point.preCompTable := table;
  905. end;
  906. if not table.ContainsKey(name) then
  907. begin
  908. table.Add(name, preCompInfo);
  909. end;
  910. finally
  911. FLock.Release;
  912. end;
  913. end;
  914. function TECCurve.SupportsCoordinateSystem(coord: Int32): Boolean;
  915. begin
  916. Result := coord = COORD_AFFINE;
  917. end;
  918. function TECCurve.ValidatePoint(const x, y: TBigInteger;
  919. withCompression: Boolean): IECPoint;
  920. var
  921. p: IECPoint;
  922. begin
  923. p := CreatePoint(x, y, withCompression);
  924. if (not p.IsValid()) then
  925. begin
  926. raise EArgumentCryptoLibException.CreateRes(@SInvalidPointCoordinates);
  927. end;
  928. Result := p;
  929. end;
  930. function TECCurve.ValidatePoint(const x, y: TBigInteger): IECPoint;
  931. var
  932. p: IECPoint;
  933. begin
  934. p := CreatePoint(x, y);
  935. if (not p.IsValid()) then
  936. begin
  937. raise EArgumentCryptoLibException.CreateRes(@SInvalidPointCoordinates);
  938. end;
  939. Result := p;
  940. end;
  941. { TECCurve.TConfig }
  942. constructor TECCurve.TConfig.Create(const outer: IECCurve; coord: Int32;
  943. const endomorphism: IECEndomorphism; const multiplier: IECMultiplier);
  944. begin
  945. Inherited Create();
  946. Fouter := outer;
  947. Fcoord := coord;
  948. Fendomorphism := endomorphism;
  949. Fmultiplier := multiplier;
  950. end;
  951. function TECCurve.TConfig.CreateCurve: IECCurve;
  952. var
  953. c: IECCurve;
  954. begin
  955. if (not Fouter.SupportsCoordinateSystem(Fcoord)) then
  956. begin
  957. raise EInvalidOperationCryptoLibException.CreateRes
  958. (@SUnSupportedCoordinateSystem);
  959. end;
  960. c := Fouter.CloneCurve();
  961. if (c = Fouter) then
  962. begin
  963. raise EInvalidOperationCryptoLibException.CreateRes(@SCurrentCurve);
  964. end;
  965. c.coord := Fcoord;
  966. c.endomorphism := Fendomorphism;
  967. c.multiplier := Fmultiplier;
  968. Result := c;
  969. end;
  970. destructor TECCurve.TConfig.Destroy;
  971. begin
  972. inherited Destroy;
  973. end;
  974. function TECCurve.TConfig.SetCoordinateSystem(coord: Int32): IConfig;
  975. begin
  976. Fcoord := coord;
  977. Result := Self as IConfig;
  978. end;
  979. function TECCurve.TConfig.SetEndomorphism(const endomorphism
  980. : IECEndomorphism): IConfig;
  981. begin
  982. Fendomorphism := endomorphism;
  983. Result := Self as IConfig;
  984. end;
  985. function TECCurve.TConfig.SetMultiplier(const multiplier
  986. : IECMultiplier): IConfig;
  987. begin
  988. Fmultiplier := multiplier;
  989. Result := Self as IConfig;
  990. end;
  991. { TAbstractFpCurve }
  992. constructor TAbstractFpCurve.Create(const q: TBigInteger);
  993. begin
  994. Inherited Create(TFiniteFields.GetPrimeField(q));
  995. end;
  996. function TAbstractFpCurve.DecompressPoint(yTilde: Int32; X1: TBigInteger)
  997. : IECPoint;
  998. var
  999. x, rhs, y: IECFieldElement;
  1000. begin
  1001. x := FromBigInteger(X1);
  1002. rhs := x.Square().Add(A).Multiply(x).Add(B);
  1003. y := rhs.Sqrt();
  1004. // /*
  1005. // * If y is not a square, then we haven't got a point on the curve
  1006. // */
  1007. if (y = Nil) then
  1008. begin
  1009. raise EArgumentCryptoLibException.CreateRes(@SInvalidPointCompression);
  1010. end;
  1011. if (y.TestBitZero() <> (yTilde = 1)) then
  1012. begin
  1013. // Use the other root
  1014. y := y.Negate();
  1015. end;
  1016. Result := CreateRawPoint(x, y, true);
  1017. end;
  1018. destructor TAbstractFpCurve.Destroy;
  1019. begin
  1020. inherited Destroy;
  1021. end;
  1022. function TAbstractFpCurve.IsValidFieldElement(x: TBigInteger): Boolean;
  1023. begin
  1024. Result := (x.IsInitialized) and (x.SignValue >= 0) and
  1025. (x.CompareTo(field.Characteristic) < 0);
  1026. end;
  1027. { TFpCurve }
  1028. function TFpCurve.CloneCurve: IECCurve;
  1029. begin
  1030. Result := TFpCurve.Create(Fm_q, Fm_r, Fm_a, Fm_b, Fm_order, Fm_cofactor);
  1031. end;
  1032. constructor TFpCurve.Create(const q, r: TBigInteger;
  1033. const A, B: IECFieldElement; const Order, Cofactor: TBigInteger);
  1034. begin
  1035. Inherited Create(q);
  1036. Fm_q := q;
  1037. Fm_r := r;
  1038. Fm_infinity := TFpPoint.Create(Self as IECCurve, Nil, Nil);
  1039. Fm_a := A;
  1040. Fm_b := B;
  1041. Fm_order := Order;
  1042. Fm_cofactor := Cofactor;
  1043. Fm_coord := FP_DEFAULT_COORDS;
  1044. end;
  1045. constructor TFpCurve.Create(const q, r: TBigInteger;
  1046. const A, B: IECFieldElement);
  1047. begin
  1048. Create(q, r, A, B, Default (TBigInteger), Default (TBigInteger));
  1049. end;
  1050. constructor TFpCurve.Create(const q, A, B, Order, Cofactor: TBigInteger);
  1051. begin
  1052. Inherited Create(q);
  1053. Fm_q := q;
  1054. Fm_r := TFpFieldElement.CalculateResidue(q);
  1055. Fm_infinity := TFpPoint.Create(Self as IECCurve, Nil, Nil);
  1056. Fm_a := FromBigInteger(A);
  1057. Fm_b := FromBigInteger(B);
  1058. Fm_order := Order;
  1059. Fm_cofactor := Cofactor;
  1060. Fm_coord := FP_DEFAULT_COORDS;
  1061. end;
  1062. constructor TFpCurve.Create(const q, A, B: TBigInteger);
  1063. begin
  1064. Create(q, A, B, Default (TBigInteger), Default (TBigInteger));
  1065. end;
  1066. function TFpCurve.CreateRawPoint(const x, y: IECFieldElement;
  1067. zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
  1068. : IECPoint;
  1069. begin
  1070. Result := TFpPoint.Create(Self as IECCurve, x, y, zs, withCompression);
  1071. end;
  1072. destructor TFpCurve.Destroy;
  1073. begin
  1074. inherited Destroy;
  1075. end;
  1076. function TFpCurve.CreateRawPoint(const x, y: IECFieldElement;
  1077. withCompression: Boolean): IECPoint;
  1078. begin
  1079. Result := TFpPoint.Create(Self as IECCurve, x, y, withCompression);
  1080. end;
  1081. function TFpCurve.FromBigInteger(x: TBigInteger): IECFieldElement;
  1082. begin
  1083. Result := TFpFieldElement.Create(Fm_q, Fm_r, x);
  1084. end;
  1085. function TFpCurve.GetFieldSize: Int32;
  1086. begin
  1087. Result := Fm_q.BitLength;
  1088. end;
  1089. function TFpCurve.GetInfinity: IECPoint;
  1090. begin
  1091. Result := Fm_infinity;
  1092. end;
  1093. function TFpCurve.GetQ: TBigInteger;
  1094. begin
  1095. Result := Fm_q;
  1096. end;
  1097. function TFpCurve.ImportPoint(const p: IECPoint): IECPoint;
  1098. begin
  1099. if ((Self as IECCurve <> p.Curve) and (CoordinateSystem = COORD_JACOBIAN) and
  1100. (not p.IsInfinity)) then
  1101. begin
  1102. case p.Curve.CoordinateSystem of
  1103. COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY, COORD_JACOBIAN_MODIFIED:
  1104. begin
  1105. Result := TFpPoint.Create(Self as IECCurve,
  1106. FromBigInteger(p.RawXCoord.ToBigInteger()),
  1107. FromBigInteger(p.RawYCoord.ToBigInteger()),
  1108. TCryptoLibGenericArray<IECFieldElement>.Create
  1109. (FromBigInteger(p.GetZCoord(0).ToBigInteger())), p.IsCompressed);
  1110. Exit;
  1111. end;
  1112. end;
  1113. end;
  1114. Result := (Inherited ImportPoint(p));
  1115. end;
  1116. function TFpCurve.SupportsCoordinateSystem(coord: Int32): Boolean;
  1117. begin
  1118. case coord of
  1119. COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_MODIFIED:
  1120. begin
  1121. Result := true;
  1122. end
  1123. else
  1124. begin
  1125. Result := false;
  1126. end;
  1127. end;
  1128. end;
  1129. { TAbstractF2mCurve }
  1130. class function TAbstractF2mCurve.BuildField(m, k1, k2, k3: Int32): IFiniteField;
  1131. begin
  1132. if (k1 = 0) then
  1133. begin
  1134. raise EArgumentCryptoLibException.CreateRes(@SInvalidK1);
  1135. end;
  1136. if (k2 = 0) then
  1137. begin
  1138. if (k3 <> 0) then
  1139. begin
  1140. raise EArgumentCryptoLibException.CreateRes(@SInvalidK3);
  1141. end;
  1142. Result := TFiniteFields.GetBinaryExtensionField
  1143. (TCryptoLibInt32Array.Create(0, k1, m));
  1144. Exit;
  1145. end;
  1146. if (k2 <= k1) then
  1147. begin
  1148. raise EArgumentCryptoLibException.CreateRes(@SK2K1MisMatch);
  1149. end;
  1150. if (k3 <= k2) then
  1151. begin
  1152. raise EArgumentCryptoLibException.CreateRes(@SK3K2Mismatch);
  1153. end;
  1154. Result := TFiniteFields.GetBinaryExtensionField(TCryptoLibInt32Array.Create(0,
  1155. k1, k2, k3, m));
  1156. end;
  1157. constructor TAbstractF2mCurve.Create(m, k1, k2, k3: Int32);
  1158. begin
  1159. Inherited Create(BuildField(m, k1, k2, k3));
  1160. end;
  1161. function TAbstractF2mCurve.CreatePoint(const x, y: TBigInteger;
  1162. withCompression: Boolean): IECPoint;
  1163. var
  1164. LX, LY: IECFieldElement;
  1165. begin
  1166. LX := FromBigInteger(x);
  1167. LY := FromBigInteger(y);
  1168. case CoordinateSystem of
  1169. COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE:
  1170. begin
  1171. if (LX.IsZero) then
  1172. begin
  1173. if (not LY.Square().Equals(B)) then
  1174. begin
  1175. raise EArgumentCryptoLibException.Create('');
  1176. end;
  1177. end
  1178. else
  1179. begin
  1180. // Y becomes Lambda (X + Y/X) here
  1181. LY := LY.Divide(LX).Add(LX);
  1182. end;
  1183. end;
  1184. end;
  1185. Result := CreateRawPoint(LX, LY, withCompression);
  1186. end;
  1187. function TAbstractF2mCurve.DecompressPoint(yTilde: Int32; X1: TBigInteger)
  1188. : IECPoint;
  1189. var
  1190. xp, yp, beta, z: IECFieldElement;
  1191. begin
  1192. xp := FromBigInteger(X1);
  1193. yp := Nil;
  1194. if (xp.IsZero) then
  1195. begin
  1196. yp := B.Sqrt();
  1197. end
  1198. else
  1199. begin
  1200. beta := xp.Square().Invert().Multiply(B).Add(A).Add(xp);
  1201. z := SolveQuadradicEquation(beta);
  1202. if (z <> Nil) then
  1203. begin
  1204. if (z.TestBitZero() <> (yTilde = 1)) then
  1205. begin
  1206. z := z.AddOne();
  1207. end;
  1208. case CoordinateSystem of
  1209. COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE:
  1210. begin
  1211. yp := z.Add(xp);
  1212. end
  1213. else
  1214. begin
  1215. yp := z.Multiply(xp);
  1216. end;
  1217. end;
  1218. end;
  1219. end;
  1220. if (yp = Nil) then
  1221. begin
  1222. raise EArgumentCryptoLibException.CreateRes(@SInvalidPointCompression);
  1223. end;
  1224. Result := CreateRawPoint(xp, yp, true);
  1225. end;
  1226. destructor TAbstractF2mCurve.Destroy;
  1227. begin
  1228. inherited Destroy;
  1229. end;
  1230. function TAbstractF2mCurve.GetIsKoblitz: Boolean;
  1231. begin
  1232. Result := (Fm_order.IsInitialized) and (Fm_cofactor.IsInitialized) and
  1233. (Fm_b.IsOne) and (Fm_a.IsZero or Fm_a.IsOne);
  1234. end;
  1235. function TAbstractF2mCurve.GetSi: TCryptoLibGenericArray<TBigInteger>;
  1236. begin
  1237. if (Fsi = Nil) then
  1238. begin
  1239. FLock.Acquire;
  1240. try
  1241. if (Fsi = Nil) then
  1242. begin
  1243. Fsi := TTnaf.GetSi(Self as IAbstractF2mCurve);
  1244. end;
  1245. finally
  1246. FLock.Release;
  1247. end;
  1248. end;
  1249. Result := Fsi;
  1250. end;
  1251. class function TAbstractF2mCurve.Inverse(m: Int32; ks: TCryptoLibInt32Array;
  1252. const x: TBigInteger): TBigInteger;
  1253. begin
  1254. Result := TLongArray.Create(x).ModInverse(m, ks).ToBigInteger();
  1255. end;
  1256. function TAbstractF2mCurve.IsValidFieldElement(x: TBigInteger): Boolean;
  1257. begin
  1258. Result := (x.IsInitialized) and (x.SignValue >= 0) and
  1259. (x.BitLength <= FieldSize);
  1260. end;
  1261. function TAbstractF2mCurve.SolveQuadradicEquation(const beta: IECFieldElement)
  1262. : IECFieldElement;
  1263. var
  1264. gamma, z, zeroElement, t, w, w2: IECFieldElement;
  1265. m, i: Int32;
  1266. begin
  1267. if (beta.IsZero) then
  1268. begin
  1269. Result := beta;
  1270. Exit;
  1271. end;
  1272. zeroElement := FromBigInteger(TBigInteger.Zero);
  1273. m := FieldSize;
  1274. repeat
  1275. t := FromBigInteger(TBigInteger.Arbitrary(m));
  1276. z := zeroElement;
  1277. w := beta;
  1278. i := 1;
  1279. while i < m do
  1280. begin
  1281. w2 := w.Square();
  1282. z := z.Square().Add(w2.Multiply(t));
  1283. w := w2.Add(beta);
  1284. System.Inc(i);
  1285. end;
  1286. if (not w.IsZero) then
  1287. begin
  1288. Result := Nil;
  1289. Exit;
  1290. end;
  1291. gamma := z.Square().Add(z);
  1292. until (not(gamma.IsZero));
  1293. Result := z;
  1294. end;
  1295. { TF2mCurve }
  1296. function TF2mCurve.CloneCurve: IECCurve;
  1297. begin
  1298. Result := TF2mCurve.Create(m, k1, k2, k3, Fm_a, Fm_b, Fm_order, Fm_cofactor);
  1299. end;
  1300. constructor TF2mCurve.Create(m, k: Int32; const A, B: TBigInteger);
  1301. begin
  1302. Create(m, k, 0, 0, A, B, Default (TBigInteger), Default (TBigInteger));
  1303. end;
  1304. constructor TF2mCurve.Create(m, k1, k2, k3: Int32; const A, B: IECFieldElement;
  1305. const Order, Cofactor: TBigInteger);
  1306. begin
  1307. Inherited Create(m, k1, k2, k3);
  1308. Fm := m;
  1309. Fk1 := k1;
  1310. Fk2 := k2;
  1311. Fk3 := k3;
  1312. Fm_order := Order;
  1313. Fm_cofactor := Cofactor;
  1314. Fm_infinity := TF2mPoint.Create(Self as IECCurve, Nil, Nil);
  1315. Fm_a := A;
  1316. Fm_b := B;
  1317. Fm_coord := F2M_DEFAULT_COORDS;
  1318. end;
  1319. constructor TF2mCurve.Create(m, k: Int32;
  1320. const A, B, Order, Cofactor: TBigInteger);
  1321. begin
  1322. Create(m, k, 0, 0, A, B, Order, Cofactor);
  1323. end;
  1324. constructor TF2mCurve.Create(m, k1, k2, k3: Int32;
  1325. const A, B, Order, Cofactor: TBigInteger);
  1326. begin
  1327. Inherited Create(m, k1, k2, k3);
  1328. Fm := m;
  1329. Fk1 := k1;
  1330. Fk2 := k2;
  1331. Fk3 := k3;
  1332. Fm_order := Order;
  1333. Fm_cofactor := Cofactor;
  1334. Fm_infinity := TF2mPoint.Create(Self as IECCurve, Nil, Nil);
  1335. if (k1 = 0) then
  1336. begin
  1337. raise EArgumentCryptoLibException.CreateRes(@SInvalidK1);
  1338. end;
  1339. if (k2 = 0) then
  1340. begin
  1341. if (k3 <> 0) then
  1342. begin
  1343. raise EArgumentCryptoLibException.CreateRes(@SInvalidK3);
  1344. end;
  1345. end
  1346. else
  1347. begin
  1348. if (k2 <= k1) then
  1349. begin
  1350. raise EArgumentCryptoLibException.CreateRes(@SK2K1MisMatch);
  1351. end;
  1352. if (k3 <= k2) then
  1353. begin
  1354. raise EArgumentCryptoLibException.CreateRes(@SK3K2Mismatch);
  1355. end;
  1356. end;
  1357. Fm_a := FromBigInteger(A);
  1358. Fm_b := FromBigInteger(B);
  1359. Fm_coord := F2M_DEFAULT_COORDS;
  1360. end;
  1361. function TF2mCurve.CreateCacheSafeLookupTable
  1362. (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
  1363. var
  1364. FE_LONGS, position, i: Int32;
  1365. table: TCryptoLibInt64Array;
  1366. p: IECPoint;
  1367. begin
  1368. FE_LONGS := (m + 63) div 64;
  1369. System.SetLength(table, len * FE_LONGS * 2);
  1370. position := 0;
  1371. for i := 0 to System.Pred(len) do
  1372. begin
  1373. p := points[off + i];
  1374. (p.RawXCoord as IF2mFieldElement).x.CopyTo(table, position);
  1375. position := position + FE_LONGS;
  1376. (p.RawYCoord as IF2mFieldElement).x.CopyTo(table, position);
  1377. position := position + FE_LONGS;
  1378. end;
  1379. Result := TDefaultF2mLookupTable.Create(Self as IF2mCurve, table, len);
  1380. end;
  1381. constructor TF2mCurve.Create(m, k1, k2, k3: Int32; const A, B: TBigInteger);
  1382. begin
  1383. Create(m, k1, k2, k3, A, B, Default (TBigInteger), Default (TBigInteger));
  1384. end;
  1385. function TF2mCurve.CreateDefaultMultiplier: IECMultiplier;
  1386. begin
  1387. if (IsKoblitz) then
  1388. begin
  1389. Result := TWTauNafMultiplier.Create();
  1390. Exit;
  1391. end;
  1392. Result := (Inherited CreateDefaultMultiplier());
  1393. end;
  1394. function TF2mCurve.CreateRawPoint(const x, y: IECFieldElement;
  1395. withCompression: Boolean): IECPoint;
  1396. begin
  1397. Result := TF2mPoint.Create(Self as IECCurve, x, y, withCompression);
  1398. end;
  1399. function TF2mCurve.CreateRawPoint(const x, y: IECFieldElement;
  1400. zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
  1401. : IECPoint;
  1402. begin
  1403. Result := TF2mPoint.Create(Self as IECCurve, x, y, zs, withCompression);
  1404. end;
  1405. destructor TF2mCurve.Destroy;
  1406. begin
  1407. inherited Destroy;
  1408. end;
  1409. function TF2mCurve.FromBigInteger(x: TBigInteger): IECFieldElement;
  1410. begin
  1411. Result := TF2mFieldElement.Create(Fm, Fk1, Fk2, Fk3, x);
  1412. end;
  1413. function TF2mCurve.GetFieldSize: Int32;
  1414. begin
  1415. Result := Fm;
  1416. end;
  1417. function TF2mCurve.GetInfinity: IECPoint;
  1418. begin
  1419. Result := Fm_infinity;
  1420. end;
  1421. function TF2mCurve.GetK1: Int32;
  1422. begin
  1423. Result := Fk1;
  1424. end;
  1425. function TF2mCurve.GetK2: Int32;
  1426. begin
  1427. Result := Fk2;
  1428. end;
  1429. function TF2mCurve.GetK3: Int32;
  1430. begin
  1431. Result := Fk3;
  1432. end;
  1433. function TF2mCurve.GetM: Int32;
  1434. begin
  1435. Result := Fm;
  1436. end;
  1437. function TF2mCurve.IsTrinomial: Boolean;
  1438. begin
  1439. Result := (k2 = 0) and (k3 = 0);
  1440. end;
  1441. function TF2mCurve.SupportsCoordinateSystem(coord: Int32): Boolean;
  1442. begin
  1443. case coord of
  1444. COORD_AFFINE, COORD_HOMOGENEOUS, COORD_LAMBDA_PROJECTIVE:
  1445. begin
  1446. Result := true;
  1447. end
  1448. else
  1449. begin
  1450. Result := false;
  1451. end;
  1452. end;
  1453. end;
  1454. { TDefaultLookupTable }
  1455. constructor TDefaultLookupTable.Create(const outer: IECCurve;
  1456. table: TCryptoLibByteArray; size: Int32);
  1457. begin
  1458. Inherited Create();
  1459. Fm_outer := outer;
  1460. Fm_table := table;
  1461. Fm_size := size;
  1462. end;
  1463. function TDefaultLookupTable.GetSize: Int32;
  1464. begin
  1465. Result := Fm_size;
  1466. end;
  1467. function TDefaultLookupTable.Lookup(index: Int32): IECPoint;
  1468. var
  1469. FE_BYTES, position, i, j: Int32;
  1470. x, y: TCryptoLibByteArray;
  1471. MASK: Byte;
  1472. XFieldElement, YFieldElement: IECFieldElement;
  1473. begin
  1474. FE_BYTES := (Fm_outer.FieldSize + 7) div 8;
  1475. System.SetLength(x, FE_BYTES);
  1476. System.SetLength(y, FE_BYTES);
  1477. position := 0;
  1478. for i := 0 to System.Pred(Fm_size) do
  1479. begin
  1480. MASK := Byte(TBits.Asr32((i xor index) - 1, 31));
  1481. for j := 0 to System.Pred(FE_BYTES) do
  1482. begin
  1483. x[j] := x[j] xor Byte(Fm_table[position + j] and MASK);
  1484. y[j] := y[j] xor Byte(Fm_table[position + FE_BYTES + j] and MASK);
  1485. end;
  1486. position := position + (FE_BYTES * 2);
  1487. end;
  1488. XFieldElement := Fm_outer.FromBigInteger(TBigInteger.Create(1, x));
  1489. YFieldElement := Fm_outer.FromBigInteger(TBigInteger.Create(1, y));
  1490. Result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement, false);
  1491. end;
  1492. { TDefaultF2mLookupTable }
  1493. constructor TDefaultF2mLookupTable.Create(const outer: IF2mCurve;
  1494. table: TCryptoLibInt64Array; size: Int32);
  1495. begin
  1496. Inherited Create();
  1497. Fm_outer := outer;
  1498. Fm_table := table;
  1499. Fm_size := size;
  1500. end;
  1501. function TDefaultF2mLookupTable.GetSize: Int32;
  1502. begin
  1503. Result := Fm_size;
  1504. end;
  1505. function TDefaultF2mLookupTable.Lookup(index: Int32): IECPoint;
  1506. var
  1507. FE_LONGS, position, m, i, j: Int32;
  1508. ks: TCryptoLibInt32Array;
  1509. x, y: TCryptoLibInt64Array;
  1510. MASK: Int64;
  1511. XFieldElement, YFieldElement: IECFieldElement;
  1512. begin
  1513. m := Fm_outer.m;
  1514. if Fm_outer.IsTrinomial() then
  1515. begin
  1516. ks := TCryptoLibInt32Array.Create(Fm_outer.k1);
  1517. end
  1518. else
  1519. begin
  1520. ks := TCryptoLibInt32Array.Create(Fm_outer.k1, Fm_outer.k2, Fm_outer.k3);
  1521. end;
  1522. FE_LONGS := (Fm_outer.m + 63) div 64;
  1523. System.SetLength(x, FE_LONGS);
  1524. System.SetLength(y, FE_LONGS);
  1525. position := 0;
  1526. for i := 0 to System.Pred(Fm_size) do
  1527. begin
  1528. MASK := TBits.Asr32((i xor index) - 1, 31);
  1529. for j := 0 to System.Pred(FE_LONGS) do
  1530. begin
  1531. x[j] := x[j] xor (Fm_table[position + j] and MASK);
  1532. y[j] := y[j] xor (Fm_table[position + FE_LONGS + j] and MASK);
  1533. end;
  1534. position := position + (FE_LONGS * 2);
  1535. end;
  1536. XFieldElement := TF2mFieldElement.Create(m, ks, TLongArray.Create(x));
  1537. YFieldElement := TF2mFieldElement.Create(m, ks, TLongArray.Create(y));
  1538. Result := Fm_outer.CreateRawPoint(XFieldElement, YFieldElement, false);
  1539. end;
  1540. end.