Browse Source

add sect283k1 custom curve.

Ugochukwu Mmaduekwe 7 years ago
parent
commit
0844a5e9ed

+ 9 - 1
CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr

@@ -440,7 +440,15 @@ uses
   ClpSecP521R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Point.pas',
   ClpISecP521R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Point.pas',
   ClpSecP521R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Curve.pas',
-  ClpISecP521R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Curve.pas';
+  ClpISecP521R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Curve.pas',
+  ClpInterleave in '..\..\CryptoLib\src\Math\Raw\ClpInterleave.pas',
+  ClpSecT283Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283Field.pas',
+  ClpSecT283FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283FieldElement.pas',
+  ClpISecT283FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecT283FieldElement.pas',
+  ClpSecT283K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Point.pas',
+  ClpISecT283K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Point.pas',
+  ClpISecT283K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Curve.pas',
+  ClpSecT283K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Curve.pas';
 
 begin
   try

+ 9 - 1
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -492,7 +492,15 @@ uses
   ClpSecP521R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Point.pas',
   ClpISecP521R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Point.pas',
   ClpSecP521R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Curve.pas',
-  ClpISecP521R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Curve.pas';
+  ClpISecP521R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Curve.pas',
+  ClpInterleave in '..\..\CryptoLib\src\Math\Raw\ClpInterleave.pas',
+  ClpSecT283Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283Field.pas',
+  ClpSecT283FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283FieldElement.pas',
+  ClpISecT283FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecT283FieldElement.pas',
+  ClpSecT283K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Point.pas',
+  ClpISecT283K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Point.pas',
+  ClpISecT283K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Curve.pas',
+  ClpSecT283K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Curve.pas';
 
 begin
 

+ 72 - 22
CryptoLib/src/Crypto/EC/ClpCustomNamedCurves.pas

@@ -37,6 +37,8 @@ uses
   ClpISecP384R1Curve,
   ClpSecP521R1Curve,
   ClpISecP521R1Curve,
+  ClpSecT283K1Curve,
+  ClpISecT283K1Curve,
   ClpIECInterface,
   ClpX9ECPoint,
   ClpIX9ECPoint,
@@ -72,16 +74,16 @@ type
       const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
       static; inline;
 
-    // class procedure DefineCurveAlias(const name: String;
-    // const oid: IDerObjectIdentifier); static; inline;
+    class procedure DefineCurveAlias(const name: String;
+      const oid: IDerObjectIdentifier); static; inline;
 
     class function ConfigureCurve(const curve: IECCurve): IECCurve;
       static; inline;
     class function ConfigureCurveGlv(const c: IECCurve;
       const p: IGlvTypeBParameters): IECCurve; static; inline;
 
-    class constructor CreateSecNamedCurves();
-    class destructor DestroySecNamedCurves();
+    class constructor CreateCustomNamedCurves();
+    class destructor DestroyCustomNamedCurves();
 
   public
     class function GetByName(const name: String): IX9ECParameters;
@@ -163,6 +165,22 @@ type
 
     end;
 
+  type
+
+    /// <summary>
+    /// sect283k1
+    /// </summary>
+    TSecT283K1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static;
+
+    end;
+
   end;
 
 implementation
@@ -194,22 +212,21 @@ begin
   FnameToCurve.Add(LName, holder);
 end;
 
-// class procedure TCustomNamedCurves.DefineCurveAlias(const name: String;
-// const oid: IDerObjectIdentifier);
-// var
-// curve: IX9ECParametersHolder;
-// LName: string;
-// begin
-// LName := name;
-// if not(FoidToCurve.TryGetValue(oid, curve)) then
-// begin
-// raise EInvalidOperationCryptoLibException.Create('');
-// end;
-// LName := UpperCase(LName);
-// FnameToOid.Add(LName, oid);
-// FnameToCurve.Add(LName, curve);
-// end;
-//
+class procedure TCustomNamedCurves.DefineCurveAlias(const name: String;
+  const oid: IDerObjectIdentifier);
+var
+  curve: IX9ECParametersHolder;
+  LName: string;
+begin
+  LName := name;
+  if not(FoidToCurve.TryGetValue(oid, curve)) then
+  begin
+    raise EInvalidOperationCryptoLibException.Create('');
+  end;
+  LName := UpperCase(LName);
+  FnameToOid.Add(LName, oid);
+  FnameToCurve.Add(LName, curve);
+end;
 
 class function TCustomNamedCurves.ConfigureCurve(const curve: IECCurve)
   : IECCurve;
@@ -279,12 +296,12 @@ begin
   result := Fnames.ToArray();
 end;
 
-class constructor TCustomNamedCurves.CreateSecNamedCurves;
+class constructor TCustomNamedCurves.CreateCustomNamedCurves;
 begin
   TCustomNamedCurves.Boot;
 end;
 
-class destructor TCustomNamedCurves.DestroySecNamedCurves;
+class destructor TCustomNamedCurves.DestroyCustomNamedCurves;
 begin
   FnameToCurve.Free;
   FnameToOid.Free;
@@ -314,6 +331,14 @@ begin
     DefineCurveWithOid('secp521r1', TSecObjectIdentifiers.SecP521r1,
       TSecP521R1Holder.Instance);
 
+    DefineCurveWithOid('sect283k1', TSecObjectIdentifiers.SecT283k1,
+      TSecT283K1Holder.Instance);
+
+    DefineCurveAlias('K-283', TSecObjectIdentifiers.SecT283k1);
+
+    DefineCurveAlias('P-384', TSecObjectIdentifiers.SecP384r1);
+    DefineCurveAlias('P-521', TSecObjectIdentifiers.SecP521r1);
+
     FIsBooted := True;
   end;
 end;
@@ -386,6 +411,7 @@ var
   S: TCryptoLibByteArray;
   curve: IECCurve;
   G: IX9ECPoint;
+  r: IECPoint;
 begin
   S := THex.Decode('D09E8800291CB85396CC6717393284AAA0DA64BA');
   curve := ConfigureCurve(TSecP521R1Curve.Create() as ISecP521R1Curve);
@@ -403,4 +429,28 @@ begin
   result := TSecP521R1Holder.Create();
 end;
 
+{ TCustomNamedCurves.TSecT283K1Holder }
+
+function TCustomNamedCurves.TSecT283K1Holder.CreateParameters: IX9ECParameters;
+var
+  S: TCryptoLibByteArray;
+  curve: IECCurve;
+  G: IX9ECPoint;
+begin
+  S := Nil;
+  curve := ConfigureCurve(TSecT283K1Curve.Create() as ISecT283K1Curve);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836' +
+    '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259')
+    );
+  result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
+end;
+
+class function TCustomNamedCurves.TSecT283K1Holder.Instance
+  : IX9ECParametersHolder;
+begin
+  result := TSecT283K1Holder.Create();
+end;
+
 end.

+ 1 - 2
CryptoLib/src/Interfaces/ClpISecP256K1Curve.pas

@@ -23,8 +23,7 @@ interface
 
 uses
   ClpIECInterface,
-  ClpBigInteger,
-  ClpCryptoLibTypes;
+  ClpBigInteger;
 
 type
   ISecP256K1LookupTable = Interface(IECLookupTable)

+ 1 - 2
CryptoLib/src/Interfaces/ClpISecP384R1Curve.pas

@@ -23,8 +23,7 @@ interface
 
 uses
   ClpIECInterface,
-  ClpBigInteger,
-  ClpCryptoLibTypes;
+  ClpBigInteger;
 
 type
   ISecP384R1LookupTable = Interface(IECLookupTable)

+ 1 - 2
CryptoLib/src/Interfaces/ClpISecP521R1Curve.pas

@@ -23,8 +23,7 @@ interface
 
 uses
   ClpIECInterface,
-  ClpBigInteger,
-  ClpCryptoLibTypes;
+  ClpBigInteger;
 
 type
   ISecP521R1LookupTable = Interface(IECLookupTable)

+ 51 - 0
CryptoLib/src/Interfaces/ClpISecT283FieldElement.pas

@@ -0,0 +1,51 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpISecT283FieldElement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECFieldElement,
+  ClpCryptoLibTypes;
+
+type
+  ISecT283FieldElement = Interface(IAbstractF2mFieldElement)
+    ['{8DD5CFAF-D879-4FC2-93D7-3C2D5D49E8D1}']
+
+    function GetM: Int32;
+    property M: Int32 read GetM;
+
+    function GetRepresentation: Int32;
+    property Representation: Int32 read GetRepresentation;
+
+    function GetK1: Int32;
+    property k1: Int32 read GetK1;
+    function GetK2: Int32;
+    property k2: Int32 read GetK2;
+    function GetK3: Int32;
+    property k3: Int32 read GetK3;
+
+    function GetX: TCryptoLibUInt64Array;
+    property X: TCryptoLibUInt64Array read GetX;
+  end;
+
+implementation
+
+end.

