|
|
@@ -6,8 +6,15 @@
|
|
|
{ * 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 ClpWNafUtilities;
|
|
|
|
|
|
{$I ..\..\..\Include\CryptoLib.inc}
|
|
|
@@ -15,8 +22,17 @@ unit ClpWNafUtilities;
|
|
|
interface
|
|
|
|
|
|
uses
|
|
|
+ SysUtils,
|
|
|
+ Math,
|
|
|
+ ClpArrayUtilities,
|
|
|
+ ClpBitOperations,
|
|
|
ClpBigInteger,
|
|
|
ClpIECCore,
|
|
|
+ ClpECCurve,
|
|
|
+ ClpECCurveConstants,
|
|
|
+ ClpECAlgorithms,
|
|
|
+ ClpECPoint,
|
|
|
+ ClpIECFieldElement,
|
|
|
ClpIPreCompCallback,
|
|
|
ClpIPreCompInfo,
|
|
|
ClpIWNafPreCompInfo,
|
|
|
@@ -26,14 +42,62 @@ uses
|
|
|
type
|
|
|
TWNafUtilities = class sealed(TObject)
|
|
|
strict private
|
|
|
+ type
|
|
|
+ TConfigureBasepointCallback = class sealed(TInterfacedObject, IPreCompCallback)
|
|
|
+ strict private
|
|
|
+ FCurve: IECCurve;
|
|
|
+ FConfWidth: Int32;
|
|
|
+ public
|
|
|
+ constructor Create(const ACurve: IECCurve; AConfWidth: Int32);
|
|
|
+ function Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TMapPointCallback = class sealed(TInterfacedObject, IPreCompCallback)
|
|
|
+ strict private
|
|
|
+ FInfoP: IWNafPreCompInfo;
|
|
|
+ FIncludeNegated: Boolean;
|
|
|
+ FPointMap: IECPointMap;
|
|
|
+ public
|
|
|
+ constructor Create(const AInfoP: IWNafPreCompInfo; AIncludeNegated: Boolean;
|
|
|
+ const APointMap: IECPointMap);
|
|
|
+ function Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TPrecomputeCallback = class sealed(TInterfacedObject, IPreCompCallback)
|
|
|
+ strict private
|
|
|
+ FP: IECPoint;
|
|
|
+ FMinWidth: Int32;
|
|
|
+ FIncludeNegated: Boolean;
|
|
|
+ function CheckExisting(const AExistingWNaf: IWNafPreCompInfo; AWidth, AReqPreCompLen: Int32;
|
|
|
+ AIncludeNegated: Boolean): Boolean;
|
|
|
+ function CheckTable(const ATable: TCryptoLibGenericArray<IECPoint>; AReqLen: Int32): Boolean;
|
|
|
+ public
|
|
|
+ constructor Create(const AP: IECPoint; AMinWidth: Int32; AIncludeNegated: Boolean);
|
|
|
+ function Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TPrecomputeWithPointMapCallback = class sealed(TInterfacedObject, IPreCompCallback)
|
|
|
+ strict private
|
|
|
+ FPoint: IECPoint;
|
|
|
+ FPointMap: IECPointMap;
|
|
|
+ FFromWNaf: IWNafPreCompInfo;
|
|
|
+ FIncludeNegated: Boolean;
|
|
|
+ function CheckTable(const ATable: TCryptoLibGenericArray<IECPoint>; AReqLen: Int32): Boolean;
|
|
|
+ function CheckExisting(const AExistingWNaf: IWNafPreCompInfo; AWidth, AReqPreCompLen: Int32;
|
|
|
+ AIncludeNegated: Boolean): Boolean;
|
|
|
+ public
|
|
|
+ constructor Create(const APoint: IECPoint; const APointMap: IECPointMap;
|
|
|
+ const AFromWNaf: IWNafPreCompInfo; AIncludeNegated: Boolean);
|
|
|
+ function Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+ end;
|
|
|
+
|
|
|
class var
|
|
|
FDefaultWindowSizeCutoffs: TCryptoLibInt32Array;
|
|
|
class function GetWindowSize(ABits: Int32; const AWindowSizeCutoffs: TCryptoLibInt32Array;
|
|
|
AMaxWidth: Int32): Int32; overload; static;
|
|
|
- class function Trim(const AArray: TCryptoLibInt32Array; ALength: Int32): TCryptoLibInt32Array; static;
|
|
|
- class function TrimBytes(const AArray: TCryptoLibByteArray; ALength: Int32): TCryptoLibByteArray; static;
|
|
|
- class function ResizeTable(const AArray: TCryptoLibGenericArray<IECPoint>;
|
|
|
- ALength: Int32): TCryptoLibGenericArray<IECPoint>; static;
|
|
|
+ class function Trim(const AArray: TCryptoLibInt32Array; ALength: Int32): TCryptoLibInt32Array; overload; static;
|
|
|
+ class function Trim(const AArray: TCryptoLibByteArray; ALength: Int32): TCryptoLibByteArray; overload; static;
|
|
|
+ class function ResizeTable(const AArray: TCryptoLibGenericArray<IECPoint>; ALength: Int32): TCryptoLibGenericArray<IECPoint>; static;
|
|
|
public
|
|
|
const
|
|
|
PRECOMP_NAME = 'bc_wnaf';
|
|
|
@@ -59,33 +123,14 @@ type
|
|
|
|
|
|
implementation
|
|
|
|
|
|
-uses
|
|
|
- System.Math,
|
|
|
- ClpArrayUtilities,
|
|
|
- ClpBitOperations,
|
|
|
- ClpECCurve,
|
|
|
- ClpECCurveConstants,
|
|
|
- ClpECAlgorithms,
|
|
|
- ClpECPoint;
|
|
|
-
|
|
|
-type
|
|
|
- TConfigureBasepointCallback = class sealed(TInterfacedObject, IPreCompCallback)
|
|
|
- strict private
|
|
|
- FCurve: IECCurve;
|
|
|
- FConfWidth: Int32;
|
|
|
- public
|
|
|
- constructor Create(const ACurve: IECCurve; AConfWidth: Int32);
|
|
|
- function Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
- end;
|
|
|
-
|
|
|
-constructor TConfigureBasepointCallback.Create(const ACurve: IECCurve; AConfWidth: Int32);
|
|
|
+constructor TWNafUtilities.TConfigureBasepointCallback.Create(const ACurve: IECCurve; AConfWidth: Int32);
|
|
|
begin
|
|
|
Inherited Create;
|
|
|
FCurve := ACurve;
|
|
|
FConfWidth := AConfWidth;
|
|
|
end;
|
|
|
|
|
|
-function TConfigureBasepointCallback.Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+function TWNafUtilities.TConfigureBasepointCallback.Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
var
|
|
|
LExistingWNaf: IWNafPreCompInfo;
|
|
|
LResult: IWNafPreCompInfo;
|
|
|
@@ -100,7 +145,7 @@ begin
|
|
|
Exit;
|
|
|
end;
|
|
|
|
|
|
- LResult := TWNafPreCompInfo.Create as IWNafPreCompInfo;
|
|
|
+ LResult := TWNafPreCompInfo.Create;
|
|
|
LResult.PromotionCountdown := 0;
|
|
|
LResult.ConfWidth := FConfWidth;
|
|
|
|
|
|
@@ -115,6 +160,272 @@ begin
|
|
|
Result := LResult;
|
|
|
end;
|
|
|
|
|
|
+constructor TWNafUtilities.TMapPointCallback.Create(const AInfoP: IWNafPreCompInfo;
|
|
|
+ AIncludeNegated: Boolean; const APointMap: IECPointMap);
|
|
|
+begin
|
|
|
+ Inherited Create;
|
|
|
+ FInfoP := AInfoP;
|
|
|
+ FIncludeNegated := AIncludeNegated;
|
|
|
+ FPointMap := APointMap;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWNafUtilities.TMapPointCallback.Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+var
|
|
|
+ LResult: IWNafPreCompInfo;
|
|
|
+ LTwiceP: IECPoint;
|
|
|
+ LPreCompP, LPreCompQ, LPreCompNegQ: TCryptoLibGenericArray<IECPoint>;
|
|
|
+ LI: Int32;
|
|
|
+begin
|
|
|
+ LResult := TWNafPreCompInfo.Create;
|
|
|
+ LResult.ConfWidth := FInfoP.ConfWidth;
|
|
|
+
|
|
|
+ LTwiceP := FInfoP.Twice;
|
|
|
+ if LTwiceP <> nil then
|
|
|
+ LResult.Twice := FPointMap.Map(LTwiceP);
|
|
|
+
|
|
|
+ LPreCompP := FInfoP.PreComp;
|
|
|
+ System.SetLength(LPreCompQ, System.Length(LPreCompP));
|
|
|
+ for LI := 0 to System.Length(LPreCompP) - 1 do
|
|
|
+ LPreCompQ[LI] := FPointMap.Map(LPreCompP[LI]);
|
|
|
+ LResult.PreComp := LPreCompQ;
|
|
|
+ LResult.Width := FInfoP.Width;
|
|
|
+
|
|
|
+ if FIncludeNegated then
|
|
|
+ begin
|
|
|
+ System.SetLength(LPreCompNegQ, System.Length(LPreCompQ));
|
|
|
+ for LI := 0 to System.Length(LPreCompNegQ) - 1 do
|
|
|
+ LPreCompNegQ[LI] := LPreCompQ[LI].Negate();
|
|
|
+ LResult.PreCompNeg := LPreCompNegQ;
|
|
|
+ end;
|
|
|
+
|
|
|
+ Result := LResult;
|
|
|
+end;
|
|
|
+
|
|
|
+constructor TWNafUtilities.TPrecomputeCallback.Create(const AP: IECPoint; AMinWidth: Int32; AIncludeNegated: Boolean);
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ FP := AP;
|
|
|
+ FMinWidth := AMinWidth;
|
|
|
+ FIncludeNegated := AIncludeNegated;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWNafUtilities.TPrecomputeCallback.CheckTable(const ATable: TCryptoLibGenericArray<IECPoint>;
|
|
|
+ AReqLen: Int32): Boolean;
|
|
|
+begin
|
|
|
+ Result := (ATable <> nil) and (System.Length(ATable) >= AReqLen);
|
|
|
+end;
|
|
|
+
|
|
|
+function TWNafUtilities.TPrecomputeCallback.CheckExisting(const AExistingWNaf: IWNafPreCompInfo;
|
|
|
+ AWidth, AReqPreCompLen: Int32; AIncludeNegated: Boolean): Boolean;
|
|
|
+var
|
|
|
+ LConfWidth: Int32;
|
|
|
+begin
|
|
|
+ if AExistingWNaf = nil then
|
|
|
+ Exit(False);
|
|
|
+ LConfWidth := AExistingWNaf.ConfWidth;
|
|
|
+ Result := (AExistingWNaf.Width >= Math.Max(LConfWidth, AWidth)) and
|
|
|
+ CheckTable(AExistingWNaf.PreComp, AReqPreCompLen) and
|
|
|
+ (not AIncludeNegated or CheckTable(AExistingWNaf.PreCompNeg, AReqPreCompLen));
|
|
|
+end;
|
|
|
+
|
|
|
+function TWNafUtilities.TPrecomputeCallback.Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+var
|
|
|
+ LExistingWNaf: IWNafPreCompInfo;
|
|
|
+ LResultInfo: IWNafPreCompInfo;
|
|
|
+ LC: IECCurve;
|
|
|
+ LPreComp, LPreCompNeg: TCryptoLibGenericArray<IECPoint>;
|
|
|
+ LTwiceP: IECPoint;
|
|
|
+ LWidth, LReqPreCompLen, LIniPreCompLen, LCurPreCompLen, LPos: Int32;
|
|
|
+ LLast, LIsoTwiceP: IECPoint;
|
|
|
+ LIso, LIso2, LIso3: IECFieldElement;
|
|
|
+begin
|
|
|
+ if not Supports(AExisting, IWNafPreCompInfo, LExistingWNaf) then
|
|
|
+ LExistingWNaf := nil;
|
|
|
+
|
|
|
+ LWidth := Math.Max(2, Math.Min(TWNafUtilities.MAX_WIDTH, FMinWidth));
|
|
|
+ LReqPreCompLen := 1 shl (LWidth - 2);
|
|
|
+
|
|
|
+ if CheckExisting(LExistingWNaf, LWidth, LReqPreCompLen, FIncludeNegated) then
|
|
|
+ begin
|
|
|
+ LExistingWNaf.DecrementPromotionCountdown;
|
|
|
+ Result := LExistingWNaf;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+
|
|
|
+ LResultInfo := TWNafPreCompInfo.Create;
|
|
|
+ LC := FP.Curve;
|
|
|
+ LPreComp := nil;
|
|
|
+ LPreCompNeg := nil;
|
|
|
+ LTwiceP := nil;
|
|
|
+
|
|
|
+ if LExistingWNaf <> nil then
|
|
|
+ begin
|
|
|
+ LResultInfo.PromotionCountdown := LExistingWNaf.DecrementPromotionCountdown;
|
|
|
+ LResultInfo.ConfWidth := LExistingWNaf.ConfWidth;
|
|
|
+ LPreComp := LExistingWNaf.PreComp;
|
|
|
+ LPreCompNeg := LExistingWNaf.PreCompNeg;
|
|
|
+ LTwiceP := LExistingWNaf.Twice;
|
|
|
+ end;
|
|
|
+
|
|
|
+ LWidth := Math.Min(TWNafUtilities.MAX_WIDTH, Math.Max(LResultInfo.ConfWidth, LWidth));
|
|
|
+ LReqPreCompLen := 1 shl (LWidth - 2);
|
|
|
+
|
|
|
+ LIniPreCompLen := 0;
|
|
|
+ if LPreComp <> nil then
|
|
|
+ LIniPreCompLen := System.Length(LPreComp);
|
|
|
+
|
|
|
+ LIso := nil;
|
|
|
+ if LIniPreCompLen < LReqPreCompLen then
|
|
|
+ begin
|
|
|
+ LPreComp := TWNafUtilities.ResizeTable(LPreComp, LReqPreCompLen);
|
|
|
+
|
|
|
+ if LReqPreCompLen = 1 then
|
|
|
+ LPreComp[0] := FP.Normalize()
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ LCurPreCompLen := LIniPreCompLen;
|
|
|
+ if LCurPreCompLen = 0 then
|
|
|
+ begin
|
|
|
+ LPreComp[0] := FP;
|
|
|
+ LCurPreCompLen := 1;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if LReqPreCompLen = 2 then
|
|
|
+ LPreComp[1] := FP.ThreeTimes()
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ LLast := LPreComp[LCurPreCompLen - 1];
|
|
|
+ if LTwiceP = nil then
|
|
|
+ begin
|
|
|
+ LIsoTwiceP := LPreComp[0].Twice();
|
|
|
+ LTwiceP := LIsoTwiceP;
|
|
|
+ { Fp quasi-isomorphism: affine twiceP and scale last for cheaper additions }
|
|
|
+ if (not LIsoTwiceP.GetIsInfinity) and TECAlgorithms.IsFpCurve(LC) and
|
|
|
+ (LC.FieldSize >= 64) then
|
|
|
+ case LC.CoordinateSystem of
|
|
|
+ TECCurveConstants.COORD_JACOBIAN, TECCurveConstants.COORD_JACOBIAN_CHUDNOVSKY,
|
|
|
+ TECCurveConstants.COORD_JACOBIAN_MODIFIED:
|
|
|
+ begin
|
|
|
+ LIso := LIsoTwiceP.GetZCoord(0);
|
|
|
+ LIsoTwiceP := LC.CreatePoint(LIsoTwiceP.XCoord.ToBigInteger(),
|
|
|
+ LIsoTwiceP.YCoord.ToBigInteger());
|
|
|
+ LIso2 := LIso.Square();
|
|
|
+ LIso3 := LIso2.Multiply(LIso);
|
|
|
+ LLast := LLast.ScaleX(LIso2).ScaleY(LIso3);
|
|
|
+ if LIniPreCompLen = 0 then
|
|
|
+ LPreComp[0] := LLast;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ LIsoTwiceP := LTwiceP;
|
|
|
+ while LCurPreCompLen < LReqPreCompLen do
|
|
|
+ begin
|
|
|
+ LPreComp[LCurPreCompLen] := LLast.Add(LIsoTwiceP);
|
|
|
+ LLast := LPreComp[LCurPreCompLen];
|
|
|
+ Inc(LCurPreCompLen);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ LC.NormalizeAll(LPreComp, LIniPreCompLen, LReqPreCompLen - LIniPreCompLen, LIso);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if FIncludeNegated then
|
|
|
+ begin
|
|
|
+ if LPreCompNeg = nil then
|
|
|
+ LPos := 0
|
|
|
+ else
|
|
|
+ LPos := System.Length(LPreCompNeg);
|
|
|
+ if LPos < LReqPreCompLen then
|
|
|
+ begin
|
|
|
+ SetLength(LPreCompNeg, LReqPreCompLen);
|
|
|
+ while LPos < LReqPreCompLen do
|
|
|
+ begin
|
|
|
+ LPreCompNeg[LPos] := LPreComp[LPos].Negate();
|
|
|
+ Inc(LPos);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ LResultInfo.PreComp := LPreComp;
|
|
|
+ LResultInfo.PreCompNeg := LPreCompNeg;
|
|
|
+ LResultInfo.Twice := LTwiceP;
|
|
|
+ LResultInfo.Width := LWidth;
|
|
|
+ Result := LResultInfo;
|
|
|
+end;
|
|
|
+
|
|
|
+constructor TWNafUtilities.TPrecomputeWithPointMapCallback.Create(const APoint: IECPoint;
|
|
|
+ const APointMap: IECPointMap; const AFromWNaf: IWNafPreCompInfo; AIncludeNegated: Boolean);
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ FPoint := APoint;
|
|
|
+ FPointMap := APointMap;
|
|
|
+ FFromWNaf := AFromWNaf;
|
|
|
+ FIncludeNegated := AIncludeNegated;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWNafUtilities.TPrecomputeWithPointMapCallback.CheckTable(
|
|
|
+ const ATable: TCryptoLibGenericArray<IECPoint>; AReqLen: Int32): Boolean;
|
|
|
+begin
|
|
|
+ Result := (ATable <> nil) and (System.Length(ATable) >= AReqLen);
|
|
|
+end;
|
|
|
+
|
|
|
+function TWNafUtilities.TPrecomputeWithPointMapCallback.CheckExisting(
|
|
|
+ const AExistingWNaf: IWNafPreCompInfo; AWidth, AReqPreCompLen: Int32;
|
|
|
+ AIncludeNegated: Boolean): Boolean;
|
|
|
+begin
|
|
|
+ Result := (AExistingWNaf <> nil) and (AExistingWNaf.Width >= AWidth) and
|
|
|
+ CheckTable(AExistingWNaf.PreComp, AReqPreCompLen) and
|
|
|
+ (not AIncludeNegated or CheckTable(AExistingWNaf.PreCompNeg, AReqPreCompLen));
|
|
|
+end;
|
|
|
+
|
|
|
+function TWNafUtilities.TPrecomputeWithPointMapCallback.Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
+var
|
|
|
+ LExistingWNaf: IWNafPreCompInfo;
|
|
|
+ LResultInfo: IWNafPreCompInfo;
|
|
|
+ LWidth, LReqPreCompLen, LI: Int32;
|
|
|
+ LPreCompFrom, LPreComp, LPreCompNeg: TCryptoLibGenericArray<IECPoint>;
|
|
|
+ LTwiceFrom: IECPoint;
|
|
|
+begin
|
|
|
+ if not Supports(AExisting, IWNafPreCompInfo, LExistingWNaf) then
|
|
|
+ LExistingWNaf := nil;
|
|
|
+
|
|
|
+ LWidth := FFromWNaf.Width;
|
|
|
+ LReqPreCompLen := System.Length(FFromWNaf.PreComp);
|
|
|
+
|
|
|
+ if CheckExisting(LExistingWNaf, LWidth, LReqPreCompLen, FIncludeNegated) then
|
|
|
+ begin
|
|
|
+ LExistingWNaf.DecrementPromotionCountdown;
|
|
|
+ Result := LExistingWNaf;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+
|
|
|
+ LResultInfo := TWNafPreCompInfo.Create;
|
|
|
+ LResultInfo.PromotionCountdown := FFromWNaf.PromotionCountdown;
|
|
|
+
|
|
|
+ LTwiceFrom := FFromWNaf.Twice;
|
|
|
+ if LTwiceFrom <> nil then
|
|
|
+ LResultInfo.Twice := FPointMap.Map(LTwiceFrom);
|
|
|
+
|
|
|
+ LPreCompFrom := FFromWNaf.PreComp;
|
|
|
+ System.SetLength(LPreComp, System.Length(LPreCompFrom));
|
|
|
+ for LI := 0 to System.High(LPreCompFrom) do
|
|
|
+ LPreComp[LI] := FPointMap.Map(LPreCompFrom[LI]);
|
|
|
+ LResultInfo.PreComp := LPreComp;
|
|
|
+ LResultInfo.Width := LWidth;
|
|
|
+
|
|
|
+ if FIncludeNegated then
|
|
|
+ begin
|
|
|
+ System.SetLength(LPreCompNeg, System.Length(LPreComp));
|
|
|
+ for LI := 0 to System.High(LPreComp) do
|
|
|
+ LPreCompNeg[LI] := LPreComp[LI].Negate();
|
|
|
+ LResultInfo.PreCompNeg := LPreCompNeg;
|
|
|
+ end;
|
|
|
+
|
|
|
+ Result := LResultInfo;
|
|
|
+end;
|
|
|
+
|
|
|
{ TWNafUtilities }
|
|
|
|
|
|
class procedure TWNafUtilities.ConfigureBasepoint(const AP: IECPoint);
|
|
|
@@ -134,9 +445,9 @@ begin
|
|
|
else
|
|
|
LBits := LOrder.BitLength;
|
|
|
|
|
|
- LConfWidth := System.Math.Min(MAX_WIDTH, GetWindowSize(LBits) + 3);
|
|
|
+ LConfWidth := Math.Min(MAX_WIDTH, GetWindowSize(LBits) + 3);
|
|
|
LC.Precompute(AP, PRECOMP_NAME,
|
|
|
- TConfigureBasepointCallback.Create(LC, LConfWidth) as IPreCompCallback);
|
|
|
+ TWNafUtilities.TConfigureBasepointCallback.Create(LC, LConfWidth) as IPreCompCallback);
|
|
|
end;
|
|
|
|
|
|
class function TWNafUtilities.GetWindowSize(ABits: Int32): Int32;
|
|
|
@@ -166,7 +477,7 @@ begin
|
|
|
LW := 0;
|
|
|
while (LW < System.Length(AWindowSizeCutoffs)) and (ABits >= AWindowSizeCutoffs[LW]) do
|
|
|
Inc(LW);
|
|
|
- Result := System.Math.Max(2, System.Math.Min(AMaxWidth, LW + 2));
|
|
|
+ Result := Math.Max(2, Math.Min(AMaxWidth, LW + 2));
|
|
|
end;
|
|
|
|
|
|
class function TWNafUtilities.Trim(const AArray: TCryptoLibInt32Array;
|
|
|
@@ -179,6 +490,16 @@ begin
|
|
|
Result[LI] := AArray[LI];
|
|
|
end;
|
|
|
|
|
|
+class function TWNafUtilities.Trim(const AArray: TCryptoLibByteArray;
|
|
|
+ ALength: Int32): TCryptoLibByteArray;
|
|
|
+var
|
|
|
+ LI: Int32;
|
|
|
+begin
|
|
|
+ System.SetLength(Result, ALength);
|
|
|
+ for LI := 0 to ALength - 1 do
|
|
|
+ Result[LI] := AArray[LI];
|
|
|
+end;
|
|
|
+
|
|
|
class function TWNafUtilities.ResizeTable(const AArray: TCryptoLibGenericArray<IECPoint>;
|
|
|
ALength: Int32): TCryptoLibGenericArray<IECPoint>;
|
|
|
var
|
|
|
@@ -187,22 +508,12 @@ begin
|
|
|
System.SetLength(Result, ALength);
|
|
|
if AArray <> nil then
|
|
|
begin
|
|
|
- LLen := System.Math.Min(System.Length(AArray), ALength);
|
|
|
+ LLen := Math.Min(System.Length(AArray), ALength);
|
|
|
for LI := 0 to LLen - 1 do
|
|
|
Result[LI] := AArray[LI];
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-class function TWNafUtilities.TrimBytes(const AArray: TCryptoLibByteArray;
|
|
|
- ALength: Int32): TCryptoLibByteArray;
|
|
|
-var
|
|
|
- LI: Int32;
|
|
|
-begin
|
|
|
- System.SetLength(Result, ALength);
|
|
|
- for LI := 0 to ALength - 1 do
|
|
|
- Result[LI] := AArray[LI];
|
|
|
-end;
|
|
|
-
|
|
|
class function TWNafUtilities.GenerateNaf(const AK: TBigInteger): TCryptoLibByteArray;
|
|
|
var
|
|
|
L3k, LDiff: TBigInteger;
|
|
|
@@ -218,7 +529,7 @@ begin
|
|
|
LDigits := L3k.BitLength - 1;
|
|
|
System.SetLength(Result, LDigits);
|
|
|
TArrayUtilities.Fill<Byte>(Result, 0, LDigits, Byte(0));
|
|
|
- LDiff := L3k.Xor(AK);
|
|
|
+ LDiff := L3k.&Xor(AK);
|
|
|
LI := 1;
|
|
|
while LI < LDigits do
|
|
|
begin
|
|
|
@@ -287,7 +598,7 @@ begin
|
|
|
LPos := AWidth;
|
|
|
end;
|
|
|
if System.Length(Result) > LLength then
|
|
|
- Result := TrimBytes(Result, LLength);
|
|
|
+ Result := Trim(Result, LLength);
|
|
|
end;
|
|
|
|
|
|
class function TWNafUtilities.GenerateJsf(const AG, AH: TBigInteger): TCryptoLibByteArray;
|
|
|
@@ -296,7 +607,7 @@ var
|
|
|
LJsf: TCryptoLibByteArray;
|
|
|
LK0, LK1: TBigInteger;
|
|
|
begin
|
|
|
- LDigits := System.Math.Max(AG.BitLength, AH.BitLength) + 1;
|
|
|
+ LDigits := Math.Max(AG.BitLength, AH.BitLength) + 1;
|
|
|
System.SetLength(LJsf, LDigits);
|
|
|
LK0 := AG;
|
|
|
LK1 := AH;
|
|
|
@@ -306,8 +617,8 @@ begin
|
|
|
LOffset := 0;
|
|
|
while ((Ld0 or Ld1) <> 0) or (LK0.BitLength > LOffset) or (LK1.BitLength > LOffset) do
|
|
|
begin
|
|
|
- Ln0 := (Int32(UInt32(LK0.GetInt32Value) shr LOffset) + Ld0) and 7;
|
|
|
- Ln1 := (Int32(UInt32(LK1.GetInt32Value) shr LOffset) + Ld1) and 7;
|
|
|
+ Ln0 := (Int32(UInt32(LK0.Int32Value) shr LOffset) + Ld0) and 7;
|
|
|
+ Ln1 := (Int32(UInt32(LK1.Int32Value) shr LOffset) + Ld1) and 7;
|
|
|
Lu0 := Ln0 and 1;
|
|
|
if Lu0 <> 0 then
|
|
|
begin
|
|
|
@@ -337,7 +648,7 @@ begin
|
|
|
Inc(LJ);
|
|
|
end;
|
|
|
if System.Length(LJsf) > LJ then
|
|
|
- Result := TrimBytes(LJsf, LJ)
|
|
|
+ Result := Trim(LJsf, LJ)
|
|
|
else
|
|
|
Result := LJsf;
|
|
|
end;
|
|
|
@@ -349,7 +660,7 @@ begin
|
|
|
if AK.SignValue = 0 then
|
|
|
Exit(0);
|
|
|
L3k := AK.ShiftLeft(1).Add(AK);
|
|
|
- LDiff := L3k.Xor(AK);
|
|
|
+ LDiff := L3k.&Xor(AK);
|
|
|
Result := LDiff.BitCount;
|
|
|
end;
|
|
|
|
|
|
@@ -384,7 +695,7 @@ begin
|
|
|
L3k := AK.ShiftLeft(1).Add(AK);
|
|
|
LBits := L3k.BitLength;
|
|
|
System.SetLength(Result, TBitOperations.Asr32(LBits, 1));
|
|
|
- LDiff := L3k.Xor(AK);
|
|
|
+ LDiff := L3k.&Xor(AK);
|
|
|
LHighBit := LBits - 1;
|
|
|
LLength := 0;
|
|
|
LZeroes := 0;
|
|
|
@@ -469,270 +780,16 @@ begin
|
|
|
Result := Trim(Result, LLength);
|
|
|
end;
|
|
|
|
|
|
-type
|
|
|
- TPrecomputeCallback = class sealed(TInterfacedObject, IPreCompCallback)
|
|
|
- strict private
|
|
|
- FP: IECPoint;
|
|
|
- FMinWidth: Int32;
|
|
|
- FIncludeNegated: Boolean;
|
|
|
- function CheckExisting(const AExistingWNaf: IWNafPreCompInfo; AWidth, AReqPreCompLen: Int32;
|
|
|
- AIncludeNegated: Boolean): Boolean;
|
|
|
- function CheckTable(const ATable: TCryptoLibGenericArray<IECPoint>; AReqLen: Int32): Boolean;
|
|
|
- public
|
|
|
- constructor Create(const AP: IECPoint; AMinWidth: Int32; AIncludeNegated: Boolean);
|
|
|
- function Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
- end;
|
|
|
-
|
|
|
-constructor TPrecomputeCallback.Create(const AP: IECPoint; AMinWidth: Int32; AIncludeNegated: Boolean);
|
|
|
-begin
|
|
|
- inherited Create;
|
|
|
- FP := AP;
|
|
|
- FMinWidth := AMinWidth;
|
|
|
- FIncludeNegated := AIncludeNegated;
|
|
|
-end;
|
|
|
-
|
|
|
-function TPrecomputeCallback.CheckTable(const ATable: TCryptoLibGenericArray<IECPoint>;
|
|
|
- AReqLen: Int32): Boolean;
|
|
|
-begin
|
|
|
- Result := (ATable <> nil) and (System.Length(ATable) >= AReqLen);
|
|
|
-end;
|
|
|
-
|
|
|
-function TPrecomputeCallback.CheckExisting(const AExistingWNaf: IWNafPreCompInfo;
|
|
|
- AWidth, AReqPreCompLen: Int32; AIncludeNegated: Boolean): Boolean;
|
|
|
-var
|
|
|
- LConfWidth: Int32;
|
|
|
-begin
|
|
|
- if AExistingWNaf = nil then
|
|
|
- Exit(False);
|
|
|
- LConfWidth := AExistingWNaf.ConfWidth;
|
|
|
- Result := (AExistingWNaf.Width >= System.Math.Max(LConfWidth, AWidth)) and
|
|
|
- CheckTable(AExistingWNaf.PreComp, AReqPreCompLen) and
|
|
|
- (not AIncludeNegated or CheckTable(AExistingWNaf.PreCompNeg, AReqPreCompLen));
|
|
|
-end;
|
|
|
-
|
|
|
-function TPrecomputeCallback.Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
-var
|
|
|
- LExistingWNaf: IWNafPreCompInfo;
|
|
|
- LResultInfo: IWNafPreCompInfo;
|
|
|
- LC: IECCurve;
|
|
|
- LPreComp, LPreCompNeg: TCryptoLibGenericArray<IECPoint>;
|
|
|
- LTwiceP: IECPoint;
|
|
|
- LWidth, LReqPreCompLen, LIniPreCompLen, LCurPreCompLen, LPos: Int32;
|
|
|
- LLast, LIsoTwiceP: IECPoint;
|
|
|
- LIso, LIso2, LIso3: IECFieldElement;
|
|
|
-begin
|
|
|
- if not Supports(AExisting, IWNafPreCompInfo, LExistingWNaf) then
|
|
|
- LExistingWNaf := nil;
|
|
|
-
|
|
|
- LWidth := System.Math.Max(2, System.Math.Min(TWNafUtilities.MAX_WIDTH, FMinWidth));
|
|
|
- LReqPreCompLen := 1 shl (LWidth - 2);
|
|
|
-
|
|
|
- if CheckExisting(LExistingWNaf, LWidth, LReqPreCompLen, FIncludeNegated) then
|
|
|
- begin
|
|
|
- LExistingWNaf.DecrementPromotionCountdown;
|
|
|
- Result := LExistingWNaf;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- LResultInfo := TWNafPreCompInfo.Create as IWNafPreCompInfo;
|
|
|
- LC := FP.Curve;
|
|
|
- LPreComp := nil;
|
|
|
- LPreCompNeg := nil;
|
|
|
- LTwiceP := nil;
|
|
|
-
|
|
|
- if LExistingWNaf <> nil then
|
|
|
- begin
|
|
|
- LResultInfo.PromotionCountdown := LExistingWNaf.DecrementPromotionCountdown;
|
|
|
- LResultInfo.ConfWidth := LExistingWNaf.ConfWidth;
|
|
|
- LPreComp := LExistingWNaf.PreComp;
|
|
|
- LPreCompNeg := LExistingWNaf.PreCompNeg;
|
|
|
- LTwiceP := LExistingWNaf.Twice;
|
|
|
- end;
|
|
|
-
|
|
|
- LWidth := System.Math.Min(TWNafUtilities.MAX_WIDTH, System.Math.Max(LResultInfo.ConfWidth, LWidth));
|
|
|
- LReqPreCompLen := 1 shl (LWidth - 2);
|
|
|
-
|
|
|
- LIniPreCompLen := 0;
|
|
|
- if LPreComp <> nil then
|
|
|
- LIniPreCompLen := System.Length(LPreComp);
|
|
|
-
|
|
|
- LIso := nil;
|
|
|
- if LIniPreCompLen < LReqPreCompLen then
|
|
|
- begin
|
|
|
- LPreComp := TWNafUtilities.ResizeTable(LPreComp, LReqPreCompLen);
|
|
|
-
|
|
|
- if LReqPreCompLen = 1 then
|
|
|
- LPreComp[0] := FP.Normalize()
|
|
|
- else
|
|
|
- begin
|
|
|
- LCurPreCompLen := LIniPreCompLen;
|
|
|
- if LCurPreCompLen = 0 then
|
|
|
- begin
|
|
|
- LPreComp[0] := FP;
|
|
|
- LCurPreCompLen := 1;
|
|
|
- end;
|
|
|
-
|
|
|
- if LReqPreCompLen = 2 then
|
|
|
- LPreComp[1] := FP.ThreeTimes()
|
|
|
- else
|
|
|
- begin
|
|
|
- LLast := LPreComp[LCurPreCompLen - 1];
|
|
|
- if LTwiceP = nil then
|
|
|
- begin
|
|
|
- LIsoTwiceP := LPreComp[0].Twice();
|
|
|
- LTwiceP := LIsoTwiceP;
|
|
|
- { Fp quasi-isomorphism: affine twiceP and scale last for cheaper additions }
|
|
|
- if (not LIsoTwiceP.GetIsInfinity) and TECAlgorithms.IsFpCurve(LC) and
|
|
|
- (LC.FieldSize >= 64) then
|
|
|
- case LC.CoordinateSystem of
|
|
|
- TECCurveConstants.COORD_JACOBIAN, TECCurveConstants.COORD_JACOBIAN_CHUDNOVSKY,
|
|
|
- TECCurveConstants.COORD_JACOBIAN_MODIFIED:
|
|
|
- begin
|
|
|
- LIso := LIsoTwiceP.GetZCoord(0);
|
|
|
- LIsoTwiceP := LC.CreatePoint(LIsoTwiceP.XCoord.ToBigInteger(),
|
|
|
- LIsoTwiceP.YCoord.ToBigInteger());
|
|
|
- LIso2 := LIso.Square();
|
|
|
- LIso3 := LIso2.Multiply(LIso);
|
|
|
- LLast := LLast.ScaleX(LIso2).ScaleY(LIso3);
|
|
|
- if LIniPreCompLen = 0 then
|
|
|
- LPreComp[0] := LLast;
|
|
|
- end;
|
|
|
- end;
|
|
|
- end
|
|
|
- else
|
|
|
- LIsoTwiceP := LTwiceP;
|
|
|
- while LCurPreCompLen < LReqPreCompLen do
|
|
|
- begin
|
|
|
- LPreComp[LCurPreCompLen] := LLast.Add(LIsoTwiceP);
|
|
|
- LLast := LPreComp[LCurPreCompLen];
|
|
|
- Inc(LCurPreCompLen);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- LC.NormalizeAll(LPreComp, LIniPreCompLen, LReqPreCompLen - LIniPreCompLen, LIso);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- if FIncludeNegated then
|
|
|
- begin
|
|
|
- if LPreCompNeg = nil then
|
|
|
- LPos := 0
|
|
|
- else
|
|
|
- LPos := System.Length(LPreCompNeg);
|
|
|
- if LPos < LReqPreCompLen then
|
|
|
- begin
|
|
|
- SetLength(LPreCompNeg, LReqPreCompLen);
|
|
|
- while LPos < LReqPreCompLen do
|
|
|
- begin
|
|
|
- LPreCompNeg[LPos] := LPreComp[LPos].Negate();
|
|
|
- Inc(LPos);
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- LResultInfo.PreComp := LPreComp;
|
|
|
- LResultInfo.PreCompNeg := LPreCompNeg;
|
|
|
- LResultInfo.Twice := LTwiceP;
|
|
|
- LResultInfo.Width := LWidth;
|
|
|
- Result := LResultInfo;
|
|
|
-end;
|
|
|
-
|
|
|
-type
|
|
|
- TPrecomputeWithPointMapCallback = class sealed(TInterfacedObject, IPreCompCallback)
|
|
|
- strict private
|
|
|
- FPoint: IECPoint;
|
|
|
- FPointMap: IECPointMap;
|
|
|
- FFromWNaf: IWNafPreCompInfo;
|
|
|
- FIncludeNegated: Boolean;
|
|
|
- function CheckTable(const ATable: TCryptoLibGenericArray<IECPoint>; AReqLen: Int32): Boolean;
|
|
|
- function CheckExisting(const AExistingWNaf: IWNafPreCompInfo; AWidth, AReqPreCompLen: Int32;
|
|
|
- AIncludeNegated: Boolean): Boolean;
|
|
|
- public
|
|
|
- constructor Create(const APoint: IECPoint; const APointMap: IECPointMap;
|
|
|
- const AFromWNaf: IWNafPreCompInfo; AIncludeNegated: Boolean);
|
|
|
- function Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
- end;
|
|
|
-
|
|
|
-constructor TPrecomputeWithPointMapCallback.Create(const APoint: IECPoint;
|
|
|
- const APointMap: IECPointMap; const AFromWNaf: IWNafPreCompInfo; AIncludeNegated: Boolean);
|
|
|
-begin
|
|
|
- inherited Create;
|
|
|
- FPoint := APoint;
|
|
|
- FPointMap := APointMap;
|
|
|
- FFromWNaf := AFromWNaf;
|
|
|
- FIncludeNegated := AIncludeNegated;
|
|
|
-end;
|
|
|
-
|
|
|
-function TPrecomputeWithPointMapCallback.CheckTable(
|
|
|
- const ATable: TCryptoLibGenericArray<IECPoint>; AReqLen: Int32): Boolean;
|
|
|
-begin
|
|
|
- Result := (ATable <> nil) and (System.Length(ATable) >= AReqLen);
|
|
|
-end;
|
|
|
-
|
|
|
-function TPrecomputeWithPointMapCallback.CheckExisting(
|
|
|
- const AExistingWNaf: IWNafPreCompInfo; AWidth, AReqPreCompLen: Int32;
|
|
|
- AIncludeNegated: Boolean): Boolean;
|
|
|
-begin
|
|
|
- Result := (AExistingWNaf <> nil) and (AExistingWNaf.Width >= AWidth) and
|
|
|
- CheckTable(AExistingWNaf.PreComp, AReqPreCompLen) and
|
|
|
- (not AIncludeNegated or CheckTable(AExistingWNaf.PreCompNeg, AReqPreCompLen));
|
|
|
-end;
|
|
|
-
|
|
|
-function TPrecomputeWithPointMapCallback.Precompute(const AExisting: IPreCompInfo): IPreCompInfo;
|
|
|
-var
|
|
|
- LExistingWNaf: IWNafPreCompInfo;
|
|
|
- LResultInfo: IWNafPreCompInfo;
|
|
|
- LWidth, LReqPreCompLen, LI: Int32;
|
|
|
- LPreCompFrom, LPreComp, LPreCompNeg: TCryptoLibGenericArray<IECPoint>;
|
|
|
- LTwiceFrom: IECPoint;
|
|
|
-begin
|
|
|
- if not Supports(AExisting, IWNafPreCompInfo, LExistingWNaf) then
|
|
|
- LExistingWNaf := nil;
|
|
|
-
|
|
|
- LWidth := FFromWNaf.Width;
|
|
|
- LReqPreCompLen := System.Length(FFromWNaf.PreComp);
|
|
|
-
|
|
|
- if CheckExisting(LExistingWNaf, LWidth, LReqPreCompLen, FIncludeNegated) then
|
|
|
- begin
|
|
|
- LExistingWNaf.DecrementPromotionCountdown;
|
|
|
- Result := LExistingWNaf;
|
|
|
- Exit;
|
|
|
- end;
|
|
|
-
|
|
|
- LResultInfo := TWNafPreCompInfo.Create as IWNafPreCompInfo;
|
|
|
- LResultInfo.PromotionCountdown := FFromWNaf.PromotionCountdown;
|
|
|
-
|
|
|
- LTwiceFrom := FFromWNaf.Twice;
|
|
|
- if LTwiceFrom <> nil then
|
|
|
- LResultInfo.Twice := FPointMap.Map(LTwiceFrom);
|
|
|
-
|
|
|
- LPreCompFrom := FFromWNaf.PreComp;
|
|
|
- System.SetLength(LPreComp, System.Length(LPreCompFrom));
|
|
|
- for LI := 0 to System.High(LPreCompFrom) do
|
|
|
- LPreComp[LI] := FPointMap.Map(LPreCompFrom[LI]);
|
|
|
- LResultInfo.PreComp := LPreComp;
|
|
|
- LResultInfo.Width := LWidth;
|
|
|
-
|
|
|
- if FIncludeNegated then
|
|
|
- begin
|
|
|
- System.SetLength(LPreCompNeg, System.Length(LPreComp));
|
|
|
- for LI := 0 to System.High(LPreComp) do
|
|
|
- LPreCompNeg[LI] := LPreComp[LI].Negate();
|
|
|
- LResultInfo.PreCompNeg := LPreCompNeg;
|
|
|
- end;
|
|
|
-
|
|
|
- Result := LResultInfo;
|
|
|
-end;
|
|
|
-
|
|
|
class function TWNafUtilities.PrecomputeWithPointMap(const AP: IECPoint;
|
|
|
const APointMap: IECPointMap; const AFromWNaf: IWNafPreCompInfo;
|
|
|
AIncludeNegated: Boolean): IWNafPreCompInfo;
|
|
|
var
|
|
|
LResult: IPreCompInfo;
|
|
|
+ LPreCompCallback: IPreCompCallback;
|
|
|
LWNaf: IWNafPreCompInfo;
|
|
|
begin
|
|
|
- LResult := AP.Curve.Precompute(AP, PRECOMP_NAME,
|
|
|
- TPrecomputeWithPointMapCallback.Create(AP, APointMap, AFromWNaf, AIncludeNegated) as IPreCompCallback);
|
|
|
+ LPreCompCallback := TWNafUtilities.TPrecomputeWithPointMapCallback.Create(AP, APointMap, AFromWNaf, AIncludeNegated);
|
|
|
+ LResult := AP.Curve.Precompute(AP, PRECOMP_NAME, LPreCompCallback);
|
|
|
if not Supports(LResult, IWNafPreCompInfo, LWNaf) then
|
|
|
raise EInvalidCastCryptoLibException.Create('Expected IWNafPreCompInfo');
|
|
|
Result := LWNaf;
|
|
|
@@ -742,10 +799,11 @@ class function TWNafUtilities.Precompute(const AP: IECPoint; AMinWidth: Int32;
|
|
|
AIncludeNegated: Boolean): IWNafPreCompInfo;
|
|
|
var
|
|
|
LResult: IPreCompInfo;
|
|
|
+ LPreCompCallback: IPreCompCallback;
|
|
|
LWNaf: IWNafPreCompInfo;
|
|
|
begin
|
|
|
- LResult := AP.Curve.Precompute(AP, PRECOMP_NAME,
|
|
|
- TPrecomputeCallback.Create(AP, AMinWidth, AIncludeNegated) as IPreCompCallback);
|
|
|
+ LPreCompCallback := TWNafUtilities.TPrecomputeCallback.Create(AP, AMinWidth, AIncludeNegated);
|
|
|
+ LResult := AP.Curve.Precompute(AP, PRECOMP_NAME, LPreCompCallback);
|
|
|
if not Supports(LResult, IWNafPreCompInfo, LWNaf) then
|
|
|
raise EInvalidCastCryptoLibException.Create('Expected IWNafPreCompInfo');
|
|
|
Result := LWNaf;
|