|
@@ -25,17 +25,18 @@ uses
|
|
|
SysUtils,
|
|
|
Math,
|
|
|
ClpCryptoLibTypes,
|
|
|
- ClpBits,
|
|
|
ClpBigInteger,
|
|
|
- ClpWNafPreCompInfo,
|
|
|
- ClpIPolynomialExtensionField,
|
|
|
- ClpIGlvEndomorphism,
|
|
|
- ClpIWNafPreCompInfo,
|
|
|
- ClpIPreCompInfo,
|
|
|
- ClpIPreCompCallBack,
|
|
|
+ ClpBits,
|
|
|
+ ClpNat,
|
|
|
ClpIECC,
|
|
|
- ClpECCurveConstants,
|
|
|
- ClpIFiniteField;
|
|
|
+ ClpECCompUtilities,
|
|
|
+ ClpIWNafPreCompInfo,
|
|
|
+ ClpIFiniteField,
|
|
|
+ ClpIFixedPointPreCompInfo,
|
|
|
+ ClpIGlvEndomorphism,
|
|
|
+ ClpIMultipliers,
|
|
|
+ ClpMultipliers,
|
|
|
+ ClpIPolynomialExtensionField;
|
|
|
|
|
|
resourcestring
|
|
|
SInvalidArray =
|
|
@@ -43,160 +44,8 @@ resourcestring
|
|
|
SInvalidPointLocation = 'Point Must be on the Same Curve';
|
|
|
SInvalidPoint = 'Invalid Point, "P"';
|
|
|
SInvalidResult = 'Invalid Result';
|
|
|
- SInvalidRange = 'Must be in the Range [2, 16], "width"';
|
|
|
- SInvalidRange2 = 'Must be in the Range [2, 8], "width"';
|
|
|
-
|
|
|
-type
|
|
|
- TWNafUtilities = class abstract(TObject)
|
|
|
-
|
|
|
- strict private
|
|
|
- const
|
|
|
- FDEFAULT_WINDOW_SIZE_CUTOFFS: array [0 .. 5] of Int32 = (13, 41, 121, 337,
|
|
|
- 897, 2305);
|
|
|
-
|
|
|
- class var
|
|
|
- FEMPTY_BYTES: TCryptoLibByteArray;
|
|
|
- FEMPTY_INTS: TCryptoLibInt32Array;
|
|
|
-
|
|
|
- type
|
|
|
- IMapPointCallback = interface(IPreCompCallback)
|
|
|
- ['{730BF27F-D5C3-4DF4-AC77-B8653C457C10}']
|
|
|
-
|
|
|
- end;
|
|
|
-
|
|
|
- type
|
|
|
- TMapPointCallback = class(TInterfacedObject, IPreCompCallback,
|
|
|
- IMapPointCallback)
|
|
|
-
|
|
|
- strict private
|
|
|
- var
|
|
|
- Fm_wnafPreCompP: IWNafPreCompInfo;
|
|
|
- Fm_includeNegated: Boolean;
|
|
|
- Fm_pointMap: IECPointMap;
|
|
|
-
|
|
|
- public
|
|
|
- constructor Create(const wnafPreCompP: IWNafPreCompInfo;
|
|
|
- includeNegated: Boolean; const pointMap: IECPointMap);
|
|
|
-
|
|
|
- function Precompute(const existing: IPreCompInfo): IPreCompInfo;
|
|
|
-
|
|
|
- end;
|
|
|
-
|
|
|
- type
|
|
|
- IWNafCallback = interface(IPreCompCallback)
|
|
|
- ['{A439A606-7899-4720-937E-C2F3D94D4811}']
|
|
|
-
|
|
|
- end;
|
|
|
-
|
|
|
- type
|
|
|
- TWNafCallback = class(TInterfacedObject, IPreCompCallback, IWNafCallback)
|
|
|
-
|
|
|
- strict private
|
|
|
-
|
|
|
- var
|
|
|
- Fm_p: IECPoint;
|
|
|
- Fm_width: Int32;
|
|
|
- Fm_includeNegated: Boolean;
|
|
|
-
|
|
|
- public
|
|
|
- constructor Create(const p: IECPoint; width: Int32;
|
|
|
- includeNegated: Boolean);
|
|
|
-
|
|
|
- function Precompute(const existing: IPreCompInfo): IPreCompInfo;
|
|
|
-
|
|
|
- end;
|
|
|
-
|
|
|
- class function CheckExisting(const existingWNaf: IWNafPreCompInfo;
|
|
|
- reqPreCompLen: Int32; includeNegated: Boolean): Boolean; static; inline;
|
|
|
-
|
|
|
- class function CheckTable(const table: TCryptoLibGenericArray<IECPoint>;
|
|
|
- reqLen: Int32): Boolean; static; inline;
|
|
|
-
|
|
|
- class function Trim(const a: TCryptoLibByteArray; length: Int32)
|
|
|
- : TCryptoLibByteArray; overload; static; inline;
|
|
|
-
|
|
|
- class function Trim(const a: TCryptoLibInt32Array; length: Int32)
|
|
|
- : TCryptoLibInt32Array; overload; static; inline;
|
|
|
-
|
|
|
- class function ResizeTable(const a: TCryptoLibGenericArray<IECPoint>;
|
|
|
- length: Int32): TCryptoLibGenericArray<IECPoint>; static; inline;
|
|
|
-
|
|
|
- class procedure Boot(); static;
|
|
|
- class constructor CreateWNafUtilities();
|
|
|
-
|
|
|
- public
|
|
|
-
|
|
|
- const
|
|
|
- PRECOMP_NAME: String = 'bc_wnaf';
|
|
|
-
|
|
|
- class function GenerateCompactNaf(const k: TBigInteger)
|
|
|
- : TCryptoLibInt32Array; static;
|
|
|
- class function GenerateCompactWindowNaf(width: Int32; const k: TBigInteger)
|
|
|
- : TCryptoLibInt32Array; static;
|
|
|
-
|
|
|
- class function GenerateJsf(const g, h: TBigInteger)
|
|
|
- : TCryptoLibByteArray; static;
|
|
|
- class function GenerateNaf(const k: TBigInteger)
|
|
|
- : TCryptoLibByteArray; static;
|
|
|
- // /**
|
|
|
- // * Computes the Window NAF (non-adjacent Form) of an integer.
|
|
|
- // * @param width The width <code>w</code> of the Window NAF. The width is
|
|
|
- // * defined as the minimal number <code>w</code>, such that for any
|
|
|
- // * <code>w</code> consecutive digits in the resulting representation, at
|
|
|
- // * most one is non-zero.
|
|
|
- // * @param k The integer of which the Window NAF is computed.
|
|
|
- // * @return The Window NAF of the given width, such that the following holds:
|
|
|
- // * <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
|
|
|
- // * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
|
|
|
- // * returned <code>byte[]</code>.
|
|
|
- // */
|
|
|
- class function GenerateWindowNaf(width: Int32; const k: TBigInteger)
|
|
|
- : TCryptoLibByteArray; static;
|
|
|
-
|
|
|
- class function GetNafWeight(const k: TBigInteger): Int32; static; inline;
|
|
|
-
|
|
|
- class function GetWNafPreCompInfo(const p: IECPoint): IWNafPreCompInfo;
|
|
|
- overload; static; inline;
|
|
|
-
|
|
|
- class function GetWNafPreCompInfo(const preCompInfo: IPreCompInfo)
|
|
|
- : IWNafPreCompInfo; overload; static; inline;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Determine window width to use for a scalar multiplication of the
|
|
|
- /// given size.
|
|
|
- /// </summary>
|
|
|
- /// <param name="bits">
|
|
|
- /// the bit-length of the scalar to multiply by
|
|
|
- /// </param>
|
|
|
- /// <returns>
|
|
|
- /// the window size to use
|
|
|
- /// </returns>
|
|
|
- class function GetWindowSize(bits: Int32): Int32; overload; static; inline;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Determine window width to use for a scalar multiplication of the
|
|
|
- /// given size.
|
|
|
- /// </summary>
|
|
|
- /// <param name="bits">
|
|
|
- /// the bit-length of the scalar to multiply by
|
|
|
- /// </param>
|
|
|
- /// <param name="windowSizeCutoffs">
|
|
|
- /// a monotonically increasing list of bit sizes at which to increment
|
|
|
- /// the window width
|
|
|
- /// </param>
|
|
|
- /// <returns>
|
|
|
- /// the window size to use
|
|
|
- /// </returns>
|
|
|
- class function GetWindowSize(bits: Int32;
|
|
|
- const windowSizeCutoffs: array of Int32): Int32; overload; static;
|
|
|
-
|
|
|
- class function MapPointWithPrecomp(const p: IECPoint; width: Int32;
|
|
|
- includeNegated: Boolean; const pointMap: IECPointMap): IECPoint; static;
|
|
|
-
|
|
|
- class function Precompute(const p: IECPoint; width: Int32;
|
|
|
- includeNegated: Boolean): IWNafPreCompInfo; static;
|
|
|
-
|
|
|
- end;
|
|
|
+ SInvalidComputation =
|
|
|
+ 'Fixed-Point Comb Doesn''t Support Scalars Larger Than The Curve Order';
|
|
|
|
|
|
type
|
|
|
TECAlgorithms = class sealed(TObject)
|
|
@@ -212,6 +61,10 @@ type
|
|
|
const infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
|
|
|
const wnafs: TCryptoLibMatrixByteArray): IECPoint; overload; static;
|
|
|
|
|
|
+ class function ImplShamirsTrickFixedPoint(const p: IECPoint;
|
|
|
+ const k: TBigInteger; const q: IECPoint; const l: TBigInteger)
|
|
|
+ : IECPoint; static;
|
|
|
+
|
|
|
public
|
|
|
class function IsF2mCurve(const c: IECCurve): Boolean; static;
|
|
|
class function IsF2mField(const field: IFiniteField): Boolean; static;
|
|
@@ -222,7 +75,7 @@ type
|
|
|
const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint; static;
|
|
|
|
|
|
class function SumOfTwoMultiplies(const p: IECPoint; const a: TBigInteger;
|
|
|
- const Q: IECPoint; const b: TBigInteger): IECPoint; static;
|
|
|
+ const q: IECPoint; const b: TBigInteger): IECPoint; static;
|
|
|
|
|
|
// /*
|
|
|
// * "Shamir's Trick", originally due to E. G. Straus
|
|
@@ -243,7 +96,7 @@ type
|
|
|
// * 9: return R
|
|
|
// */
|
|
|
class function ShamirsTrick(const p: IECPoint; const k: TBigInteger;
|
|
|
- const Q: IECPoint; const l: TBigInteger): IECPoint; static;
|
|
|
+ const q: IECPoint; const l: TBigInteger): IECPoint; static;
|
|
|
|
|
|
class function ImportPoint(const c: IECCurve; const p: IECPoint)
|
|
|
: IECPoint; static;
|
|
@@ -277,14 +130,13 @@ type
|
|
|
: IECPoint; static;
|
|
|
|
|
|
class function ImplShamirsTrickJsf(const p: IECPoint; const k: TBigInteger;
|
|
|
- const Q: IECPoint; const l: TBigInteger): IECPoint; static;
|
|
|
+ const q: IECPoint; const l: TBigInteger): IECPoint; static;
|
|
|
|
|
|
class function ImplShamirsTrickWNaf(const p: IECPoint; const k: TBigInteger;
|
|
|
- const Q: IECPoint; const l: TBigInteger): IECPoint; overload; static;
|
|
|
+ const q: IECPoint; const l: TBigInteger): IECPoint; overload; static;
|
|
|
|
|
|
- class function ImplShamirsTrickWNaf(const p: IECPoint; const k: TBigInteger;
|
|
|
- const pointMapQ: IECPointMap; const l: TBigInteger): IECPoint;
|
|
|
- overload; static;
|
|
|
+ class function ImplShamirsTrickWNaf(const endomorphism: IECEndomorphism;
|
|
|
+ const p: IECPoint; const k, l: TBigInteger): IECPoint; overload; static;
|
|
|
|
|
|
class function ImplSumOfMultiplies
|
|
|
(const ps: TCryptoLibGenericArray<IECPoint>;
|
|
@@ -296,8 +148,8 @@ type
|
|
|
const ks: TCryptoLibGenericArray<TBigInteger>;
|
|
|
const glvEndomorphism: IGlvEndomorphism): IECPoint; static;
|
|
|
|
|
|
- class function ImplSumOfMultiplies
|
|
|
- (const ps: TCryptoLibGenericArray<IECPoint>; const pointMap: IECPointMap;
|
|
|
+ class function ImplSumOfMultiplies(const endomorphism: IECEndomorphism;
|
|
|
+ const ps: TCryptoLibGenericArray<IECPoint>;
|
|
|
const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
|
|
|
overload; static;
|
|
|
|
|
@@ -341,33 +193,124 @@ begin
|
|
|
result := p;
|
|
|
end;
|
|
|
|
|
|
+class function TECAlgorithms.ImplShamirsTrickFixedPoint(const p: IECPoint;
|
|
|
+ const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
|
|
|
+var
|
|
|
+ c: IECCurve;
|
|
|
+ combSize, widthP, widthQ, width, d, fullComb, i, top, j: Int32;
|
|
|
+ infoP, infoQ: IFixedPointPreCompInfo;
|
|
|
+ lookupTableP, lookupTableQ: IECLookupTable;
|
|
|
+ m: IFixedPointCombMultiplier;
|
|
|
+ r1, r2, R, addP, addQ, t: IECPoint;
|
|
|
+ BigK, BigL: TCryptoLibUInt32Array;
|
|
|
+ secretBitK, secretBitL, secretIndexK, secretIndexL: UInt32;
|
|
|
+begin
|
|
|
+ c := p.Curve;
|
|
|
+ combSize := TFixedPointUtilities.GetCombSize(c);
|
|
|
+
|
|
|
+ if (((k.BitLength) > combSize) or (l.BitLength > combSize)) then
|
|
|
+ begin
|
|
|
+ (*
|
|
|
+ * TODO The comb works best when the scalars are less than the (possibly unknown) order.
|
|
|
+ * Still, if we want to handle larger scalars, we could allow customization of the comb
|
|
|
+ * size, or alternatively we could deal with the 'extra' bits either by running the comb
|
|
|
+ * multiple times as necessary, or by using an alternative multiplier as prelude.
|
|
|
+ *)
|
|
|
+ raise EInvalidOperationCryptoLibException.CreateRes(@SInvalidComputation);
|
|
|
+ end;
|
|
|
+
|
|
|
+ infoP := TFixedPointUtilities.Precompute(p);
|
|
|
+ infoQ := TFixedPointUtilities.Precompute(q);
|
|
|
+
|
|
|
+ lookupTableP := infoP.LookupTable;
|
|
|
+ lookupTableQ := infoQ.LookupTable;
|
|
|
+
|
|
|
+ widthP := infoP.width;
|
|
|
+ widthQ := infoQ.width;
|
|
|
+
|
|
|
+ // TODO This shouldn't normally happen, but a better "solution" is desirable anyway
|
|
|
+ if (widthP <> widthQ) then
|
|
|
+ begin
|
|
|
+ m := TFixedPointCombMultiplier.Create();
|
|
|
+ r1 := m.Multiply(p, k);
|
|
|
+ r2 := m.Multiply(q, l);
|
|
|
+ result := r1.Add(r2);
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+
|
|
|
+ width := widthP;
|
|
|
+
|
|
|
+ d := ((combSize + width) - 1) div width;
|
|
|
+
|
|
|
+ R := c.Infinity;
|
|
|
+
|
|
|
+ fullComb := d * width;
|
|
|
+ BigK := TNat.FromBigInteger(fullComb, k);
|
|
|
+ BigL := TNat.FromBigInteger(fullComb, l);
|
|
|
+
|
|
|
+ top := fullComb - 1;
|
|
|
+
|
|
|
+ for i := 0 to System.Pred(d) do
|
|
|
+ begin
|
|
|
+ secretIndexK := 0;
|
|
|
+ secretIndexL := 0;
|
|
|
+
|
|
|
+ j := top - i;
|
|
|
+
|
|
|
+ while j >= 0 do
|
|
|
+ begin
|
|
|
+
|
|
|
+ secretBitK := BigK[TBits.Asr32(j, 5)] shr (j and $1F);
|
|
|
+ secretIndexK := secretIndexK xor (secretBitK shr 1);
|
|
|
+ secretIndexK := secretIndexK shl 1;
|
|
|
+ secretIndexK := secretIndexK xor secretBitK;
|
|
|
+
|
|
|
+ secretBitL := BigL[TBits.Asr32(j, 5)] shr (j and $1F);
|
|
|
+ secretIndexL := secretIndexL xor (secretBitL shr 1);
|
|
|
+ secretIndexL := secretIndexL shl 1;
|
|
|
+ secretIndexL := secretIndexL xor secretBitL;
|
|
|
+
|
|
|
+ System.Dec(j, d);
|
|
|
+ end;
|
|
|
+
|
|
|
+ addP := lookupTableP.LookupVar(Int32(secretIndexK));
|
|
|
+ addQ := lookupTableQ.LookupVar(Int32(secretIndexL));
|
|
|
+
|
|
|
+ t := addP.Add(addQ);
|
|
|
+
|
|
|
+ R := R.TwicePlus(t);
|
|
|
+ end;
|
|
|
+
|
|
|
+ result := R.Add(infoP.Offset).Add(infoQ.Offset);
|
|
|
+end;
|
|
|
+
|
|
|
class function TECAlgorithms.ImplShamirsTrickJsf(const p: IECPoint;
|
|
|
- const k: TBigInteger; const Q: IECPoint; const l: TBigInteger): IECPoint;
|
|
|
+ const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
|
|
|
var
|
|
|
Curve: IECCurve;
|
|
|
- infinity, R: IECPoint;
|
|
|
+ Infinity, R: IECPoint;
|
|
|
PaddQ, PsubQ: IECPoint;
|
|
|
points, table: TCryptoLibGenericArray<IECPoint>;
|
|
|
jsf: TCryptoLibByteArray;
|
|
|
i, jsfi, kDigit, lDigit, index: Int32;
|
|
|
begin
|
|
|
Curve := p.Curve;
|
|
|
- infinity := Curve.infinity;
|
|
|
+ Infinity := Curve.Infinity;
|
|
|
|
|
|
// TODO conjugate co-Z addition (ZADDC) can return both of these
|
|
|
- PaddQ := p.Add(Q);
|
|
|
- PsubQ := p.Subtract(Q);
|
|
|
+ PaddQ := p.Add(q);
|
|
|
+ PsubQ := p.Subtract(q);
|
|
|
|
|
|
- points := TCryptoLibGenericArray<IECPoint>.Create(Q, PsubQ, p, PaddQ);
|
|
|
+ points := TCryptoLibGenericArray<IECPoint>.Create(q, PsubQ, p, PaddQ);
|
|
|
Curve.NormalizeAll(points);
|
|
|
|
|
|
table := TCryptoLibGenericArray<IECPoint>.Create(points[3].Negate(),
|
|
|
- points[2].Negate(), points[1].Negate(), points[0].Negate(), infinity,
|
|
|
+ points[2].Negate(), points[1].Negate(), points[0].Negate(), Infinity,
|
|
|
points[0], points[1], points[2], points[3]);
|
|
|
|
|
|
jsf := TWNafUtilities.GenerateJsf(k, l);
|
|
|
|
|
|
- R := infinity;
|
|
|
+ R := Infinity;
|
|
|
|
|
|
i := System.length(jsf);
|
|
|
System.Dec(i);
|
|
@@ -387,13 +330,12 @@ begin
|
|
|
result := R;
|
|
|
end;
|
|
|
|
|
|
-class function TECAlgorithms.ImplShamirsTrickWNaf(const p: IECPoint;
|
|
|
- const k: TBigInteger; const pointMapQ: IECPointMap; const l: TBigInteger)
|
|
|
- : IECPoint;
|
|
|
+class function TECAlgorithms.ImplShamirsTrickWNaf(const endomorphism
|
|
|
+ : IECEndomorphism; const p: IECPoint; const k, l: TBigInteger): IECPoint;
|
|
|
var
|
|
|
negK, negL: Boolean;
|
|
|
- width: Int32;
|
|
|
- Q: IECPoint;
|
|
|
+ minWidth, widthP, widthQ: Int32;
|
|
|
+ q: IECPoint;
|
|
|
infoP, infoQ: IWNafPreCompInfo;
|
|
|
preCompP, preCompQ, preCompNegP, preCompNegQ
|
|
|
: TCryptoLibGenericArray<IECPoint>;
|
|
@@ -408,12 +350,15 @@ begin
|
|
|
LK := LK.Abs();
|
|
|
LL := LL.Abs();
|
|
|
|
|
|
- width := Max(2, Min(16, TWNafUtilities.GetWindowSize(Max(LK.BitLength,
|
|
|
- LL.BitLength))));
|
|
|
+ minWidth := TWNafUtilities.GetWindowSize(Max(k.BitLength, l.BitLength), 8);
|
|
|
|
|
|
- Q := TWNafUtilities.MapPointWithPrecomp(p, width, true, pointMapQ);
|
|
|
- infoP := TWNafUtilities.GetWNafPreCompInfo(p);
|
|
|
- infoQ := TWNafUtilities.GetWNafPreCompInfo(Q);
|
|
|
+ infoP := TWNafUtilities.Precompute(p, minWidth, true);
|
|
|
+ q := TEndoUtilities.MapPoint(endomorphism, p);
|
|
|
+ infoQ := TWNafUtilities.PrecomputeWithPointMap(q, endomorphism.pointMap,
|
|
|
+ infoP, true);
|
|
|
+
|
|
|
+ widthP := Min(8, infoP.width);
|
|
|
+ widthQ := Min(8, infoQ.width);
|
|
|
|
|
|
case negK of
|
|
|
true:
|
|
@@ -443,8 +388,8 @@ begin
|
|
|
preCompNegQ := infoQ.PreCompNeg
|
|
|
end;
|
|
|
|
|
|
- wnafP := TWNafUtilities.GenerateWindowNaf(width, LK);
|
|
|
- wnafQ := TWNafUtilities.GenerateWindowNaf(width, LL);
|
|
|
+ wnafP := TWNafUtilities.GenerateWindowNaf(widthP, LK);
|
|
|
+ wnafQ := TWNafUtilities.GenerateWindowNaf(widthQ, LL);
|
|
|
|
|
|
result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
|
|
|
preCompNegQ, wnafQ);
|
|
@@ -457,29 +402,48 @@ begin
|
|
|
end;
|
|
|
|
|
|
class function TECAlgorithms.ImplShamirsTrickWNaf(const p: IECPoint;
|
|
|
- const k: TBigInteger; const Q: IECPoint; const l: TBigInteger): IECPoint;
|
|
|
+ const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
|
|
|
var
|
|
|
negK, negL: Boolean;
|
|
|
- widthP, widthQ: Int32;
|
|
|
+ minWidthP, minWidthQ, widthP, widthQ, combSize: Int32;
|
|
|
infoP, infoQ: IWNafPreCompInfo;
|
|
|
preCompP, preCompQ, preCompNegP, preCompNegQ
|
|
|
: TCryptoLibGenericArray<IECPoint>;
|
|
|
wnafP, wnafQ: TCryptoLibByteArray;
|
|
|
- LK, LL: TBigInteger;
|
|
|
+ kAbs, lAbs: TBigInteger;
|
|
|
+ c: IECCurve;
|
|
|
begin
|
|
|
- LK := k;
|
|
|
- LL := l;
|
|
|
- negK := LK.SignValue < 0;
|
|
|
- negL := LL.SignValue < 0;
|
|
|
|
|
|
- LK := LK.Abs();
|
|
|
- LL := LL.Abs();
|
|
|
+ negK := k.SignValue < 0;
|
|
|
+ negL := l.SignValue < 0;
|
|
|
+
|
|
|
+ kAbs := k.Abs();
|
|
|
+ lAbs := l.Abs();
|
|
|
|
|
|
- widthP := Max(2, Min(16, TWNafUtilities.GetWindowSize(LK.BitLength)));
|
|
|
- widthQ := Max(2, Min(16, TWNafUtilities.GetWindowSize(LL.BitLength)));
|
|
|
+ minWidthP := TWNafUtilities.GetWindowSize(kAbs.BitLength, 8);
|
|
|
+ minWidthQ := TWNafUtilities.GetWindowSize(lAbs.BitLength, 8);
|
|
|
|
|
|
- infoP := TWNafUtilities.Precompute(p, widthP, true);
|
|
|
- infoQ := TWNafUtilities.Precompute(Q, widthQ, true);
|
|
|
+ infoP := TWNafUtilities.Precompute(p, minWidthP, true);
|
|
|
+ infoQ := TWNafUtilities.Precompute(q, minWidthQ, true);
|
|
|
+
|
|
|
+ // When P, Q are 'promoted' (i.e. reused several times), switch to fixed-point algorithm
|
|
|
+
|
|
|
+ c := p.Curve;
|
|
|
+ combSize := TFixedPointUtilities.GetCombSize(c);
|
|
|
+ if ((not negK) and (not negL) and (k.BitLength <= combSize) and
|
|
|
+ (l.BitLength <= combSize) and (infoP.IsPromoted) and (infoQ.IsPromoted))
|
|
|
+ then
|
|
|
+ begin
|
|
|
+ result := ImplShamirsTrickFixedPoint(p, k, q, l);
|
|
|
+ infoP.PreComp := Nil; // Review
|
|
|
+ infoP.PreCompNeg := Nil; // Review
|
|
|
+ infoQ.PreComp := Nil; // Review
|
|
|
+ infoQ.PreCompNeg := Nil; // Review
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+
|
|
|
+ widthP := Min(8, infoP.width);
|
|
|
+ widthQ := Min(8, infoQ.width);
|
|
|
|
|
|
if negK then
|
|
|
begin
|
|
@@ -517,8 +481,8 @@ begin
|
|
|
preCompNegQ := infoQ.PreCompNeg
|
|
|
end;
|
|
|
|
|
|
- wnafP := TWNafUtilities.GenerateWindowNaf(widthP, LK);
|
|
|
- wnafQ := TWNafUtilities.GenerateWindowNaf(widthQ, LL);
|
|
|
+ wnafP := TWNafUtilities.GenerateWindowNaf(widthP, kAbs);
|
|
|
+ wnafQ := TWNafUtilities.GenerateWindowNaf(widthQ, lAbs);
|
|
|
|
|
|
result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
|
|
|
preCompNegQ, wnafQ);
|
|
@@ -536,15 +500,15 @@ class function TECAlgorithms.ImplShamirsTrickWNaf(const preCompP,
|
|
|
var
|
|
|
len, zeroes, i, wiP, wiQ, nP, nQ: Int32;
|
|
|
Curve: IECCurve;
|
|
|
- infinity, R, point: IECPoint;
|
|
|
+ Infinity, R, point: IECPoint;
|
|
|
tableP, tableQ: TCryptoLibGenericArray<IECPoint>;
|
|
|
begin
|
|
|
- len := Math.Max(System.length(wnafP), System.length(wnafQ));
|
|
|
+ len := Max(System.length(wnafP), System.length(wnafQ));
|
|
|
|
|
|
Curve := preCompP[0].Curve;
|
|
|
- infinity := Curve.infinity;
|
|
|
+ Infinity := Curve.Infinity;
|
|
|
|
|
|
- R := infinity;
|
|
|
+ R := Infinity;
|
|
|
zeroes := 0;
|
|
|
|
|
|
i := len - 1;
|
|
@@ -576,7 +540,7 @@ begin
|
|
|
continue;
|
|
|
end;
|
|
|
|
|
|
- point := infinity;
|
|
|
+ point := Infinity;
|
|
|
if (wiP <> 0) then
|
|
|
begin
|
|
|
nP := System.Abs(wiP);
|
|
@@ -626,17 +590,19 @@ begin
|
|
|
result := R;
|
|
|
end;
|
|
|
|
|
|
-class function TECAlgorithms.ImplSumOfMultiplies
|
|
|
- (const ps: TCryptoLibGenericArray<IECPoint>; const pointMap: IECPointMap;
|
|
|
+class function TECAlgorithms.ImplSumOfMultiplies(const endomorphism
|
|
|
+ : IECEndomorphism; const ps: TCryptoLibGenericArray<IECPoint>;
|
|
|
const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
|
|
|
var
|
|
|
halfCount, fullCount: Int32;
|
|
|
negs: TCryptoLibBooleanArray;
|
|
|
infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
|
|
|
+ infoP, infoQ: IWNafPreCompInfo;
|
|
|
wnafs: TCryptoLibMatrixByteArray;
|
|
|
- i, j0, j1, width: Int32;
|
|
|
+ i, j0, j1, minWidth, widthP, widthQ: Int32;
|
|
|
kj0, kj1: TBigInteger;
|
|
|
- p, Q: IECPoint;
|
|
|
+ p, q: IECPoint;
|
|
|
+ pointMap: IECPointMap;
|
|
|
begin
|
|
|
halfCount := System.length(ps);
|
|
|
fullCount := halfCount shl 1;
|
|
@@ -644,6 +610,8 @@ begin
|
|
|
System.SetLength(infos, fullCount);
|
|
|
System.SetLength(wnafs, fullCount);
|
|
|
|
|
|
+ pointMap := endomorphism.pointMap;
|
|
|
+
|
|
|
for i := 0 to System.Pred(halfCount) do
|
|
|
begin
|
|
|
j0 := i shl 1;
|
|
@@ -656,15 +624,21 @@ begin
|
|
|
negs[j1] := kj1.SignValue < 0;
|
|
|
kj1 := kj1.Abs();
|
|
|
|
|
|
- width := Max(2, Min(16, TWNafUtilities.GetWindowSize(Max(kj0.BitLength,
|
|
|
- kj1.BitLength))));
|
|
|
+ minWidth := TWNafUtilities.GetWindowSize
|
|
|
+ (Max(kj0.BitLength, kj1.BitLength), 8);
|
|
|
|
|
|
p := ps[i];
|
|
|
- Q := TWNafUtilities.MapPointWithPrecomp(p, width, true, pointMap);
|
|
|
- infos[j0] := TWNafUtilities.GetWNafPreCompInfo(p);
|
|
|
- infos[j1] := TWNafUtilities.GetWNafPreCompInfo(Q);
|
|
|
- wnafs[j0] := TWNafUtilities.GenerateWindowNaf(width, kj0);
|
|
|
- wnafs[j1] := TWNafUtilities.GenerateWindowNaf(width, kj1);
|
|
|
+ infoP := TWNafUtilities.Precompute(p, minWidth, true);
|
|
|
+ q := TEndoUtilities.MapPoint(endomorphism, p);
|
|
|
+ infoQ := TWNafUtilities.PrecomputeWithPointMap(q, pointMap, infoP, true);
|
|
|
+
|
|
|
+ widthP := Min(8, infoP.width);
|
|
|
+ widthQ := Min(8, infoQ.width);
|
|
|
+
|
|
|
+ infos[j0] := infoP;
|
|
|
+ infos[j1] := infoQ;
|
|
|
+ wnafs[j0] := TWNafUtilities.GenerateWindowNaf(widthP, kj0);
|
|
|
+ wnafs[j1] := TWNafUtilities.GenerateWindowNaf(widthQ, kj1);
|
|
|
end;
|
|
|
|
|
|
result := ImplSumOfMultiplies(negs, infos, wnafs);
|
|
@@ -681,8 +655,9 @@ class function TECAlgorithms.ImplSumOfMultiplies
|
|
|
(const ps: TCryptoLibGenericArray<IECPoint>;
|
|
|
const ks: TCryptoLibGenericArray<TBigInteger>): IECPoint;
|
|
|
var
|
|
|
- count, i, width: Int32;
|
|
|
+ count, i, width, minWidth: Int32;
|
|
|
negs: TCryptoLibBooleanArray;
|
|
|
+ info: IWNafPreCompInfo;
|
|
|
infos: TCryptoLibGenericArray<IWNafPreCompInfo>;
|
|
|
wnafs: TCryptoLibMatrixByteArray;
|
|
|
ki: TBigInteger;
|
|
@@ -700,8 +675,11 @@ begin
|
|
|
negs[i] := ki.SignValue < 0;
|
|
|
ki := ki.Abs();
|
|
|
|
|
|
- width := Max(2, Min(16, TWNafUtilities.GetWindowSize(ki.BitLength)));
|
|
|
- infos[i] := TWNafUtilities.Precompute(ps[i], width, true);
|
|
|
+ minWidth := TWNafUtilities.GetWindowSize(ki.BitLength, 8);
|
|
|
+ info := TWNafUtilities.Precompute(ps[i], minWidth, true);
|
|
|
+ width := Min(8, info.width);
|
|
|
+
|
|
|
+ infos[i] := info;
|
|
|
wnafs[i] := TWNafUtilities.GenerateWindowNaf(width, ki);
|
|
|
end;
|
|
|
|
|
@@ -721,9 +699,9 @@ class function TECAlgorithms.ImplSumOfMultiplies
|
|
|
const wnafs: TCryptoLibMatrixByteArray): IECPoint;
|
|
|
var
|
|
|
len, count, zeroes: Int32;
|
|
|
- i, J, wi, n: Int32;
|
|
|
+ i, j, wi, n: Int32;
|
|
|
Curve: IECCurve;
|
|
|
- infinity, R, point: IECPoint;
|
|
|
+ Infinity, R, point: IECPoint;
|
|
|
wnaf: TCryptoLibByteArray;
|
|
|
info: IWNafPreCompInfo;
|
|
|
table: TCryptoLibGenericArray<IECPoint>;
|
|
@@ -737,19 +715,19 @@ begin
|
|
|
end;
|
|
|
|
|
|
Curve := infos[0].PreComp[0].Curve;
|
|
|
- infinity := Curve.infinity;
|
|
|
+ Infinity := Curve.Infinity;
|
|
|
|
|
|
- R := infinity;
|
|
|
+ R := Infinity;
|
|
|
zeroes := 0;
|
|
|
|
|
|
i := len - 1;
|
|
|
while (i >= 0) do
|
|
|
begin
|
|
|
- point := infinity;
|
|
|
+ point := Infinity;
|
|
|
|
|
|
- for J := 0 to System.Pred(count) do
|
|
|
+ for j := 0 to System.Pred(count) do
|
|
|
begin
|
|
|
- wnaf := wnafs[J];
|
|
|
+ wnaf := wnafs[j];
|
|
|
if i < System.length(wnaf) then
|
|
|
begin
|
|
|
wi := Int32(ShortInt(wnaf[i]));
|
|
@@ -762,8 +740,8 @@ begin
|
|
|
if (wi <> 0) then
|
|
|
begin
|
|
|
n := System.Abs(wi);
|
|
|
- info := infos[J];
|
|
|
- if (wi < 0 = negs[J]) then
|
|
|
+ info := infos[j];
|
|
|
+ if (wi < 0 = negs[j]) then
|
|
|
begin
|
|
|
table := info.PreComp;
|
|
|
end
|
|
@@ -776,7 +754,7 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
- if (point = infinity) then
|
|
|
+ if (point = Infinity) then
|
|
|
begin
|
|
|
System.Inc(zeroes);
|
|
|
System.Dec(i);
|
|
@@ -809,11 +787,10 @@ class function TECAlgorithms.ImplSumOfMultipliesGlv
|
|
|
const glvEndomorphism: IGlvEndomorphism): IECPoint;
|
|
|
var
|
|
|
n: TBigInteger;
|
|
|
- len, i, J: Int32;
|
|
|
+ len, i, j: Int32;
|
|
|
&abs, ab: TCryptoLibGenericArray<TBigInteger>;
|
|
|
- pointMap: IECPointMap;
|
|
|
pqs: TCryptoLibGenericArray<IECPoint>;
|
|
|
- p, Q: IECPoint;
|
|
|
+ p, q: IECPoint;
|
|
|
begin
|
|
|
n := ps[0].Curve.Order;
|
|
|
|
|
@@ -822,40 +799,39 @@ begin
|
|
|
System.SetLength(Abs, len shl 1);
|
|
|
|
|
|
i := 0;
|
|
|
- J := 0;
|
|
|
+ j := 0;
|
|
|
|
|
|
while (i < len) do
|
|
|
begin
|
|
|
ab := glvEndomorphism.DecomposeScalar(ks[i].&Mod(n));
|
|
|
|
|
|
- Abs[J] := ab[0];
|
|
|
- System.Inc(J);
|
|
|
- Abs[J] := ab[1];
|
|
|
- System.Inc(J);
|
|
|
+ Abs[j] := ab[0];
|
|
|
+ System.Inc(j);
|
|
|
+ Abs[j] := ab[1];
|
|
|
+ System.Inc(j);
|
|
|
System.Inc(i);
|
|
|
end;
|
|
|
|
|
|
- pointMap := glvEndomorphism.pointMap;
|
|
|
if (glvEndomorphism.HasEfficientPointMap) then
|
|
|
begin
|
|
|
- result := TECAlgorithms.ImplSumOfMultiplies(ps, pointMap, Abs);
|
|
|
+ result := TECAlgorithms.ImplSumOfMultiplies(glvEndomorphism, ps, Abs);
|
|
|
Exit;
|
|
|
end;
|
|
|
|
|
|
System.SetLength(pqs, len shl 1);
|
|
|
|
|
|
i := 0;
|
|
|
- J := 0;
|
|
|
+ j := 0;
|
|
|
|
|
|
while (i < len) do
|
|
|
begin
|
|
|
p := ps[i];
|
|
|
- Q := pointMap.Map(p);
|
|
|
+ q := TEndoUtilities.MapPoint(glvEndomorphism, p);
|
|
|
|
|
|
- pqs[J] := p;
|
|
|
- System.Inc(J);
|
|
|
- pqs[J] := Q;
|
|
|
- System.Inc(J);
|
|
|
+ pqs[j] := p;
|
|
|
+ System.Inc(j);
|
|
|
+ pqs[j] := q;
|
|
|
+ System.Inc(j);
|
|
|
System.Inc(i);
|
|
|
end;
|
|
|
|
|
@@ -903,7 +879,7 @@ class procedure TECAlgorithms.MontgomeryTrick
|
|
|
const scale: IECFieldElement);
|
|
|
var
|
|
|
c: TCryptoLibGenericArray<IECFieldElement>;
|
|
|
- i, J: Int32;
|
|
|
+ i, j: Int32;
|
|
|
u, tmp: IECFieldElement;
|
|
|
begin
|
|
|
// /*
|
|
@@ -935,10 +911,10 @@ begin
|
|
|
|
|
|
while (i > 0) do
|
|
|
begin
|
|
|
- J := off + i;
|
|
|
+ j := off + i;
|
|
|
System.Dec(i);
|
|
|
- tmp := zs[J];
|
|
|
- zs[J] := c[i].Multiply(u);
|
|
|
+ tmp := zs[j];
|
|
|
+ zs[j] := c[i].Multiply(u);
|
|
|
u := u.Multiply(tmp);
|
|
|
end;
|
|
|
|
|
@@ -955,18 +931,18 @@ class function TECAlgorithms.ReferenceMultiply(const p: IECPoint;
|
|
|
const k: TBigInteger): IECPoint;
|
|
|
var
|
|
|
x: TBigInteger;
|
|
|
- Q, LP: IECPoint;
|
|
|
+ q, LP: IECPoint;
|
|
|
t, i: Int32;
|
|
|
begin
|
|
|
LP := p;
|
|
|
x := k.Abs();
|
|
|
- Q := LP.Curve.infinity;
|
|
|
+ q := LP.Curve.Infinity;
|
|
|
t := x.BitLength;
|
|
|
if (t > 0) then
|
|
|
begin
|
|
|
if (x.TestBit(0)) then
|
|
|
begin
|
|
|
- Q := LP;
|
|
|
+ q := LP;
|
|
|
end;
|
|
|
i := 1;
|
|
|
while (i < t) do
|
|
@@ -974,7 +950,7 @@ begin
|
|
|
LP := LP.Twice();
|
|
|
if (x.TestBit(i)) then
|
|
|
begin
|
|
|
- Q := Q.Add(LP);
|
|
|
+ q := q.Add(LP);
|
|
|
end;
|
|
|
System.Inc(i);
|
|
|
end;
|
|
@@ -983,23 +959,23 @@ begin
|
|
|
|
|
|
if k.SignValue < 0 then
|
|
|
begin
|
|
|
- result := Q.Negate();
|
|
|
+ result := q.Negate();
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
- result := Q;
|
|
|
+ result := q;
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
class function TECAlgorithms.ShamirsTrick(const p: IECPoint;
|
|
|
- const k: TBigInteger; const Q: IECPoint; const l: TBigInteger): IECPoint;
|
|
|
+ const k: TBigInteger; const q: IECPoint; const l: TBigInteger): IECPoint;
|
|
|
var
|
|
|
cp: IECCurve;
|
|
|
LQ: IECPoint;
|
|
|
begin
|
|
|
cp := p.Curve;
|
|
|
- LQ := Q;
|
|
|
+ LQ := q;
|
|
|
LQ := ImportPoint(cp, LQ);
|
|
|
|
|
|
result := ImplCheckResult(ImplShamirsTrickJsf(p, k, LQ, l));
|
|
@@ -1060,7 +1036,7 @@ begin
|
|
|
end;
|
|
|
|
|
|
class function TECAlgorithms.SumOfTwoMultiplies(const p: IECPoint;
|
|
|
- const a: TBigInteger; const Q: IECPoint; const b: TBigInteger): IECPoint;
|
|
|
+ const a: TBigInteger; const q: IECPoint; const b: TBigInteger): IECPoint;
|
|
|
var
|
|
|
cp: IECCurve;
|
|
|
f2mCurve: IAbstractF2mCurve;
|
|
@@ -1068,7 +1044,7 @@ var
|
|
|
LQ: IECPoint;
|
|
|
begin
|
|
|
cp := p.Curve;
|
|
|
- LQ := Q;
|
|
|
+ LQ := q;
|
|
|
LQ := ImportPoint(cp, LQ);
|
|
|
|
|
|
// Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
|
|
@@ -1090,711 +1066,4 @@ begin
|
|
|
result := ImplCheckResult(ImplShamirsTrickWNaf(p, a, LQ, b));
|
|
|
end;
|
|
|
|
|
|
-{ TWNafUtilities }
|
|
|
-
|
|
|
-class function TWNafUtilities.ResizeTable
|
|
|
- (const a: TCryptoLibGenericArray<IECPoint>; length: Int32)
|
|
|
- : TCryptoLibGenericArray<IECPoint>;
|
|
|
-begin
|
|
|
- result := System.Copy(a);
|
|
|
- System.SetLength(result, length);
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.Trim(const a: TCryptoLibInt32Array; length: Int32)
|
|
|
- : TCryptoLibInt32Array;
|
|
|
-begin
|
|
|
- result := System.Copy(a, 0, length);
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.Trim(const a: TCryptoLibByteArray; length: Int32)
|
|
|
- : TCryptoLibByteArray;
|
|
|
-begin
|
|
|
- result := System.Copy(a, 0, length);
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.CheckTable(const table
|
|
|
- : TCryptoLibGenericArray<IECPoint>; reqLen: Int32): Boolean;
|
|
|
-begin
|
|
|
- result := (table <> Nil) and (System.length(table) >= reqLen);
|
|
|
-end;
|
|
|
-
|
|
|
-class procedure TWNafUtilities.Boot;
|
|
|
-begin
|
|
|
- FEMPTY_BYTES := Nil;
|
|
|
- FEMPTY_INTS := Nil;
|
|
|
-end;
|
|
|
-
|
|
|
-class constructor TWNafUtilities.CreateWNafUtilities;
|
|
|
-begin
|
|
|
- TWNafUtilities.Boot;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.CheckExisting(const existingWNaf
|
|
|
- : IWNafPreCompInfo; reqPreCompLen: Int32; includeNegated: Boolean): Boolean;
|
|
|
-begin
|
|
|
- result := (existingWNaf <> Nil) and CheckTable(existingWNaf.PreComp,
|
|
|
- reqPreCompLen) and ((not includeNegated) or
|
|
|
- CheckTable(existingWNaf.PreCompNeg, reqPreCompLen));
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GenerateCompactNaf(const k: TBigInteger)
|
|
|
- : TCryptoLibInt32Array;
|
|
|
-var
|
|
|
- _3k, diff: TBigInteger;
|
|
|
- bits, highBit, &length, zeroes, i, digit: Int32;
|
|
|
- naf: TCryptoLibInt32Array;
|
|
|
-begin
|
|
|
- if ((TBits.Asr32(k.BitLength, 16)) <> 0) then
|
|
|
- begin
|
|
|
- raise EArgumentCryptoLibException.CreateRes(@SInvalidBitLength);
|
|
|
- end;
|
|
|
- if (k.SignValue = 0) then
|
|
|
- begin
|
|
|
- result := FEMPTY_INTS;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- _3k := k.ShiftLeft(1).Add(k);
|
|
|
-
|
|
|
- bits := _3k.BitLength;
|
|
|
- System.SetLength(naf, TBits.Asr32(bits, 1));
|
|
|
-
|
|
|
- diff := _3k.&Xor(k);
|
|
|
-
|
|
|
- highBit := bits - 1;
|
|
|
- &length := 0;
|
|
|
- zeroes := 0;
|
|
|
-
|
|
|
- i := 1;
|
|
|
-
|
|
|
- while (i < highBit) do
|
|
|
- begin
|
|
|
- if (not diff.TestBit(i)) then
|
|
|
- begin
|
|
|
- System.Inc(zeroes);
|
|
|
- System.Inc(i);
|
|
|
- continue;
|
|
|
- end;
|
|
|
-
|
|
|
- if k.TestBit(i) then
|
|
|
- begin
|
|
|
- digit := -1;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- digit := 1;
|
|
|
- end;
|
|
|
-
|
|
|
- naf[length] := (digit shl 16) or zeroes;
|
|
|
- System.Inc(length);
|
|
|
- zeroes := 1;
|
|
|
-
|
|
|
- System.Inc(i, 2);
|
|
|
-
|
|
|
- end;
|
|
|
-
|
|
|
- naf[length] := (1 shl 16) or zeroes;
|
|
|
- System.Inc(length);
|
|
|
-
|
|
|
- if (System.length(naf) > length) then
|
|
|
- begin
|
|
|
- naf := Trim(naf, length);
|
|
|
- end;
|
|
|
-
|
|
|
- result := naf;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GenerateCompactWindowNaf(width: Int32;
|
|
|
- const k: TBigInteger): TCryptoLibInt32Array;
|
|
|
-var
|
|
|
- wnaf: TCryptoLibInt32Array;
|
|
|
- pow2, mask, sign, &length, &pos, digit, zeroes: Int32;
|
|
|
- carry: Boolean;
|
|
|
- LK: TBigInteger;
|
|
|
-begin
|
|
|
- LK := k;
|
|
|
- if (width = 2) then
|
|
|
- begin
|
|
|
- result := GenerateCompactNaf(LK);
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- if ((width < 2) or (width > 16)) then
|
|
|
- begin
|
|
|
- raise EArgumentCryptoLibException.CreateRes(@SInvalidRange);
|
|
|
- end;
|
|
|
- if ((TBits.Asr32(LK.BitLength, 16)) <> 0) then
|
|
|
- begin
|
|
|
- raise EArgumentCryptoLibException.CreateRes(@SInvalidBitLength);
|
|
|
- end;
|
|
|
- if (LK.SignValue = 0) then
|
|
|
- begin
|
|
|
- result := FEMPTY_INTS;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- System.SetLength(wnaf, (LK.BitLength div width) + 1);
|
|
|
-
|
|
|
- // 2^width and a mask and sign bit set accordingly
|
|
|
- pow2 := 1 shl width;
|
|
|
- mask := pow2 - 1;
|
|
|
- sign := TBits.Asr32(pow2, 1);
|
|
|
-
|
|
|
- carry := false;
|
|
|
- length := 0;
|
|
|
- pos := 0;
|
|
|
-
|
|
|
- while (pos <= LK.BitLength) do
|
|
|
- begin
|
|
|
- if (LK.TestBit(pos) = carry) then
|
|
|
- begin
|
|
|
- System.Inc(pos);
|
|
|
- continue;
|
|
|
- end;
|
|
|
-
|
|
|
- LK := LK.ShiftRight(pos);
|
|
|
-
|
|
|
- digit := LK.Int32Value and mask;
|
|
|
- if (carry) then
|
|
|
- begin
|
|
|
- System.Inc(digit);
|
|
|
- end;
|
|
|
-
|
|
|
- carry := (digit and sign) <> 0;
|
|
|
- if (carry) then
|
|
|
- begin
|
|
|
- digit := digit - pow2;
|
|
|
- end;
|
|
|
-
|
|
|
- if length > 0 then
|
|
|
- begin
|
|
|
- zeroes := pos - 1;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- zeroes := pos;
|
|
|
- end;
|
|
|
-
|
|
|
- wnaf[length] := (digit shl 16) or zeroes;
|
|
|
- System.Inc(length);
|
|
|
- pos := width;
|
|
|
- end;
|
|
|
-
|
|
|
- // Reduce the WNAF array to its actual length
|
|
|
- if (System.length(wnaf) > length) then
|
|
|
- begin
|
|
|
- wnaf := Trim(wnaf, length);
|
|
|
- end;
|
|
|
-
|
|
|
- result := wnaf;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GenerateJsf(const g, h: TBigInteger)
|
|
|
- : TCryptoLibByteArray;
|
|
|
-var
|
|
|
- digits, J, d0, d1, offset, n0, n1, u0, u1: Int32;
|
|
|
- jsf: TCryptoLibByteArray;
|
|
|
- k0, k1: TBigInteger;
|
|
|
-begin
|
|
|
- digits := Max(g.BitLength, h.BitLength) + 1;
|
|
|
-
|
|
|
- System.SetLength(jsf, digits);
|
|
|
-
|
|
|
- k0 := g;
|
|
|
- k1 := h;
|
|
|
- J := 0;
|
|
|
- d0 := 0;
|
|
|
- d1 := 0;
|
|
|
-
|
|
|
- offset := 0;
|
|
|
-
|
|
|
- while (((d0 or d1) <> 0) or (k0.BitLength > offset) or
|
|
|
- (k1.BitLength > offset)) do
|
|
|
- begin
|
|
|
- n0 := (Int32(UInt32(k0.Int32Value) shr offset) + d0) and 7;
|
|
|
- n1 := (Int32(UInt32(k1.Int32Value) shr offset) + d1) and 7;
|
|
|
-
|
|
|
- u0 := n0 and 1;
|
|
|
- if (u0 <> 0) then
|
|
|
- begin
|
|
|
- u0 := u0 - (n0 and 2);
|
|
|
- if (((n0 + u0) = 4) and ((n1 and 3) = 2)) then
|
|
|
- begin
|
|
|
- u0 := -u0;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- u1 := n1 and 1;
|
|
|
- if (u1 <> 0) then
|
|
|
- begin
|
|
|
- u1 := u1 - (n1 and 2);
|
|
|
- if (((n1 + u1) = 4) and ((n0 and 3) = 2)) then
|
|
|
- begin
|
|
|
- u1 := -u1;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- if ((d0 shl 1) = (1 + u0)) then
|
|
|
- begin
|
|
|
- d0 := d0 xor 1;
|
|
|
- end;
|
|
|
- if ((d1 shl 1) = (1 + u1)) then
|
|
|
- begin
|
|
|
- d1 := d1 xor 1;
|
|
|
- end;
|
|
|
-
|
|
|
- System.Inc(offset);
|
|
|
- if (offset = 30) then
|
|
|
- begin
|
|
|
- offset := 0;
|
|
|
- k0 := k0.ShiftRight(30);
|
|
|
- k1 := k1.ShiftRight(30);
|
|
|
- end;
|
|
|
-
|
|
|
- jsf[J] := Byte((u0 shl 4) or (u1 and $F));
|
|
|
- System.Inc(J);
|
|
|
- end;
|
|
|
-
|
|
|
- // Reduce the JSF array to its actual length
|
|
|
- if (System.length(jsf) > J) then
|
|
|
- begin
|
|
|
- jsf := Trim(jsf, J);
|
|
|
- end;
|
|
|
-
|
|
|
- result := jsf;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GenerateNaf(const k: TBigInteger)
|
|
|
- : TCryptoLibByteArray;
|
|
|
-var
|
|
|
- _3k, diff: TBigInteger;
|
|
|
- digits, i: Int32;
|
|
|
- naf: TCryptoLibByteArray;
|
|
|
-begin
|
|
|
- if (k.SignValue = 0) then
|
|
|
- begin
|
|
|
- result := FEMPTY_BYTES;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- _3k := k.ShiftLeft(1).Add(k);
|
|
|
-
|
|
|
- digits := _3k.BitLength - 1;
|
|
|
- System.SetLength(naf, digits);
|
|
|
-
|
|
|
- diff := _3k.&Xor(k);
|
|
|
-
|
|
|
- i := 1;
|
|
|
-
|
|
|
- while i < digits do
|
|
|
- begin
|
|
|
- if (diff.TestBit(i)) then
|
|
|
- begin
|
|
|
- if k.TestBit(i) then
|
|
|
- begin
|
|
|
- naf[i - 1] := Byte(-1);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- naf[i - 1] := Byte(1);
|
|
|
- end;
|
|
|
-
|
|
|
- System.Inc(i);
|
|
|
- end;
|
|
|
- System.Inc(i);
|
|
|
- end;
|
|
|
-
|
|
|
- naf[digits - 1] := 1;
|
|
|
-
|
|
|
- result := naf;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GenerateWindowNaf(width: Int32;
|
|
|
- const k: TBigInteger): TCryptoLibByteArray;
|
|
|
-var
|
|
|
- wnaf: TCryptoLibByteArray;
|
|
|
- pow2, mask, sign, &length, &pos, digit: Int32;
|
|
|
- carry: Boolean;
|
|
|
- LK: TBigInteger;
|
|
|
-begin
|
|
|
- LK := k;
|
|
|
- if (width = 2) then
|
|
|
- begin
|
|
|
- result := GenerateNaf(LK);
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- if ((width < 2) or (width > 8)) then
|
|
|
- begin
|
|
|
- raise EArgumentCryptoLibException.CreateRes(@SInvalidRange2);
|
|
|
- end;
|
|
|
- if (LK.SignValue = 0) then
|
|
|
- begin
|
|
|
- result := FEMPTY_BYTES;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- System.SetLength(wnaf, LK.BitLength + 1);
|
|
|
-
|
|
|
- // 2^width and a mask and sign bit set accordingly
|
|
|
- pow2 := 1 shl width;
|
|
|
- mask := pow2 - 1;
|
|
|
- sign := TBits.Asr32(pow2, 1);
|
|
|
-
|
|
|
- carry := false;
|
|
|
- length := 0;
|
|
|
- pos := 0;
|
|
|
-
|
|
|
- while (pos <= LK.BitLength) do
|
|
|
- begin
|
|
|
- if (LK.TestBit(pos) = carry) then
|
|
|
- begin
|
|
|
- System.Inc(pos);
|
|
|
- continue;
|
|
|
- end;
|
|
|
-
|
|
|
- LK := LK.ShiftRight(pos);
|
|
|
-
|
|
|
- digit := LK.Int32Value and mask;
|
|
|
- if (carry) then
|
|
|
- begin
|
|
|
- System.Inc(digit);
|
|
|
- end;
|
|
|
-
|
|
|
- carry := (digit and sign) <> 0;
|
|
|
- if (carry) then
|
|
|
- begin
|
|
|
- digit := digit - pow2;
|
|
|
- end;
|
|
|
-
|
|
|
- if length > 0 then
|
|
|
- begin
|
|
|
- length := length + (pos - 1);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- length := length + (pos);
|
|
|
- end;
|
|
|
-
|
|
|
- wnaf[length] := Byte(digit);
|
|
|
- System.Inc(length);
|
|
|
- pos := width;
|
|
|
- end;
|
|
|
-
|
|
|
- // Reduce the WNAF array to its actual length
|
|
|
- if (System.length(wnaf) > length) then
|
|
|
- begin
|
|
|
- wnaf := Trim(wnaf, length);
|
|
|
- end;
|
|
|
-
|
|
|
- result := wnaf;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GetNafWeight(const k: TBigInteger): Int32;
|
|
|
-var
|
|
|
- _3k, diff: TBigInteger;
|
|
|
-begin
|
|
|
- if (k.SignValue = 0) then
|
|
|
- begin
|
|
|
- result := 0;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- _3k := k.ShiftLeft(1).Add(k);
|
|
|
- diff := _3k.&Xor(k);
|
|
|
-
|
|
|
- result := diff.BitCount;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GetWindowSize(bits: Int32;
|
|
|
- const windowSizeCutoffs: array of Int32): Int32;
|
|
|
-var
|
|
|
- w: Int32;
|
|
|
-begin
|
|
|
- w := 0;
|
|
|
- while (w < System.length(windowSizeCutoffs)) do
|
|
|
- begin
|
|
|
- if (bits < windowSizeCutoffs[w]) then
|
|
|
- begin
|
|
|
- break;
|
|
|
- end;
|
|
|
- System.Inc(w);
|
|
|
- end;
|
|
|
-
|
|
|
- result := w + 2;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GetWindowSize(bits: Int32): Int32;
|
|
|
-begin
|
|
|
- result := GetWindowSize(bits, FDEFAULT_WINDOW_SIZE_CUTOFFS);
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GetWNafPreCompInfo(const preCompInfo
|
|
|
- : IPreCompInfo): IWNafPreCompInfo;
|
|
|
-begin
|
|
|
- result := preCompInfo as IWNafPreCompInfo;
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.GetWNafPreCompInfo(const p: IECPoint)
|
|
|
- : IWNafPreCompInfo;
|
|
|
-var
|
|
|
- preCompInfo: IPreCompInfo;
|
|
|
-begin
|
|
|
- preCompInfo := p.Curve.GetPreCompInfo(p, PRECOMP_NAME);
|
|
|
- result := GetWNafPreCompInfo(preCompInfo);
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.MapPointWithPrecomp(const p: IECPoint;
|
|
|
- width: Int32; includeNegated: Boolean; const pointMap: IECPointMap): IECPoint;
|
|
|
-var
|
|
|
- c: IECCurve;
|
|
|
- wnafPreCompP: IWNafPreCompInfo;
|
|
|
- Q: IECPoint;
|
|
|
-begin
|
|
|
- c := p.Curve;
|
|
|
-
|
|
|
- wnafPreCompP := Precompute(p, width, includeNegated);
|
|
|
-
|
|
|
- Q := pointMap.Map(p);
|
|
|
-
|
|
|
- c.Precompute(Q, PRECOMP_NAME, TMapPointCallback.Create(wnafPreCompP,
|
|
|
- includeNegated, pointMap) as IMapPointCallback);
|
|
|
-
|
|
|
- result := Q;
|
|
|
-
|
|
|
-end;
|
|
|
-
|
|
|
-class function TWNafUtilities.Precompute(const p: IECPoint; width: Int32;
|
|
|
- includeNegated: Boolean): IWNafPreCompInfo;
|
|
|
-begin
|
|
|
- result := p.Curve.Precompute(p, PRECOMP_NAME, TWNafCallback.Create(p, width,
|
|
|
- includeNegated) as IWNafCallback) as IWNafPreCompInfo;
|
|
|
-end;
|
|
|
-
|
|
|
-{ TWNafUtilities.TMapPointCallback }
|
|
|
-
|
|
|
-constructor TWNafUtilities.TMapPointCallback.Create(const wnafPreCompP
|
|
|
- : IWNafPreCompInfo; includeNegated: Boolean; const pointMap: IECPointMap);
|
|
|
-begin
|
|
|
- Inherited Create();
|
|
|
- Fm_wnafPreCompP := wnafPreCompP;
|
|
|
- Fm_includeNegated := includeNegated;
|
|
|
- Fm_pointMap := pointMap;
|
|
|
-end;
|
|
|
-
|
|
|
-function TWNafUtilities.TMapPointCallback.Precompute(const existing
|
|
|
- : IPreCompInfo): IPreCompInfo;
|
|
|
-var
|
|
|
- tempResult: IWNafPreCompInfo;
|
|
|
- twiceP, twiceQ: IECPoint;
|
|
|
- preCompP, preCompQ, preCompNegQ: TCryptoLibGenericArray<IECPoint>;
|
|
|
- i: Int32;
|
|
|
-begin
|
|
|
- tempResult := TWNafPreCompInfo.Create();
|
|
|
-
|
|
|
- twiceP := Fm_wnafPreCompP.Twice;
|
|
|
- if (twiceP <> Nil) then
|
|
|
- begin
|
|
|
- twiceQ := Fm_pointMap.Map(twiceP);
|
|
|
- tempResult.Twice := twiceQ;
|
|
|
- end;
|
|
|
-
|
|
|
- preCompP := Fm_wnafPreCompP.PreComp;
|
|
|
-
|
|
|
- System.SetLength(preCompQ, System.length(preCompP));
|
|
|
- for i := 0 to System.Pred(System.length(preCompP)) do
|
|
|
- begin
|
|
|
- preCompQ[i] := Fm_pointMap.Map(preCompP[i]);
|
|
|
- end;
|
|
|
-
|
|
|
- tempResult.PreComp := preCompQ;
|
|
|
-
|
|
|
- if (Fm_includeNegated) then
|
|
|
- begin
|
|
|
-
|
|
|
- System.SetLength(preCompNegQ, System.length(preCompQ));
|
|
|
-
|
|
|
- for i := 0 to System.Pred(System.length(preCompNegQ)) do
|
|
|
- begin
|
|
|
- preCompNegQ[i] := preCompQ[i].Negate();
|
|
|
- end;
|
|
|
-
|
|
|
- tempResult.PreCompNeg := preCompNegQ;
|
|
|
- end;
|
|
|
-
|
|
|
- result := tempResult;
|
|
|
-end;
|
|
|
-
|
|
|
-{ TWNafUtilities.TWNafCallback }
|
|
|
-
|
|
|
-constructor TWNafUtilities.TWNafCallback.Create(const p: IECPoint; width: Int32;
|
|
|
- includeNegated: Boolean);
|
|
|
-begin
|
|
|
- Inherited Create();
|
|
|
- Fm_p := p;
|
|
|
- Fm_width := width;
|
|
|
- Fm_includeNegated := includeNegated;
|
|
|
-end;
|
|
|
-
|
|
|
-function TWNafUtilities.TWNafCallback.Precompute(const existing: IPreCompInfo)
|
|
|
- : IPreCompInfo;
|
|
|
-var
|
|
|
- twiceP, isoTwiceP, last: IECPoint;
|
|
|
- c: IECCurve;
|
|
|
- PreComp, PreCompNeg, EMPTY_POINTS: TCryptoLibGenericArray<IECPoint>;
|
|
|
- tempRes, existingWNaf: IWNafPreCompInfo;
|
|
|
- reqPreCompLen, iniPreCompLen, curPreCompLen, pos: Int32;
|
|
|
- iso, iso2, iso3: IECFieldElement;
|
|
|
-begin
|
|
|
- EMPTY_POINTS := Nil;
|
|
|
- existingWNaf := existing as IWNafPreCompInfo;
|
|
|
-
|
|
|
- reqPreCompLen := 1 shl Max(0, Fm_width - 2);
|
|
|
-
|
|
|
- if (CheckExisting(existingWNaf, reqPreCompLen, Fm_includeNegated)) then
|
|
|
- begin
|
|
|
- result := existingWNaf;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- c := Fm_p.Curve;
|
|
|
-
|
|
|
- if (existingWNaf <> Nil) then
|
|
|
- begin
|
|
|
- PreComp := existingWNaf.PreComp;
|
|
|
- PreCompNeg := existingWNaf.PreCompNeg;
|
|
|
- twiceP := existingWNaf.Twice;
|
|
|
- end;
|
|
|
-
|
|
|
- iniPreCompLen := 0;
|
|
|
- if (PreComp = Nil) then
|
|
|
- begin
|
|
|
- PreComp := EMPTY_POINTS;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- iniPreCompLen := System.length(PreComp);
|
|
|
- end;
|
|
|
-
|
|
|
- if (iniPreCompLen < reqPreCompLen) then
|
|
|
- begin
|
|
|
- PreComp := TWNafUtilities.ResizeTable(PreComp, reqPreCompLen);
|
|
|
-
|
|
|
- if (reqPreCompLen = 1) then
|
|
|
- begin
|
|
|
- PreComp[0] := Fm_p.Normalize();
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- curPreCompLen := iniPreCompLen;
|
|
|
- if (curPreCompLen = 0) then
|
|
|
- begin
|
|
|
- PreComp[0] := Fm_p;
|
|
|
- curPreCompLen := 1;
|
|
|
- end;
|
|
|
-
|
|
|
- if (reqPreCompLen = 2) then
|
|
|
- begin
|
|
|
- PreComp[1] := Fm_p.threeTimes();
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- isoTwiceP := twiceP;
|
|
|
- last := PreComp[curPreCompLen - 1];
|
|
|
- if (isoTwiceP = Nil) then
|
|
|
- begin
|
|
|
- isoTwiceP := PreComp[0].Twice();
|
|
|
- twiceP := isoTwiceP;
|
|
|
- //
|
|
|
- // /*
|
|
|
- // * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
|
|
|
- // * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
|
|
|
- // * also requires scaling the initial point's X, Y coordinates, and reversing the
|
|
|
- // * isomorphism as part of the subsequent normalization.
|
|
|
- // *
|
|
|
- // * NOTE: The correctness of this optimization depends on:
|
|
|
- // * 1) additions do not use the curve's A, B coefficients.
|
|
|
- // * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
|
|
|
- // */
|
|
|
- if ((not(twiceP.IsInfinity)) and (TECAlgorithms.IsFpCurve(c)) and
|
|
|
- (c.FieldSize >= 64)) then
|
|
|
- begin
|
|
|
- case (c.CoordinateSystem) of
|
|
|
- TECCurveConstants.COORD_JACOBIAN,
|
|
|
- TECCurveConstants.COORD_JACOBIAN_CHUDNOVSKY,
|
|
|
- TECCurveConstants.COORD_JACOBIAN_MODIFIED:
|
|
|
-
|
|
|
- begin
|
|
|
- iso := twiceP.GetZCoord(0);
|
|
|
- isoTwiceP := c.CreatePoint(twiceP.XCoord.ToBigInteger,
|
|
|
- twiceP.YCoord.ToBigInteger());
|
|
|
-
|
|
|
- iso2 := iso.square();
|
|
|
- iso3 := iso2.Multiply(iso);
|
|
|
- last := last.scaleX(iso2).scaleY(iso3);
|
|
|
-
|
|
|
- if (iniPreCompLen = 0) then
|
|
|
- begin
|
|
|
- PreComp[0] := last;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- end;
|
|
|
-
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- while (curPreCompLen < reqPreCompLen) do
|
|
|
- begin
|
|
|
- // /*
|
|
|
- // * Compute the new ECPoints for the precomputation array. The values 1, 3,
|
|
|
- // * 5, ..., 2^(width-1)-1 times p are computed
|
|
|
- // */
|
|
|
- last := last.Add(isoTwiceP);
|
|
|
- PreComp[curPreCompLen] := last;
|
|
|
- System.Inc(curPreCompLen);
|
|
|
- end;
|
|
|
- end;
|
|
|
- //
|
|
|
- // /*
|
|
|
- // * Having oft-used operands in affine form makes operations faster.
|
|
|
- // */
|
|
|
- c.NormalizeAll(PreComp, iniPreCompLen,
|
|
|
- reqPreCompLen - iniPreCompLen, iso);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- if (Fm_includeNegated) then
|
|
|
- begin
|
|
|
-
|
|
|
- if (PreCompNeg = Nil) then
|
|
|
- begin
|
|
|
- pos := 0;
|
|
|
- System.SetLength(PreCompNeg, reqPreCompLen);
|
|
|
-
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- pos := System.length(PreCompNeg);
|
|
|
- if (pos < reqPreCompLen) then
|
|
|
- begin
|
|
|
- PreCompNeg := TWNafUtilities.ResizeTable(PreCompNeg, reqPreCompLen);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- while (pos < reqPreCompLen) do
|
|
|
- begin
|
|
|
- PreCompNeg[pos] := PreComp[pos].Negate();
|
|
|
- System.Inc(pos);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- tempRes := TWNafPreCompInfo.Create();
|
|
|
- tempRes.PreComp := PreComp;
|
|
|
- tempRes.PreCompNeg := PreCompNeg;
|
|
|
- tempRes.Twice := twiceP;
|
|
|
-
|
|
|
- result := tempRes;
|
|
|
-end;
|
|
|
-
|
|
|
end.
|