+ 55 - 0
CryptoLib/src/Interfaces/ClpISecT283K1Curve.pas

@@ -0,0 +1,55 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpISecT283K1Curve;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecT283K1LookupTable = Interface(IECLookupTable)
+    ['{3AF41553-A108-46D6-9CCC-AB1814A0A247}']
+  end;
+
+type
+  ISecT283K1Curve = Interface(IAbstractF2mCurve)
+    ['{1D88AF22-721F-4E89-82A2-1C1CFFB7830C}']
+
+    function GetM: Int32;
+    property M: Int32 read GetM;
+
+    function GetK1: Int32;
+    property K1: Int32 read GetK1;
+
+    function GetK2: Int32;
+    property K2: Int32 read GetK2;
+
+    function GetK3: Int32;
+    property K3: Int32 read GetK3;
+
+    function GetIsTrinomial: Boolean;
+    property IsTrinomial: Boolean read GetIsTrinomial;
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpISecT283K1Point.pas

@@ -0,0 +1,35 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpISecT283K1Point;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecT283K1Point = Interface(IAbstractF2mPoint)
+    ['{516DA5D2-430B-42FC-A3FB-691E77B76D8B}']
+
+  end;
+
+implementation
+
+end.

+ 9 - 6
CryptoLib/src/Math/EC/ClpECCurve.pas

@@ -175,8 +175,10 @@ type
 
     end;
 
-  function FromBigInteger(const x: TBigInteger): IECFieldElement; virtual; abstract;
-  function IsValidFieldElement(const x: TBigInteger): Boolean; virtual; abstract;
+  function FromBigInteger(const x: TBigInteger): IECFieldElement;
+    virtual; abstract;
+  function IsValidFieldElement(const x: TBigInteger): Boolean; virtual;
+    abstract;
 
   function Configure(): IConfig; virtual;
   function ValidatePoint(const x, y: TBigInteger): IECPoint; overload; virtual;
@@ -420,6 +422,11 @@ type
     /// </summary>
     Fsi: TCryptoLibGenericArray<TBigInteger>;
 
+    class function BuildField(m, k1, k2, k3: Int32): IFiniteField; static;
+
+  strict protected
+    constructor Create(m, k1, k2, k3: Int32);
+
     /// <summary>
     /// Returns true if this is a Koblitz curve (ABC curve).
     /// </summary>
@@ -428,10 +435,6 @@ type
     /// </returns>
     function GetIsKoblitz: Boolean; virtual;
 
-    class function BuildField(m, k1, k2, k3: Int32): IFiniteField; static;
-
-  strict protected
-    constructor Create(m, k1, k2, k3: Int32);
     function DecompressPoint(yTilde: Int32; X1: TBigInteger): IECPoint;
       override;
 

+ 6 - 6
CryptoLib/src/Math/EC/ClpECFieldElement.pas

@@ -205,12 +205,12 @@ type
   end;
 
 type
-  TAbstract2mFieldElement = class abstract(TECFieldElement,
+  TAbstractF2mFieldElement = class abstract(TECFieldElement,
     IAbstractF2mFieldElement)
 
   public
-    function Trace(): Int32;
-    function HalfTrace(): IECFieldElement;
+    function Trace(): Int32; virtual;
+    function HalfTrace(): IECFieldElement; virtual;
 
   end;
 
@@ -222,7 +222,7 @@ type
   // * basis representations are supported. Gaussian normal basis (GNB)
   // * representation is not supported.
   // */
-  TF2mFieldElement = class(TAbstract2mFieldElement, IF2mFieldElement)
+  TF2mFieldElement = class(TAbstractF2mFieldElement, IF2mFieldElement)
 
   strict private
 
@@ -1373,7 +1373,7 @@ end;
 
 { TAbstract2mFieldElement }
 
-function TAbstract2mFieldElement.HalfTrace: IECFieldElement;
+function TAbstractF2mFieldElement.HalfTrace: IECFieldElement;
 var
   m, i: Int32;
   fe, ht: IECFieldElement;
@@ -1397,7 +1397,7 @@ begin
   result := ht;
 end;
 
-function TAbstract2mFieldElement.Trace: Int32;
+function TAbstractF2mFieldElement.Trace: Int32;
 var
   m, i: Int32;
   fe, tr: IECFieldElement;

+ 2 - 3
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Field.pas

@@ -41,13 +41,12 @@ type
 
     class function GetP: TCryptoLibUInt32Array; static; inline;
 
-    class constructor SecP521R1Field();
-
-  strict protected
     class procedure ImplMultiply(x, y, zz: TCryptoLibUInt32Array);
       static; inline;
     class procedure ImplSquare(x, zz: TCryptoLibUInt32Array); static; inline;
 
+    class constructor SecP521R1Field();
+
   public
     class procedure Add(x, y, z: TCryptoLibUInt32Array); static; inline;
     class procedure AddOne(x, z: TCryptoLibUInt32Array); static; inline;

+ 533 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283Field.pas

@@ -0,0 +1,533 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpSecT283Field;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBits,
+  ClpNat,
+  ClpNat320,
+  ClpInterleave,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecT283Field = class sealed(TObject)
+
+  strict private
+  const
+    M27 = UInt64(System.High(UInt64) shr 37);
+    M57 = UInt64(System.High(UInt64) shr 7);
+
+    class var
+
+      FROOT_Z: TCryptoLibUInt64Array;
+
+    class procedure ImplCompactExt(zz: TCryptoLibUInt64Array); static;
+    class procedure ImplExpand(x, z: TCryptoLibUInt64Array); static; inline;
+    class procedure ImplMultiply(x, y, zz: TCryptoLibUInt64Array); static;
+    class procedure ImplMulw(x, y: UInt64; z: TCryptoLibUInt64Array;
+      zOff: Int32); static;
+
+    class procedure ImplSquare(x, zz: TCryptoLibUInt64Array); static; inline;
+
+    class constructor SecT283Field();
+
+  public
+    class procedure Add(x, y, z: TCryptoLibUInt64Array); static; inline;
+    class procedure AddExt(xx, yy, zz: TCryptoLibUInt64Array); static; inline;
+    class procedure AddOne(x, z: TCryptoLibUInt64Array); static; inline;
+    class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt64Array;
+      static; inline;
+
+    class procedure Invert(x, z: TCryptoLibUInt64Array); static;
+    class procedure Multiply(x, y, z: TCryptoLibUInt64Array); static; inline;
+    class procedure MultiplyAddToExt(x, y, zz: TCryptoLibUInt64Array);
+      static; inline;
+    class procedure Reduce(xx, z: TCryptoLibUInt64Array); static;
+    class procedure Reduce37(z: TCryptoLibUInt64Array; zOff: Int32);
+      static; inline;
+    class procedure Sqrt(x, z: TCryptoLibUInt64Array); static;
+
+    class procedure Square(x, z: TCryptoLibUInt64Array); static; inline;
+    class procedure SquareAddToExt(x, zz: TCryptoLibUInt64Array);
+      static; inline;
+    class procedure SquareN(x: TCryptoLibUInt64Array; n: Int32;
+      z: TCryptoLibUInt64Array); static; inline;
+
+    class function Trace(x: TCryptoLibUInt64Array): UInt32; static; inline;
+
+  end;
+
+implementation
+
+{ TSecT283Field }
+
+class constructor TSecT283Field.SecT283Field;
+begin
+  FROOT_Z := TCryptoLibUInt64Array.Create(UInt64($0C30C30C30C30808),
+    UInt64($30C30C30C30C30C3), UInt64($820820820820830C),
+    UInt64($0820820820820820), UInt64($2082082));
+end;
+
+class procedure TSecT283Field.Reduce37(z: TCryptoLibUInt64Array; zOff: Int32);
+var
+  z4, t: UInt64;
+begin
+  z4 := z[zOff + 4];
+  t := z4 shr 27;
+  z[zOff] := z[zOff] xor (t xor (t shl 5) xor (t shl 7) xor (t shl 12));
+  z[zOff + 4] := z4 and M27;
+end;
+
+class procedure TSecT283Field.Add(x, y, z: TCryptoLibUInt64Array);
+begin
+  z[0] := x[0] xor y[0];
+  z[1] := x[1] xor y[1];
+  z[2] := x[2] xor y[2];
+  z[3] := x[3] xor y[3];
+  z[4] := x[4] xor y[4];
+end;
+
+class procedure TSecT283Field.AddExt(xx, yy, zz: TCryptoLibUInt64Array);
+begin
+  zz[0] := xx[0] xor yy[0];
+  zz[1] := xx[1] xor yy[1];
+  zz[2] := xx[2] xor yy[2];
+  zz[3] := xx[3] xor yy[3];
+  zz[4] := xx[4] xor yy[4];
+  zz[5] := xx[5] xor yy[5];
+  zz[6] := xx[6] xor yy[6];
+  zz[7] := xx[7] xor yy[7];
+  zz[8] := xx[8] xor yy[8];
+end;
+
+class procedure TSecT283Field.AddOne(x, z: TCryptoLibUInt64Array);
+begin
+  z[0] := x[0] xor UInt64(1);
+  z[1] := x[1];
+  z[2] := x[2];
+  z[3] := x[3];
+  z[4] := x[4];
+end;
+
+class function TSecT283Field.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt64Array;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.FromBigInteger64(x);
+  Reduce37(z, 0);
+  result := z;
+end;
+
+class procedure TSecT283Field.Multiply(x, y, z: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat320.CreateExt64();
+  ImplMultiply(x, y, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecT283Field.ImplSquare(x, zz: TCryptoLibUInt64Array);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(4) do
+  begin
+    TInterleave.Expand64To128(x[i], zz, i shl 1);
+  end;
+
+  zz[8] := TInterleave.Expand32to64(UInt32(x[4]));
+end;
+
+class procedure TSecT283Field.Square(x, z: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat.Create64(9);
+  ImplSquare(x, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecT283Field.SquareN(x: TCryptoLibUInt64Array; n: Int32;
+  z: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+{$IFDEF DEBUG}
+  System.Assert(n > 0);
+{$ENDIF DEBUG}
+  tt := TNat.Create64(9);
+  ImplSquare(x, tt);
+  Reduce(tt, z);
+
+  System.Dec(n);
+  while (n > 0) do
+  begin
+    ImplSquare(z, tt);
+    Reduce(tt, z);
+    System.Dec(n);
+  end;
+end;
+
+class procedure TSecT283Field.Invert(x, z: TCryptoLibUInt64Array);
+var
+  t0, t1: TCryptoLibUInt64Array;
+begin
+  if TNat320.IsZero64(x) then
+  begin
+    raise EInvalidOperationCryptoLibException.Create('');
+  end;
+
+  // Itoh-Tsujii inversion
+
+  t0 := TNat320.Create64();
+  t1 := TNat320.Create64();
+
+  Square(x, t0);
+  Multiply(t0, x, t0);
+  SquareN(t0, 2, t1);
+  Multiply(t1, t0, t1);
+  SquareN(t1, 4, t0);
+  Multiply(t0, t1, t0);
+  SquareN(t0, 8, t1);
+  Multiply(t1, t0, t1);
+  Square(t1, t1);
+  Multiply(t1, x, t1);
+  SquareN(t1, 17, t0);
+  Multiply(t0, t1, t0);
+  Square(t0, t0);
+  Multiply(t0, x, t0);
+  SquareN(t0, 35, t1);
+  Multiply(t1, t0, t1);
+  SquareN(t1, 70, t0);
+  Multiply(t0, t1, t0);
+  Square(t0, t0);
+  Multiply(t0, x, t0);
+  SquareN(t0, 141, t1);
+  Multiply(t1, t0, t1);
+  Square(t1, z);
+end;
+
+class procedure TSecT283Field.ImplCompactExt(zz: TCryptoLibUInt64Array);
+var
+  z0, z1, z2, z3, z4, z5, z6, z7, z8, z9: UInt64;
+begin
+  z0 := zz[0];
+  z1 := zz[1];
+  z2 := zz[2];
+  z3 := zz[3];
+  z4 := zz[4];
+  z5 := zz[5];
+  z6 := zz[6];
+  z7 := zz[7];
+  z8 := zz[8];
+  z9 := zz[9];
+  zz[0] := z0 xor (z1 shl 57);
+  zz[1] := (z1 shr 7) xor (z2 shl 50);
+  zz[2] := (z2 shr 14) xor (z3 shl 43);
+  zz[3] := (z3 shr 21) xor (z4 shl 36);
+  zz[4] := (z4 shr 28) xor (z5 shl 29);
+  zz[5] := (z5 shr 35) xor (z6 shl 22);
+  zz[6] := (z6 shr 42) xor (z7 shl 15);
+  zz[7] := (z7 shr 49) xor (z8 shl 8);
+  zz[8] := (z8 shr 56) xor (z9 shl 1);
+  zz[9] := (z9 shr 63); // Zero!
+end;
+
+class procedure TSecT283Field.ImplExpand(x, z: TCryptoLibUInt64Array);
+var
+  x0, x1, x2, x3, x4: UInt64;
+begin
+  x0 := x[0];
+  x1 := x[1];
+  x2 := x[2];
+  x3 := x[3];
+  x4 := x[4];
+  z[0] := x0 and M57;
+  z[1] := ((x0 shr 57) xor (x1 shl 7)) and M57;
+  z[2] := ((x1 shr 50) xor (x2 shl 14)) and M57;
+  z[3] := ((x2 shr 43) xor (x3 shl 21)) and M57;
+  z[4] := ((x3 shr 36) xor (x4 shl 28));
+end;
+
+class procedure TSecT283Field.ImplMultiply(x, y, zz: TCryptoLibUInt64Array);
+var
+  a, b, p: TCryptoLibUInt64Array;
+  u0, u1, u2, u3, v0, v1, v2, v3, A4, A5, B4, B5, t1, t2, t3, t4, t5, t6, t7,
+    t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22,
+    t23, t24, t25, t26, t27, t28, t29, t30, t31, t32, t33, t34, t35, t36, t37,
+    t38, t39: UInt64;
+begin
+  // /*
+  // * Formula (17) from "Some New Results on Binary Polynomial Multiplication",
+  // * Murat Cenk and M. Anwar Hasan.
+  // *
+  // * The formula as given contained an error in the term t25, as noted below
+  // */
+  System.SetLength(a, 5);
+  System.SetLength(b, 5);
+  ImplExpand(x, a);
+  ImplExpand(y, b);
+
+  System.SetLength(p, 26);
+
+  ImplMulw(a[0], b[0], p, 0); // m1
+  ImplMulw(a[1], b[1], p, 2); // m2
+  ImplMulw(a[2], b[2], p, 4); // m3
+  ImplMulw(a[3], b[3], p, 6); // m4
+  ImplMulw(a[4], b[4], p, 8); // m5
+
+  u0 := a[0] xor a[1];
+  v0 := b[0] xor b[1];
+  u1 := a[0] xor a[2];
+  v1 := b[0] xor b[2];
+  u2 := a[2] xor a[4];
+  v2 := b[2] xor b[4];
+  u3 := a[3] xor a[4];
+  v3 := b[3] xor b[4];
+
+  ImplMulw(u1 xor a[3], v1 xor b[3], p, 18); // m10
+  ImplMulw(u2 xor a[1], v2 xor b[1], p, 20); // m11
+
+  A4 := u0 xor u3;
+  B4 := v0 xor v3;
+  A5 := A4 xor a[2];
+  B5 := B4 xor b[2];
+
+  ImplMulw(A4, B4, p, 22); // m12
+  ImplMulw(A5, B5, p, 24); // m13
+
+  ImplMulw(u0, v0, p, 10); // m6
+  ImplMulw(u1, v1, p, 12); // m7
+  ImplMulw(u2, v2, p, 14); // m8
+  ImplMulw(u3, v3, p, 16); // m9
+
+
+  // Improved method factors out common single-word terms
+  // NOTE: p1,...,p26 in the paper maps to p[0],...,p[25] here
+
+  zz[0] := p[0];
+  zz[9] := p[9];
+
+  t1 := p[0] xor p[1];
+  t2 := t1 xor p[2];
+  t3 := t2 xor p[10];
+
+  zz[1] := t3;
+
+  t4 := p[3] xor p[4];
+  t5 := p[11] xor p[12];
+  t6 := t4 xor t5;
+  t7 := t2 xor t6;
+
+  zz[2] := t7;
+
+  t8 := t1 xor t4;
+  t9 := p[5] xor p[6];
+  t10 := t8 xor t9;
+  t11 := t10 xor p[8];
+  t12 := p[13] xor p[14];
+  t13 := t11 xor t12;
+  t14 := p[18] xor p[22];
+  t15 := t14 xor p[24];
+  t16 := t13 xor t15;
+
+  zz[3] := t16;
+
+  t17 := p[7] xor p[8];
+  t18 := t17 xor p[9];
+  t19 := t18 xor p[17];
+
+  zz[8] := t19;
+
+  t20 := t18 xor t9;
+  t21 := p[15] xor p[16];
+  t22 := t20 xor t21;
+
+  zz[7] := t22;
+
+  t23 := t22 xor t3;
+  t24 := p[19] xor p[20];
+  // t25 := p[23] xor  p[24];
+  t25 := p[25] xor p[24]; // Fixes an error in the paper: p[23] -> p{25]
+  t26 := p[18] xor p[23];
+  t27 := t24 xor t25;
+  t28 := t27 xor t26;
+  t29 := t28 xor t23;
+
+  zz[4] := t29;
+
+  t30 := t7 xor t19;
+  t31 := t27 xor t30;
+  t32 := p[21] xor p[22];
+  t33 := t31 xor t32;
+
+  zz[5] := t33;
+
+  t34 := t11 xor p[0];
+  t35 := t34 xor p[9];
+  t36 := t35 xor t12;
+  t37 := t36 xor p[21];
+  t38 := t37 xor p[23];
+  t39 := t38 xor p[25];
+
+  zz[6] := t39;
+
+  ImplCompactExt(zz);
+end;
+
+class procedure TSecT283Field.ImplMulw(x, y: UInt64; z: TCryptoLibUInt64Array;
+  zOff: Int32);
+var
+  u: TCryptoLibUInt64Array;
+  j: UInt32;
+  g, h, l: UInt64;
+  k: Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert((x shr 57) = 0);
+  System.Assert((y shr 57) = 0);
+{$ENDIF DEBUG}
+  System.SetLength(u, 8);
+  // u[0] := 0;
+  u[1] := y;
+  u[2] := u[1] shl 1;
+  u[3] := u[2] xor y;
+  u[4] := u[2] shl 1;
+  u[5] := u[4] xor y;
+  u[6] := u[3] shl 1;
+  u[7] := u[6] xor y;
+
+  j := UInt32(x);
+  h := 0;
+  l := u[j and 7];
+  k := 48;
+
+  repeat
+
+    j := UInt32(x shr k);
+    g := u[j and 7] xor u[(j shr 3) and 7] shl 3 xor u[(j shr 6) and 7] shl 6;
+    l := l xor ((g shl k));
+    h := h xor TBits.NegativeRightShift64(g, -k);
+
+    System.Dec(k, 9);
+  until not(k > 0);
+
+  h := h xor (((x and Int64($0100804020100800)) and
+    UInt64(TBits.Asr64(Int64(y) shl 7, 63))) shr 8);
+
+{$IFDEF DEBUG}
+  System.Assert((h shr 49) = 0);
+{$ENDIF DEBUG}
+  z[zOff] := l and M57;
+  z[zOff + 1] := (l shr 57) xor (h shl 7);
+end;
+
+class procedure TSecT283Field.MultiplyAddToExt(x, y, zz: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat320.CreateExt64();
+  ImplMultiply(x, y, tt);
+  AddExt(zz, tt, zz);
+end;
+
+class procedure TSecT283Field.Reduce(xx, z: TCryptoLibUInt64Array);
+var
+  x0, x1, x2, x3, x4, x5, x6, x7, x8, t: UInt64;
+begin
+  x0 := xx[0];
+  x1 := xx[1];
+  x2 := xx[2];
+  x3 := xx[3];
+  x4 := xx[4];
+  x5 := xx[5];
+  x6 := xx[6];
+  x7 := xx[7];
+  x8 := xx[8];
+
+  x3 := x3 xor ((x8 shl 37) xor (x8 shl 42) xor (x8 shl 44) xor (x8 shl 49));
+  x4 := x4 xor ((x8 shr 27) xor (x8 shr 22) xor (x8 shr 20) xor (x8 shr 15));
+
+  x2 := x2 xor ((x7 shl 37) xor (x7 shl 42) xor (x7 shl 44) xor (x7 shl 49));
+  x3 := x3 xor ((x7 shr 27) xor (x7 shr 22) xor (x7 shr 20) xor (x7 shr 15));
+
+  x1 := x1 xor ((x6 shl 37) xor (x6 shl 42) xor (x6 shl 44) xor (x6 shl 49));
+  x2 := x2 xor ((x6 shr 27) xor (x6 shr 22) xor (x6 shr 20) xor (x6 shr 15));
+
+  x0 := x0 xor ((x5 shl 37) xor (x5 shl 42) xor (x5 shl 44) xor (x5 shl 49));
+  x1 := x1 xor ((x5 shr 27) xor (x5 shr 22) xor (x5 shr 20) xor (x5 shr 15));
+
+  t := x4 shr 27;
+  z[0] := x0 xor t xor (t shl 5) xor (t shl 7) xor (t shl 12);
+  z[1] := x1;
+  z[2] := x2;
+  z[3] := x3;
+  z[4] := x4 and M27;
+end;
+
+class procedure TSecT283Field.Sqrt(x, z: TCryptoLibUInt64Array);
+var
+  u0, u1, e0, e1, e2: UInt64;
+  odd: TCryptoLibUInt64Array;
+begin
+  odd := TNat320.Create64();
+
+  u0 := TInterleave.Unshuffle(x[0]);
+  u1 := TInterleave.Unshuffle(x[1]);
+  e0 := (u0 and UInt64($00000000FFFFFFFF)) or (u1 shl 32);
+  odd[0] := (u0 shr 32) or (u1 and UInt64($FFFFFFFF00000000));
+
+  u0 := TInterleave.Unshuffle(x[2]);
+  u1 := TInterleave.Unshuffle(x[3]);
+  e1 := (u0 and UInt64($00000000FFFFFFFF)) or (u1 shl 32);
+  odd[1] := (u0 shr 32) or (u1 and UInt64($FFFFFFFF00000000));
+
+  u0 := TInterleave.Unshuffle(x[4]);
+  e2 := (u0 and UInt64($00000000FFFFFFFF));
+  odd[2] := (u0 shr 32);
+
+  Multiply(odd, FROOT_Z, z);
+
+  z[0] := z[0] xor e0;
+  z[1] := z[1] xor e1;
+  z[2] := z[2] xor e2;
+end;
+
+class procedure TSecT283Field.SquareAddToExt(x, zz: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat.Create64(9);
+  ImplSquare(x, tt);
+  AddExt(zz, tt, zz);
+end;
+
+class function TSecT283Field.Trace(x: TCryptoLibUInt64Array): UInt32;
+begin
+  // Non-zero-trace bits: 0, 271
+  result := UInt32(x[0] xor (x[4] shr 15)) and UInt32(1);
+end;
+
+end.

+ 381 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283FieldElement.pas

@@ -0,0 +1,381 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpSecT283FieldElement;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat320,
+  ClpECFieldElement,
+  ClpIECFieldElement,
+  ClpSecT283Field,
+  ClpISecT283FieldElement,
+  ClpBigInteger,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidValueForSecT283FieldElement =
+    'Value Invalid for SecT283FieldElement "%s"';
+
+type
+  TSecT283FieldElement = class(TAbstractF2mFieldElement, ISecT283FieldElement)
+
+  strict private
+
+    function GetM: Int32; inline;
+
+    function GetRepresentation: Int32; inline;
+
+    function GetK1: Int32; inline;
+    function GetK2: Int32; inline;
+    function GetK3: Int32; inline;
+
+    function Equals(const other: ISecT283FieldElement): Boolean;
+      reintroduce; overload;
+
+  strict protected
+  var
+    Fx: TCryptoLibUInt64Array;
+
+    function GetFieldName: string; override;
+    function GetFieldSize: Int32; override;
+    function GetIsOne: Boolean; override;
+    function GetIsZero: Boolean; override;
+
+    function GetX: TCryptoLibUInt64Array; inline;
+    property X: TCryptoLibUInt64Array read GetX;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const X: TBigInteger); overload;
+    constructor Create(X: TCryptoLibUInt64Array); overload;
+
+    function TestBitZero: Boolean; override;
+    function ToBigInteger(): TBigInteger; override;
+
+    function Add(const b: IECFieldElement): IECFieldElement; override;
+    function AddOne(): IECFieldElement; override;
+    function Subtract(const b: IECFieldElement): IECFieldElement; override;
+
+    function Multiply(const b: IECFieldElement): IECFieldElement; override;
+    function MultiplyMinusProduct(const b, X, y: IECFieldElement)
+      : IECFieldElement; override;
+    function MultiplyPlusProduct(const b, X, y: IECFieldElement)
+      : IECFieldElement; override;
+    function Divide(const b: IECFieldElement): IECFieldElement; override;
+    function Negate(): IECFieldElement; override;
+    function Square(): IECFieldElement; override;
+    function SquareMinusProduct(const X, y: IECFieldElement)
+      : IECFieldElement; override;
+    function SquarePlusProduct(const X, y: IECFieldElement)
+      : IECFieldElement; override;
+
+    function SquarePow(pow: Int32): IECFieldElement; override;
+
+    function Trace(): Int32; override;
+
+    function Invert(): IECFieldElement; override;
+
+    /// <summary>
+    /// return a sqrt root - the routine verifies that the calculation
+    /// returns the right value - if <br />none exists it returns null.
+    /// </summary>
+    function Sqrt(): IECFieldElement; override;
+
+    function Equals(const other: IECFieldElement): Boolean; overload; override;
+
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property IsZero: Boolean read GetIsZero;
+    property IsOne: Boolean read GetIsOne;
+    property FieldName: string read GetFieldName;
+    property FieldSize: Int32 read GetFieldSize;
+
+    property Representation: Int32 read GetRepresentation;
+
+    property M: Int32 read GetM;
+
+    property k1: Int32 read GetK1;
+
+    property k2: Int32 read GetK2;
+
+    property k3: Int32 read GetK3;
+
+  end;
+
+implementation
+
+{ TSecT283FieldElement }
+
+function TSecT283FieldElement.Add(const b: IECFieldElement): IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Add(Fx, (b as ISecT283FieldElement).X, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.AddOne: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.AddOne(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+constructor TSecT283FieldElement.Create(const X: TBigInteger);
+begin
+  if ((not(X.IsInitialized)) or (X.SignValue < 0) or (X.BitLength > 283)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidValueForSecT283FieldElement, ['x']);
+  end;
+  Inherited Create();
+  Fx := TSecT283Field.FromBigInteger(X);
+end;
+
+constructor TSecT283FieldElement.Create;
+begin
+  Inherited Create();
+  Fx := TNat320.Create64();
+end;
+
+constructor TSecT283FieldElement.Create(X: TCryptoLibUInt64Array);
+begin
+  Inherited Create();
+  Fx := X;
+end;
+
+function TSecT283FieldElement.Divide(const b: IECFieldElement): IECFieldElement;
+begin
+  result := Multiply(b.Invert());
+end;
+
+function TSecT283FieldElement.Equals(const other: ISecT283FieldElement)
+  : Boolean;
+begin
+  if ((Self as ISecT283FieldElement) = other) then
+  begin
+    result := true;
+    Exit;
+  end;
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TNat320.Eq64(Fx, other.X);
+end;
+
+function TSecT283FieldElement.Equals(const other: IECFieldElement): Boolean;
+begin
+  result := Equals(other as ISecT283FieldElement);
+end;
+
+function TSecT283FieldElement.GetFieldName: string;
+begin
+  result := 'SecT283Field';
+end;
+
+function TSecT283FieldElement.GetFieldSize: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283FieldElement.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := 2831275 xor TArrayUtils.GetArrayHashCode(Fx, 0, 5);
+end;
+
+function TSecT283FieldElement.GetIsOne: Boolean;
+begin
+  result := TNat320.IsOne64(Fx);
+end;
+
+function TSecT283FieldElement.GetIsZero: Boolean;
+begin
+  result := TNat320.IsZero64(Fx);
+end;
+
+function TSecT283FieldElement.GetK1: Int32;
+begin
+  result := 5;
+end;
+
+function TSecT283FieldElement.GetK2: Int32;
+begin
+  result := 7;
+end;
+
+function TSecT283FieldElement.GetK3: Int32;
+begin
+  result := 12;
+end;
+
+function TSecT283FieldElement.GetM: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283FieldElement.GetRepresentation: Int32;
+begin
+  result := TF2mFieldElement.Ppb;
+end;
+
+function TSecT283FieldElement.GetX: TCryptoLibUInt64Array;
+begin
+  result := Fx;
+end;
+
+function TSecT283FieldElement.Invert: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Invert(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Multiply(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Multiply(Fx, (b as ISecT283FieldElement).X, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.MultiplyMinusProduct(const b, X,
+  y: IECFieldElement): IECFieldElement;
+begin
+  result := MultiplyPlusProduct(b, X, y);
+end;
+
+function TSecT283FieldElement.MultiplyPlusProduct(const b, X,
+  y: IECFieldElement): IECFieldElement;
+var
+  ax, bx, xx, yx, tt, z: TCryptoLibUInt64Array;
+begin
+  ax := Fx;
+  bx := (b as ISecT283FieldElement).X;
+  xx := (X as ISecT283FieldElement).X;
+  yx := (y as ISecT283FieldElement).X;
+
+  tt := TNat.Create64(9);
+  TSecT283Field.MultiplyAddToExt(ax, bx, tt);
+  TSecT283Field.MultiplyAddToExt(xx, yx, tt);
+
+  z := TNat320.Create64();
+  TSecT283Field.Reduce(tt, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Negate: IECFieldElement;
+begin
+  result := Self as IECFieldElement;
+end;
+
+function TSecT283FieldElement.Sqrt: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Sqrt(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Square: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Square(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.SquareMinusProduct(const X, y: IECFieldElement)
+  : IECFieldElement;
+begin
+  result := SquarePlusProduct(X, y);
+end;
+
+function TSecT283FieldElement.SquarePlusProduct(const X, y: IECFieldElement)
+  : IECFieldElement;
+var
+  ax, xx, yx, tt, z: TCryptoLibUInt64Array;
+begin
+  ax := Fx;
+  xx := (X as ISecT283FieldElement).X;
+  yx := (y as ISecT283FieldElement).X;
+
+  tt := TNat.Create64(9);
+  TSecT283Field.SquareAddToExt(ax, tt);
+  TSecT283Field.MultiplyAddToExt(xx, yx, tt);
+
+  z := TNat320.Create64();
+  TSecT283Field.Reduce(tt, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.SquarePow(pow: Int32): IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  if (pow < 1) then
+  begin
+    result := Self as IECFieldElement;
+    Exit;
+  end;
+
+  z := TNat320.Create64();
+  TSecT283Field.SquareN(Fx, pow, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Subtract(const b: IECFieldElement)
+  : IECFieldElement;
+begin
+  // Addition and subtraction are the same in F2m
+  result := Add(b);
+end;
+
+function TSecT283FieldElement.TestBitZero: Boolean;
+begin
+  result := (Fx[0] and UInt64(1)) <> UInt64(0);
+end;
+
+function TSecT283FieldElement.ToBigInteger: TBigInteger;
+begin
+  result := TNat320.ToBigInteger64(Fx);
+end;
+
+function TSecT283FieldElement.Trace: Int32;
+begin
+  result := Int32(TSecT283Field.Trace(Fx));
+end;
+
+end.

+ 283 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283K1Curve.pas

@@ -0,0 +1,283 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpSecT283K1Curve;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpHex,
+  ClpBits,
+  ClpNat320,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpSecT283FieldElement,
+  ClpISecT283FieldElement,
+  ClpSecT283K1Point,
+  ClpISecT283K1Curve,
+  ClpISecT283K1Point,
+  ClpIECFieldElement,
+  ClpWTauNafMultiplier,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecT283K1Curve = class sealed(TAbstractF2mCurve, ISecT283K1Curve)
+
+  strict private
+
+  type
+    TSecT283K1LookupTable = class sealed(TInterfacedObject,
+      ISecT283K1LookupTable, IECLookupTable)
+
+    strict private
+    var
+      Fm_outer: ISecT283K1Curve;
+      Fm_table: TCryptoLibUInt64Array;
+      Fm_size: Int32;
+
+      function GetSize: Int32; virtual;
+
+    public
+
+      constructor Create(const outer: ISecT283K1Curve;
+        table: TCryptoLibUInt64Array; size: Int32);
+
+      function Lookup(index: Int32): IECPoint; virtual;
+
+      property size: Int32 read GetSize;
+
+    end;
+
+  const
+    SECT283K1_DEFAULT_COORDS = Int32(TECCurve.COORD_LAMBDA_PROJECTIVE);
+    SECT283K1_FE_LONGS = Int32(5);
+
+    function GetM: Int32; inline;
+    function GetK1: Int32; inline;
+    function GetK2: Int32; inline;
+    function GetK3: Int32; inline;
+    function GetIsTrinomial: Boolean; inline;
+
+  strict protected
+  var
+    Fm_infinity: ISecT283K1Point;
+
+    function GetFieldSize: Int32; override;
+    function GetInfinity: IECPoint; override;
+    function GetIsKoblitz: Boolean; override;
+
+    function CloneCurve(): IECCurve; override;
+
+    function CreateDefaultMultiplier(): IECMultiplier; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      withCompression: Boolean): IECPoint; overload; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+      : IECPoint; overload; override;
+
+  public
+    constructor Create();
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
+
+    function SupportsCoordinateSystem(coord: Int32): Boolean; override;
+
+    function CreateCacheSafeLookupTable
+      (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32)
+      : IECLookupTable; override;
+
+    property Infinity: IECPoint read GetInfinity;
+    property FieldSize: Int32 read GetFieldSize;
+    property IsKoblitz: Boolean read GetIsKoblitz;
+
+    property M: Int32 read GetM;
+    property K1: Int32 read GetK1;
+    property K2: Int32 read GetK2;
+    property K3: Int32 read GetK3;
+    property IsTrinomial: Boolean read GetIsTrinomial;
+
+  end;
+
+implementation
+
+{ TSecT283K1Curve }
+
+constructor TSecT283K1Curve.Create;
+begin
+  Inherited Create(283, 5, 7, 12);
+  Fm_infinity := TSecT283K1Point.Create(Self as IECCurve, Nil, Nil);
+
+  Fm_a := FromBigInteger(TBigInteger.Zero);
+  Fm_b := FromBigInteger(TBigInteger.One);
+  Fm_order := TBigInteger.Create(1,
+    THex.Decode
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61')
+    );
+  Fm_cofactor := TBigInteger.ValueOf(4);
+
+  Fm_coord := SECT283K1_DEFAULT_COORDS;
+end;
+
+function TSecT283K1Curve.CloneCurve: IECCurve;
+begin
+  result := TSecT283K1Curve.Create() as ISecT283K1Curve;
+end;
+
+function TSecT283K1Curve.CreateCacheSafeLookupTable
+  (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
+var
+  table: TCryptoLibUInt64Array;
+  pos, i: Int32;
+  p: IECPoint;
+begin
+  System.SetLength(table, len * SECT283K1_FE_LONGS * 2);
+
+  pos := 0;
+  for i := 0 to System.Pred(len) do
+  begin
+    p := points[off + i];
+    TNat320.Copy64((p.RawXCoord as ISecT283FieldElement).x, 0, table, pos);
+    pos := pos + SECT283K1_FE_LONGS;
+    TNat320.Copy64((p.RawYCoord as ISecT283FieldElement).x, 0, table, pos);
+    pos := pos + SECT283K1_FE_LONGS;
+  end;
+
+  result := TSecT283K1LookupTable.Create(Self as ISecT283K1Curve, table, len);
+end;
+
+function TSecT283K1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  withCompression: Boolean): IECPoint;
+begin
+  result := TSecT283K1Point.Create(Self as IECCurve, x, y, withCompression);
+end;
+
+function TSecT283K1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+  : IECPoint;
+begin
+  result := TSecT283K1Point.Create(Self as IECCurve, x, y, zs, withCompression);
+end;
+
+function TSecT283K1Curve.FromBigInteger(const x: TBigInteger): IECFieldElement;
+begin
+  result := TSecT283FieldElement.Create(x);
+end;
+
+function TSecT283K1Curve.GetFieldSize: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283K1Curve.GetInfinity: IECPoint;
+begin
+  result := Fm_infinity;
+end;
+
+function TSecT283K1Curve.GetIsKoblitz: Boolean;
+begin
+  result := True;
+end;
+
+function TSecT283K1Curve.GetIsTrinomial: Boolean;
+begin
+  result := False;
+end;
+
+function TSecT283K1Curve.GetK1: Int32;
+begin
+  result := 5;
+end;
+
+function TSecT283K1Curve.GetK2: Int32;
+begin
+  result := 7;
+end;
+
+function TSecT283K1Curve.GetK3: Int32;
+begin
+  result := 12;
+end;
+
+function TSecT283K1Curve.GetM: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283K1Curve.SupportsCoordinateSystem(coord: Int32): Boolean;
+begin
+  case coord of
+    COORD_LAMBDA_PROJECTIVE:
+      result := True
+  else
+    result := False;
+  end;
+end;
+
+function TSecT283K1Curve.CreateDefaultMultiplier(): IECMultiplier;
+begin
+  result := TWTauNafMultiplier.Create() as IECMultiplier;
+end;
+
+{ TSecT283K1Curve.TSecT283K1LookupTable }
+
+constructor TSecT283K1Curve.TSecT283K1LookupTable.Create
+  (const outer: ISecT283K1Curve; table: TCryptoLibUInt64Array; size: Int32);
+begin
+  Inherited Create();
+  Fm_outer := outer;
+  Fm_table := table;
+  Fm_size := size;
+end;
+
+function TSecT283K1Curve.TSecT283K1LookupTable.GetSize: Int32;
+begin
+  result := Fm_size;
+end;
+
+function TSecT283K1Curve.TSecT283K1LookupTable.Lookup(index: Int32): IECPoint;
+var
+  x, y: TCryptoLibUInt64Array;
+  pos, i, J: Int32;
+  MASK: UInt64;
+begin
+  x := TNat320.Create64();
+  y := TNat320.Create64();
+  pos := 0;
+
+  for i := 0 to System.Pred(Fm_size) do
+  begin
+    MASK := UInt64(Int64(TBits.Asr32((i xor index) - 1, 31)));
+
+    for J := 0 to System.Pred(SECT283K1_FE_LONGS) do
+    begin
+      x[J] := x[J] xor (Fm_table[pos + J] and MASK);
+      y[J] := y[J] xor (Fm_table[pos + SECT283K1_FE_LONGS + J] and MASK);
+    end;
+
+    pos := pos + (SECT283K1_FE_LONGS * 2);
+  end;
+
+  result := Fm_outer.CreateRawPoint(TSecT283FieldElement.Create(x)
+    as ISecT283FieldElement, TSecT283FieldElement.Create(y)
+    as ISecT283FieldElement, False);
+end;
+
+end.

+ 476 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283K1Point.pas

@@ -0,0 +1,476 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpSecT283K1Point;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpECPoint,
+  ClpISecT283K1Point,
+  ClpIECFieldElement,
+  ClpIECInterface,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOneOfECFieldElementIsNil = 'Exactly One of the Field Elements is Nil';
+
+type
+  TSecT283K1Point = class sealed(TAbstractF2mPoint, ISecT283K1Point)
+
+  strict protected
+    function Detach(): IECPoint; override;
+
+    function GetCompressionYTilde: Boolean; override;
+    property CompressionYTilde: Boolean read GetCompressionYTilde;
+
+  public
+
+    /// <summary>
+    /// Create a point which encodes without point compression.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement);
+      overload; deprecated 'Use ECCurve.createPoint to construct points';
+
+    /// <summary>
+    /// Create a point that encodes with or without point compresion.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    /// <param name="withCompression">
+    /// if true encode with point compression
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      withCompression: Boolean); overload;
+      deprecated
+      'Per-point compression property will be removed, see GetEncoded(boolean)';
+
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>;
+      withCompression: Boolean); overload;
+
+    function Add(const b: IECPoint): IECPoint; override;
+    function Negate(): IECPoint; override;
+
+    function Twice(): IECPoint; override;
+    function TwicePlus(const b: IECPoint): IECPoint; override;
+
+    function GetYCoord: IECFieldElement; override;
+    property YCoord: IECFieldElement read GetYCoord;
+
+  end;
+
+implementation
+
+{ TSecT283K1Point }
+
+function TSecT283K1Point.Add(const b: IECPoint): IECPoint;
+var
+  LCurve: IECCurve;
+  X1, X2, L1, L2, Z1, Z2, U2, S2, U1, S1, A, LB, X3, L3, Z3, Y1, Y2, L, Y3, AU1,
+    AU2, ABZ2: IECFieldElement;
+  Z1IsOne, Z2IsOne: Boolean;
+  p: IECPoint;
+begin
+  if ((IsInfinity)) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if ((b.IsInfinity)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  LCurve := curve;
+
+  X1 := RawXCoord;
+  X2 := b.RawXCoord;
+
+  if (X1.IsZero) then
+  begin
+    if (X2.IsZero) then
+    begin
+      result := LCurve.Infinity;
+      Exit;
+    end;
+
+    result := b.Add(Self as IECPoint);
+    Exit;
+  end;
+
+  L1 := RawYCoord;
+  Z1 := RawZCoords[0];
+  L2 := b.RawYCoord;
+  Z2 := b.RawZCoords[0];
+
+  Z1IsOne := Z1.IsOne;
+  U2 := X2;
+  S2 := L2;
+  if (not(Z1IsOne)) then
+  begin
+    U2 := U2.Multiply(Z1);
+    S2 := S2.Multiply(Z1);
+  end;
+
+  Z2IsOne := Z2.IsOne;
+  U1 := X1;
+  S1 := L1;
+  if (not(Z2IsOne)) then
+  begin
+    U1 := U1.Multiply(Z2);
+    S1 := S1.Multiply(Z2);
+  end;
+
+  A := S1.Add(S2);
+  LB := U1.Add(U2);
+
+  if (LB.IsZero) then
+  begin
+    if (A.IsZero) then
+    begin
+      result := Twice();
+      Exit;
+    end;
+
+    result := LCurve.Infinity;
+    Exit;
+  end;
+
+  if (X2.IsZero) then
+  begin
+    // TODO This can probably be optimized quite a bit
+    p := Self.Normalize();
+    X1 := p.XCoord;
+    Y1 := p.YCoord;
+
+    Y2 := L2;
+    L := Y1.Add(Y2).Divide(X1);
+
+    X3 := L.Square().Add(L).Add(X1);
+    if (X3.IsZero) then
+    begin
+      result := TSecT283K1Point.Create(LCurve, X3, LCurve.b, IsCompressed);
+      Exit;
+    end;
+
+    Y3 := L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+    L3 := Y3.Divide(X3).Add(X3);
+    Z3 := LCurve.FromBigInteger(TBigInteger.One);
+  end
+  else
+  begin
+    LB := LB.Square();
+
+    AU1 := A.Multiply(U1);
+    AU2 := A.Multiply(U2);
+
+    X3 := AU1.Multiply(AU2);
+    if (X3.IsZero) then
+    begin
+      result := TSecT283K1Point.Create(curve, X3, curve.b, IsCompressed);
+      Exit;
+    end;
+
+    ABZ2 := A.Multiply(LB);
+    if (not(Z2IsOne)) then
+    begin
+      ABZ2 := ABZ2.Multiply(Z2);
+    end;
+
+    L3 := AU2.Add(LB).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+    Z3 := ABZ2;
+    if (not(Z1IsOne)) then
+    begin
+      Z3 := Z3.Multiply(Z1);
+    end;
+  end;
+
+  result := TSecT283K1Point.Create(LCurve, X3, L3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed);
+end;
+
+constructor TSecT283K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement);
+begin
+  Create(curve, x, y, false);
+end;
+
+constructor TSecT283K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; zs: TCryptoLibGenericArray<IECFieldElement>;
+  withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, zs, withCompression);
+end;
+
+constructor TSecT283K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, withCompression);
+  if ((x = Nil) <> (y = Nil)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SOneOfECFieldElementIsNil);
+  end;
+end;
+
+function TSecT283K1Point.Detach: IECPoint;
+begin
+  result := TSecT283K1Point.Create(Nil, AffineXCoord, AffineYCoord);
+end;
+
+function TSecT283K1Point.GetCompressionYTilde: Boolean;
+var
+  x, y: IECFieldElement;
+begin
+  x := RawXCoord;
+  if (x.IsZero) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  y := RawYCoord;
+
+  // Y is actually Lambda (X + Y/X) here
+  result := y.TestBitZero() <> x.TestBitZero();
+end;
+
+function TSecT283K1Point.GetYCoord: IECFieldElement;
+var
+  x, L, y, Z: IECFieldElement;
+begin
+  x := RawXCoord;
+  L := RawYCoord;
+
+  if ((IsInfinity) or (x.IsZero)) then
+  begin
+    result := L;
+    Exit;
+  end;
+
+  // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+  y := L.Add(x).Multiply(x);
+
+  Z := RawZCoords[0];
+  if (not(Z.IsOne)) then
+  begin
+    y := y.Divide(Z);
+  end;
+
+  result := y;
+end;
+
+function TSecT283K1Point.Negate: IECPoint;
+var
+  x, L, Z: IECFieldElement;
+begin
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  x := RawXCoord;
+  if (x.IsZero) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  // L is actually Lambda (X + Y/X) here
+  L := RawYCoord;
+  Z := RawZCoords[0];
+  result := TSecT283K1Point.Create(curve, x, L.Add(Z),
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z), IsCompressed);
+end;
+
+function TSecT283K1Point.Twice: IECPoint;
+var
+  LCurve: IECCurve;
+  X1, L1, Z1, Z1Sq, T, X3, Z3, t1, t2, L3: IECFieldElement;
+  Z1IsOne: Boolean;
+begin
+  if ((IsInfinity)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  LCurve := Self.curve;
+
+  X1 := RawXCoord;
+  if (X1.IsZero) then
+  begin
+    // A point with X == 0 is it's own Additive inverse
+    result := LCurve.Infinity;
+    Exit;
+  end;
+
+  L1 := RawYCoord;
+  Z1 := RawZCoords[0];
+
+  Z1IsOne := Z1.IsOne;
+  if Z1IsOne then
+  begin
+    Z1Sq := Z1;
+  end
+  else
+  begin
+    Z1Sq := Z1.Square();
+  end;
+
+  if (Z1IsOne) then
+  begin
+    T := L1.Square().Add(L1);
+  end
+  else
+  begin
+    T := L1.Add(Z1).Multiply(L1);
+  end;
+
+  if (T.IsZero) then
+  begin
+    result := TSecT283K1Point.Create(LCurve, T, LCurve.b, IsCompressed);
+    Exit;
+  end;
+
+  X3 := T.Square();
+  if Z1IsOne then
+  begin
+    Z3 := T;
+  end
+  else
+  begin
+    Z3 := T.Multiply(Z1Sq);
+  end;
+
+  t1 := L1.Add(X1).Square();
+
+  if Z1IsOne then
+  begin
+    t2 := Z1;
+  end
+  else
+  begin
+    t2 := Z1Sq.Square();
+  end;
+
+  L3 := t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3);
+
+  result := TSecT283K1Point.Create(LCurve, X3, L3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed);
+end;
+
+function TSecT283K1Point.TwicePlus(const b: IECPoint): IECPoint;
+var
+  LCurve: IECCurve;
+  X1, X2, Z2, L1, Z1, L2, X1Sq, L1Sq, Z1Sq, L1Z1, T, L2plus1, A, X2Z1Sq, LB, X3,
+    Z3, L3: IECFieldElement;
+begin
+  if ((IsInfinity)) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  LCurve := Self.curve;
+
+  X1 := RawXCoord;
+  if (X1.IsZero) then
+  begin
+    // A point with X == 0 is it's own Additive inverse
+    result := b;
+    Exit;
+  end;
+
+  // NOTE: TwicePlus() only optimized for lambda-affine argument
+  X2 := b.RawXCoord;
+  Z2 := b.RawZCoords[0];
+  if ((X2.IsZero) or (not(Z2.IsOne))) then
+  begin
+    result := Twice().Add(b);
+    Exit;
+  end;
+
+  L1 := RawYCoord;
+  Z1 := RawZCoords[0];
+  L2 := b.RawYCoord;
+
+  X1Sq := X1.Square();
+  L1Sq := L1.Square();
+  Z1Sq := Z1.Square();
+  L1Z1 := L1.Multiply(Z1);
+
+  T := L1Sq.Add(L1Z1);
+  L2plus1 := L2.AddOne();
+  A := L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+  X2Z1Sq := X2.Multiply(Z1Sq);
+  LB := X2Z1Sq.Add(T).Square();
+
+  if (LB.IsZero) then
+  begin
+    if (A.IsZero) then
+    begin
+      result := b.Twice();
+      Exit;
+    end;
+
+    result := LCurve.Infinity;
+    Exit;
+  end;
+
+  if (A.IsZero) then
+  begin
+    result := TSecT283K1Point.Create(LCurve, A, LCurve.b, IsCompressed);
+    Exit;
+  end;
+
+  X3 := A.Square().Multiply(X2Z1Sq);
+  Z3 := A.Multiply(LB).Multiply(Z1Sq);
+  L3 := A.Add(LB).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+  result := TSecT283K1Point.Create(LCurve, X3, L3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed);
+end;
+
+end.

+ 7 - 0
CryptoLib/src/Math/Field/ClpGF2Polynomial.pas

@@ -42,7 +42,9 @@ type
 
     function GetExponentsPresent(): TCryptoLibInt32Array; virtual;
 
+    function Equals(other: TObject): Boolean; overload; override;
     function Equals(const other: IGF2Polynomial): Boolean; reintroduce;
+      overload;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}override;
 
@@ -78,6 +80,11 @@ begin
   Result := TArrayUtils.AreEqual(Fexponents, other.exponents);
 end;
 
+function TGF2Polynomial.Equals(other: TObject): Boolean;
+begin
+  Result := Self.Equals((other as TGF2Polynomial) as IGF2Polynomial);
+end;
+
 function TGF2Polynomial.GetDegree: Int32;
 begin
   Result := Fexponents[System.Length(Fexponents) - 1];

+ 235 - 0
CryptoLib/src/Math/Raw/ClpInterleave.pas

@@ -0,0 +1,235 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpInterleave;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes;
+
+type
+  TInterleave = class sealed(TObject)
+
+  strict private
+  const
+    M32 = UInt64($55555555);
+    M64 = UInt64($5555555555555555);
+    M64R = UInt64($AAAAAAAAAAAAAAAA);
+
+  public
+    class function Expand8to16(x: UInt32): UInt32; static; inline;
+    class function Expand16to32(x: UInt32): UInt32; static; inline;
+    class function Expand32to64(x: UInt32): UInt64; static;
+    class procedure Expand64To128(x: UInt64; z: TCryptoLibUInt64Array;
+      zOff: Int32); static;
+    class procedure Expand64To128Rev(x: UInt64; z: TCryptoLibUInt64Array;
+      zOff: Int32); static;
+    class function Shuffle(x: UInt32): UInt32; overload; static;
+    class function Shuffle(x: UInt64): UInt64; overload; static;
+    class function Shuffle2(x: UInt32): UInt32; static;
+    class function Unshuffle(x: UInt32): UInt32; overload; static;
+    class function Unshuffle(x: UInt64): UInt64; overload; static;
+    class function Unshuffle2(x: UInt32): UInt32; static;
+
+  end;
+
+implementation
+
+{ TInterleave }
+
+class function TInterleave.Expand8to16(x: UInt32): UInt32;
+begin
+  x := x and UInt32($FF);
+  x := (x or (x shl 4)) and UInt32($0F0F);
+  x := (x or (x shl 2)) and UInt32($3333);
+  x := (x or (x shl 1)) and UInt32($5555);
+  result := x;
+end;
+
+class function TInterleave.Expand16to32(x: UInt32): UInt32;
+begin
+  x := x and UInt32($FFFF);
+  x := (x or (x shl 8)) and UInt32($00FF00FF);
+  x := (x or (x shl 4)) and UInt32($0F0F0F0F);
+  x := (x or (x shl 2)) and UInt32($33333333);
+  x := (x or (x shl 1)) and UInt32($55555555);
+  result := x;
+end;
+
+class function TInterleave.Expand32to64(x: UInt32): UInt64;
+var
+  t: UInt32;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt32($0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt32($22222222);
+  x := x xor (t xor (t shl 1));
+
+  result := ((x shr 1) and M32) shl 32 or (x and M32);
+end;
+
+class procedure TInterleave.Expand64To128(x: UInt64; z: TCryptoLibUInt64Array;
+  zOff: Int32);
+var
+  t: UInt64;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+
+  z[zOff] := (x) and M64;
+  z[zOff + 1] := (x shr 1) and M64;
+end;
+
+class procedure TInterleave.Expand64To128Rev(x: UInt64;
+  z: TCryptoLibUInt64Array; zOff: Int32);
+var
+  t: UInt64;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+
+  z[zOff] := (x) and M64R;
+  z[zOff + 1] := (x shl 1) and M64R;
+end;
+
+class function TInterleave.Shuffle(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt32($0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt32($22222222);
+  x := x xor (t xor (t shl 1));
+  result := x;
+end;
+
+class function TInterleave.Shuffle(x: UInt64): UInt64;
+var
+  t: UInt64;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+  result := x;
+end;
+
+class function TInterleave.Shuffle2(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "shuffle" (twice) low half to even bits and high half to odd bits
+  t := (x xor (x shr 7)) and UInt32($00AA00AA);
+  x := x xor (t xor (t shl 7));
+  t := (x xor (x shr 14)) and UInt32($0000CCCC);
+  x := x xor (t xor (t shl 14));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  result := x;
+end;
+
+class function TInterleave.Unshuffle(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "unshuffle" even bits to low half and odd bits to high half
+  t := (x xor (x shr 1)) and UInt32($22222222);
+  x := x xor (t xor (t shl 1));
+  t := (x xor (x shr 2)) and UInt32($0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  result := x;
+end;
+
+class function TInterleave.Unshuffle(x: UInt64): UInt64;
+var
+  t: UInt64;
+begin
+  // "unshuffle" even bits to low half and odd bits to high half
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  result := x;
+end;
+
+class function TInterleave.Unshuffle2(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "unshuffle" (twice) even bits to low half and odd bits to high half
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 14)) and UInt32($0000CCCC);
+  x := x xor (t xor (t shl 14));
+  t := (x xor (x shr 7)) and UInt32($00AA00AA);
+  x := x xor (t xor (t shl 7));
+  result := x;
+end;
+
+end.

+ 33 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -25,7 +25,7 @@
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
     <Version Major="2" Minor="3"/>
-    <Files Count="438">
+    <Files Count="446">
       <Item1>
         <Filename Value="..\..\Asn1\ClpAsn1Encodable.pas"/>
         <UnitName Value="ClpAsn1Encodable"/>
@@ -1780,6 +1780,38 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <Filename Value="..\..\Interfaces\ClpISecP521R1Curve.pas"/>
         <UnitName Value="ClpISecP521R1Curve"/>
       </Item438>
+      <Item439>
+        <Filename Value="..\..\Math\Raw\ClpInterleave.pas"/>
+        <UnitName Value="ClpInterleave"/>
+      </Item439>
+      <Item440>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283Field.pas"/>
+        <UnitName Value="ClpSecT283Field"/>
+      </Item440>
+      <Item441>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283FieldElement.pas"/>
+        <UnitName Value="ClpSecT283FieldElement"/>
+      </Item441>
+      <Item442>
+        <Filename Value="..\..\Interfaces\ClpISecT283FieldElement.pas"/>
+        <UnitName Value="ClpISecT283FieldElement"/>
+      </Item442>
+      <Item443>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283K1Point.pas"/>
+        <UnitName Value="ClpSecT283K1Point"/>
+      </Item443>
+      <Item444>
+        <Filename Value="..\..\Interfaces\ClpISecT283K1Point.pas"/>
+        <UnitName Value="ClpISecT283K1Point"/>
+      </Item444>
+      <Item445>
+        <Filename Value="..\..\Interfaces\ClpISecT283K1Curve.pas"/>
+        <UnitName Value="ClpISecT283K1Curve"/>
+      </Item445>
+      <Item446>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283K1Curve.pas"/>
+        <UnitName Value="ClpSecT283K1Curve"/>
+      </Item446>
     </Files>
     <RequiredPkgs Count="3">
       <Item1>

+ 4 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas

@@ -143,7 +143,10 @@ uses
   ClpISecP384R1FieldElement, ClpSecP384R1Point, ClpISecP384R1Point, 
   ClpSecP384R1Curve, ClpNat192, ClpISecP384R1Curve, ClpSecP521R1Field, 
   ClpNat512, ClpSecP521R1FieldElement, ClpISecP521R1FieldElement, 
-  ClpSecP521R1Point, ClpISecP521R1Point, ClpSecP521R1Curve, ClpISecP521R1Curve;
+  ClpSecP521R1Point, ClpISecP521R1Point, ClpSecP521R1Curve, 
+  ClpISecP521R1Curve, ClpInterleave, ClpSecT283Field, ClpSecT283FieldElement, 
+  ClpISecT283FieldElement, ClpSecT283K1Point, ClpISecT283K1Point, 
+  ClpISecT283K1Curve, ClpSecT283K1Curve;
 
 implementation
 

+ 31 - 0
CryptoLib/src/Utils/ClpArrayUtils.pas

@@ -65,6 +65,9 @@ type
     class function GetArrayHashCode(const data: TCryptoLibUInt32Array;
       off, len: Int32): Int32; overload; static;
 
+    class function GetArrayHashCode(const data: TCryptoLibUInt64Array;
+      off, len: Int32): Int32; overload; static;
+
     class function Prepend(const A: TCryptoLibByteArray; B: Byte)
       : TCryptoLibByteArray; static;
 
@@ -316,6 +319,34 @@ begin
   Result := hc;
 end;
 
+class function TArrayUtils.GetArrayHashCode(const data: TCryptoLibUInt64Array;
+  off, len: Int32): Int32;
+var
+  i, hc: Int32;
+  di: UInt64;
+begin
+  if data = Nil then
+  begin
+    Result := 0;
+    Exit;
+  end;
+
+  i := len;
+  hc := i + 1;
+
+  System.Dec(i);
+  while (i >= 0) do
+  begin
+    di := data[off + i];
+    hc := hc * 257;
+    hc := hc xor Int32(di);
+    hc := hc * 257;
+    hc := hc xor Int32(di shr 32);
+    System.Dec(i);
+  end;
+  Result := hc;
+end;
+
 class function TArrayUtils.Prepend(const A: TCryptoLibByteArray; B: Byte)
   : TCryptoLibByteArray;
 var

+ 31 - 0
CryptoLib/src/Utils/ClpBits.pas

@@ -108,6 +108,28 @@ type
     class function NegativeRightShift32(Value: UInt32; ShiftBits: Int32)
       : UInt32; static; inline;
 
+    /// <summary>
+    /// Calculates Negative Right Shift. This was implemented to circumvent a
+    /// compiler issue when performing Shift Right on certain values with a
+    /// Negative Shift Bits. In some C Compilers, this is "Undefined"
+    /// </summary>
+    /// <param name="Value">
+    /// Value to Perform Shift On
+    /// </param>
+    /// <param name="ShiftBits">
+    /// Integer, number of bits to shift value to. This Number <b>Must be
+    /// Negative</b>
+    /// </param>
+    /// <param name="value">
+    /// UInt64 value to compute 'NRS' on.
+    /// </param>
+    /// <returns>
+    /// Shifted value.
+    /// </returns>
+
+    class function NegativeRightShift64(Value: UInt64; ShiftBits: Int32)
+      : UInt64; static; inline;
+
     class function RotateLeft8(a_value: Byte; a_n: Int32): Byte; static; inline;
     class function RotateLeft32(a_value: UInt32; a_n: Int32): UInt32;
       static; inline;
@@ -272,6 +294,15 @@ begin
   Result := Value shr (32 + ShiftBits);
 end;
 
+class function TBits.NegativeRightShift64(Value: UInt64;
+  ShiftBits: Int32): UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(ShiftBits < 0);
+{$ENDIF DEBUG}
+  Result := Value shr (64 + ShiftBits);
+end;
+
 class function TBits.RotateLeft32(a_value: UInt32; a_n: Int32): UInt32;
 begin
 {$IFDEF DEBUG}